原创: EDI-VOID 合天智汇
0x00 shellcode编写
首先shellcode的编写可以用纯汇编也可以用c ,其两者难易程度可想而知,还是抱住VS的大腿,不过这其中要注意一些代码格式和编译选项,以确保生成的shellcode是地址无关的
比如像如下代码都会被编译器优化,编译器会把字符串放在常量区,以下代码在vc6能通过,vs2017这些新版本的不能通过,新版本的语意更严谨。
char*arr = "test";
实际上是constchar*arr = "test";
Vc6中反汇编代码如下
可以看到字符串指针是一个固定的地址,在前面加上const关键字后会发现生成的代码是一样的,可见旧版本的编译器很善解人意,把你不严谨的代码改了
但是如果以以下的形式写的话,就成了地址无关的代码
charcmd[] = { 'c','a','l','c','\x00'};
这样写的需要我们在数组末尾手动添加截断字符
字符串的绝对地址引用问题解决了,下一个就是函数的调用,是dll的加载基址相关的,不同的操作系统某个dll的加载基址不一样,就需要动态定位,需要得到别的api的地址的话,首先我们需要得到dll的基址,可以通过进程PEB结构中的成员来遍历,遍历到kernel32.dll以后再遍历到GetProcAddress函数的地址和LoadLibrary的地址就万事大吉了,别的函数只需要这两个函数来获取了
首先获取PEB结构可以直接调用winternl.h里的一个宏
_PEB*peb = NtCurrentTeb()->ProcessEnvironmentBlock;
查看其宏定义看似调用了函数,查看反汇编代码发现实则是地址无关的代码
mov eax,dword ptr fs:[00000018h]
mov ecx,dword ptr [eax 30h]
也可以参照teb的结构自己来实现一个GetPeb函数让指令使用更少的字节
fs:[0x18]处是一个指向TEB自身的指针,TEB结构0x30处是PEB指针