堆溢出利用的精髓是DWORD SHOOT的利用,精准是DWORD SHOOT的优点,但是“火力不足”
常用的狙击目标(XP SP1之前)
-
内存变量(比如改了后就可以绕过身份验证)
-
代码逻辑(分支处的判断逻辑,将身份验证函数的调用修改为nop)
-
函数的返回地址(栈上的地址可能不同,这个有一定局限性)
-
攻击异常处理机制
-
函数指针
-
PEB线程同步函数的入口地址
狙击PRB中的RtlEnterCritical-Section()的函数指针
当进程退出时,ExitProcess要做很多善后工作,必须用到临界区函数
RtlEnterCriticalSection和RtlLeaceCriticalSection来同步线程防止“脏数据”的产生
据说win2000调用临界区函数是peb+0x20的函数指针间接完成的
具体就是0x7ffdf020存着指向RtlEnterCriticalSection的指针
0x7ffdf024存放着指向RtlLeaceCriticalSection的指针
看作者的代码:
#include <windows.h> char shellcode[]= "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90";//200 bytes 0x90 main() { HLOCAL h1 = 0, h2 = 0; HANDLE hp; hp = HeapCreate(0,0x1000,0x10000); h1 = HeapAlloc(hp,HEAP_ZERO_MEMORY,200); //__asm int 3 //used to break the process //memcpy(h1,shellcode,200); //normal cpy, used to watch the heap memcpy(h1,shellcode,0x200); //overflow,0x200=512 h2 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8); return 0; }
首先申请200字节,将0x200(这里作者故意写错,0x200=512)写进去,h1指向的地址处,造成溢出了
超过200字节后的数据将覆盖尾块的块首
用伪造的指针覆盖块首的空表指针,当h2分配的时候造成DWORD SHOOT
DWORD SHOOT目标是修改0x7ffdf020的RtlEnterCriticalSection为shellcode的地址
DWORD SHOOT完毕,对溢出导致异常,调用ExitProcess,
最终指向shellcode
下面的运行结果将上面的0x200改为200,不然200个90后的数据会改变
接下来这样
更改了块首和两个空表指针,当然我们那个要根据自己的电脑来修改,比如我实验就是0x003A000000的堆区的
可以看到修改成功了
继续,还有有点用,但这里的代码有点奇怪, 这里看着是比较块首的大小与0x0114比较
实验失败,哎