2007年8月7日星期二

[Tips]点评"基于栈指纹检测缓冲区溢出的一点思路"

by czy
2007-08-08
http://www.ph4nt0m.org

《基于栈指纹检测缓冲区溢出的一点思路》原文 (by gyzy)
http://www.xfocus.net/articles/200708/936.html

呵呵,难得看到有兄弟敢写这么高深的技术.
1.绕过KABA和MCAFEE的技巧,就不多说了,除了把SC移到PEB中执行我觉得最简单的办法就是在SHELLCODE中尽量不调用 getprocaddress和loadlibrary,取API地址可以用HASH比较,取DLL基地址可以通过PEB.最主要的WINEXEC可以用如下办法:

    CALL @@nextsc
@@nextsc:
    add 
byte ptr [esp],0DH
    push 
1 ;FOR TEST
    push esi   ;ESI指向要运行的木马的路径
    push [edi
+28h] ;RET
    JMP  dword ptr [edi
+8h] ;winexec,'c:\xxx',1


简单的说就是在调用winexec之前先压入getcurrentprocess函入的入口地址,或是其它的在KERNEL32.DLL中,没有参数且代码特别简单的函数.
getcurrentprocess的代码只有如下两行:
83 C8 FF or eax,-1
C3 ret
当然如果SC中必须调用漏洞程序中没有加载的DLL中的函数时可以用如下办法来调用LOADLIBRARY

    CALL @@nextsc1
@@nextsc1:
    add 
byte ptr [esp],0xH
    push esi   ;ESI指向要加载的DLL名
     mov eax, [edi
+28h] ;RET
    add eax,
3
    push eax
    JMP  dword ptr [edi
+xh] ;loadlibrary,'xxxx'



2.SC中真的有指纹吗?
GYZY兄的办法我觉得有多个地方可以破突.
HMODULE WINAPI MyLoadLibraryA(LPCTSTR lpFileName)
{
    DWORD stackbase,stacklimit,retaddr;

    __asm{
        mov eax,dword ptr [esp
+0x1c]
        mov retaddr,eax
        mov eax,dword ptr fs:[
4]
        mov stackbase,eax
        mov eax,dword ptr fs:[
8]
        mov stacklimit,eax
    }

    
if ( retaddr < stacklimit && retaddr > stackbase )
    {
overflow:
        MessageBox(
0,"BufferOverflow Detected!","gyzy",MB_ICONINFORMATION);
        
return NULL;
    }

    
//0x64 0xA1 0x30 0x00 0x00 0x00
    __asm{
        push    
0x100
        pop        ecx
        mov        esi,esp
compare:
        cmp        dword ptr [esi],
0x0030A164    //检测mov eax,fs:[30]
        je        overflow
        inc        esi
        loop    compare
    }

    
return fLoadLibraryA(lpFileName);
}



上面是他的核心代码吧,原理应该是:先在每次调用LOADLIBRARY的时候得到当前调用线程的线程栈的
地址范围,前面的办法这儿可以很简单的突破.然后从ESP开始往高地址走100个字节,检测有没有mov eax,fs:[30]
突破1:只检查了ESP往高地址100个字节,在SC中可以在调用所有API之前先把ESP减1000h(也许可以更大要看具体情况)
突破2:SC完可能不在栈中,而在堆或是PEB中.
突破3:检测mov eax,fs:[30],这个指令的变形办法实在太多了.如果都要检测的话,我看不现实,起码严重影响性能.
突破4:不管你检测什么指令,我在调用这个指令之后,调用被HOOK的API之前我都可以把这个指令修改成NOP,只要这个指令不会再被调用.


3.在我看来检测技术不但要检测返回地址的范围,还要检测一下返回地址里的指令是不是C3或是C2 XX XX,这样还要好一点点.
起码可以把SWANCALL消灭掉.