0x000 前言
近几年大家都喜欢用CS来进行后渗透,所以对于ShellCode大家应该不会陌生。
但是可能很多人并不懂CS它的功能是什么,CS生成的ShellCode是一段下载者。
主要功能为下载becon.dll,然后内存加载,我们所用的相关功能都在becon里。
ShellCode可能采用汇编或VC编写后转成机器码提取关键机器码,优势在于体积小
体积小就可以直接结合漏洞使用,什么Word文档、MS17010溢出、IE漏洞挂马等
都可以直接结合CS来使用,直接CS上线,而不是非要先做其它操作再植入CS。
网上关于汇编或VC编写ShellCode的文章很多,但是.NET的"ShellCode"很少见
本文将教大家如何用操作码实现.NET版"ShellCode"的编写。
0x001 指令、操作码、字节码
在正式开始前,先给大家科普一下指令、操作码、机器码等的区别
指令: 命令cpu干什么,是由操作码字段和地址码字段(操作数字段)组成
操作码(Opcode): 就是执行某种操作的命令代码
BYTECODE(字节码):与机器代码相同,除了它主要由基于软件的解释器(如Java或CLR)使用
程序集:有两个“程序集” – 一个汇编程序是一系列的助记符和操作数,它们被馈送到“汇编程序”,
“汇编程序”将助记符和操作数“汇编成可执行的机器代码”.可选地,“链接器”链接组件并生成可执行文件.
CLR语言:(.NET语言)中的第二个“程序集”是一系列CLR代码,其中注入了元数据信息,可执行代码库,但不能直接执行.
0x002 Payload ShellCode
机器码(溢出常用的ShellCode): 就是指令的二进制代码(包括操作码和地址码),功能打开和关闭计算机中的开关的数字序列,以执行某些工作 – 例如增加数字,分支,乘法等等.这是纯机器特有的,由处理器的实现者.
K8理解的ShellCode是子弹,用枪发射(好比处理器执行); 无论你用的是哪种子弹(ShellCode),都是用枪来射(处理器执行)。
Payload: K8的理解是弹药,弹药可装填到弹壳里用,也可直接点然,也可圈起来当成炮仗点燃,但是弹药不能直接被枪发射。
PS:发现很多搞安全的对很多概念搞混,如很多文章常把payload和shellcode混为一谈
看了以上释义,您应该了解明显shellcode只是payload中的一种了,不可能属于同一个。
很多人把操作码误解为ShellCode还可以理解,起码长得像还有点类似,但真不是。
不要看到二进制、16进制或者byte数组就说是shellcode,长得像人都不定是人呢。
0x003 .NET函数代码
.NET包含多种语言,这里我使用C#的代码做为例子
public int Add(int x, int y)
{
x = x * y;
return x + y;
}
0x003 反汇编得到IL指令
指令速查表:https://www.jb51.net/article/86802.htm
IL语言,可理解为.NET的汇编,无论你使用的是C#还是VB.NET或者F#开发功能,都可以将其反编译成IL代码。使用ildasm.exe工具反编译,可以看到IL代码和汇编差不多,可能是常用.NET吧,感觉比汇编简单好多。
// Method begins at RVA 0x2170
// Code size 9 (0x9)
.maxstack 8
IL_0000: /* 03 | */ ldarg.1
IL_0001: /* 04 | */ ldarg.2
IL_0002: /* 5A | */ mul
IL_0003: /* 10 | 01 */ starg.s x
IL_0005: /* 03 | */ ldarg.1
IL_0006: /* 04 | */ ldarg.2
IL_0007: /* 58 | */ add
IL_0008: /* 2A | */ ret
} // end of method MethodBodyDemo::Add
0x004 IL指令转.NET操作码
如同VC反汇编提取机器码一样,我们将对应16进制复制出来,然后再对比指令速查表提取关键操作码
0x02,0x03,0x5A,0x10,0x00,0x02,0x03,0x58,0x2A
0x005 操作码加载
private static Func<int, int, int> LoadByteAssmbly(byte[] bytes)
{
var asmName = new AssemblyName("DynamicAssembly");
var asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);
var module = asmBuilder.DefineDynamicModule("DynamicModule");
var typeBuilder = module.DefineType("DynamicType");
var method = typeBuilder.DefineMethod("DynamicMethod",
MethodAttributes.Public | MethodAttributes.Static,
typeof(int),
new[] { typeof(int), typeof(int) });
method.CreateMethodBody(bytes, bytes.Length);
var type = typeBuilder.CreateType();
return (Func<int, int, int>)type.GetMethod("DynamicMethod").CreateDelegate(typeof(Func<int, int, int>));
}