7.1.3 漏洞的分析
“Yeah!成功!”大家都叫了起来,然后纷纷说道,“虽然成功利用过多次,但真的对一个新漏洞利用成功了,还是有点激动的,呵呵!”
“这很好啊!其实正是这些小小的成就,让你品尝到了努力成功后的喜悦。这样才能触动你的进一步发展,实现真正的成功。”老师说道。
“好了,进入我们的重头戏,来分析漏洞的成因吧!”
“好啊!这下可以看看实际程序中的漏洞是怎样出现的了。”大家高兴的说。
“首先启动我们的调试利器——SoftICE。”
“嗯,在jmp esp转换成call ebx的利用方式那里我们使用过,果然很强大!”古风真是好记性。
“这位同学记忆力真好!这里我们会进一步深入使用它。启动CCProxy,再重新发送全‘A’的过长数据。
因为会产生异常,所以SoftICE就会捕获异常,自动弹出来。停在了下面这句话:”
001B : 41414141 INVALID
小知识:
SoftICE默认情况下是开了异常捕获功能的。即有什么异常发生时,会自动激活SoftICE。我们可使用指令 Fault on 和 Fault off 来打开或关闭异常捕获功能。
“ 001B : 41414141 INVALID 意思是41414141指向的指令非法。”老师解释道。
“哦!那些指令究竟是什么数据呢?”宇强进一步问道。
“在SoftICE下,我们输入 code on 命令显示机器码,就可以看到对应的地方全是FFFF数据。”
001B : 41414141 FFFF INVALID
“哦!”
“我们再看看上下左右相关的数据吧,输入 data 命令,就会出现一个数据窗口。然后输入 d eip ,就会在数据窗口中显示出如下的值。”
001B : 41414141 ?? ?? ?? ?? ?? ??
001B : 41414151 ?? ?? ?? ?? ?? ??
“上下左右都是非法的啊?”
“是的,因为没有代码加载在这个部分,所以系统默认填充1,就是全F。”老师解释道,“而我们的关键,就是要找到发生问题的那段程序。”
“我们看看现在堆栈里面的值,和前面类似,这里用命令 d esp ,就出现了现在堆栈数据的情况。”
esp = 012A790C
0023:012A790C 41 41 41 41 41 41 41 41-4 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0023:012A791C 41 41 41 41 41 41 41 41-4 41 41 41 41 20 48 54 AAAAAAAAAAAAA HT
0023:012A792C 54 50 2F 31 2E 30 0D 0A TP/1.0
“原EIP和堆栈都已被我们过长的数据覆盖,我们无法从现今的堆栈中找到问题代码的位置。”
“是啊!怎么办呢?”小倩着急的说道。
“我们先推理一下。现在ESP=012A790C,程序返回后,堆栈指针ESP会指向012A790C;所以应该是某个函数(假设是函数A)执行前把返回地址存在了012A790C-4或附近中;然后在函数A执行过程中作了无长度限制的字符串拷贝,使返回地址被覆盖成了我们发送的41414141!”
“那个函数A就是有问题的函数;而无长度限制的字符串拷贝就是Strcpy、Strcat一类的操作。”
“哦,难道我们要猜测哪个函数A在012A790C附近中保存了返回地址?”宇强说道。
“非常正确!”老师特别高兴,“第一种方法:用 bpx 命令往Strcpy、Strcat等函数入口处设断点,然后返回函数A的空间,看是否会出现覆盖问题。”
“第二种方法,因为函数A会往012A790C附近写入返回地址,所以我们设置断点,在往012A790C这个地址写东西时中断下来,看能否找到有问题的函数A。”
“我们这里用第二种方法。”
“退出SoftICE,回到Windows下重新启动CCProxy。再进入SoftICE输入 addr proxy ,表示进入进程空间;然后输入 bpmd 012A790C w ,表示往012A790C写东西时停下来。”
大家眼睛都看得直直的,小倩也在边听边记。
“好,设置完毕后,我们再运行攻击代码,这样,当往012A790C写入的时候,就会被SoftICE中断。”
“运行过程中,会有好几次中断,但显然都不是保存函数返回地址的操作,我们按F5继续让它执行。终于到了下面这句时,SoftICE被中断弹出。”老师指住下面的指令说。
0040F2A0 : call 0040A410
“此时ESP=012A790C, 即先把返回地址保存在012A790C中,然后跳到0040A410函数内部执行。根据我们的猜测,相信就是这个函数在处理时,返回地址被覆盖了。”
“函数中究竟是什么东西导致错误了呢?我们跟进去看看吧!按F8动态跟踪进 0040A410函数内部。”
“哎哟!这里全是反汇编的代码,怎么能看懂啊?”玉波嚷了起来。
“直接让你看出有问题的地方,的确比较困难。但我们是在动态跟踪啊!当有 Push push call 时,我们就知道这是在调用函数,然后可以通过 d 命令来查看参数究竟是什么。”
“我们实际来使用一遍吧!当执行到 0040A5F8: 55 push EBP 这句时,我们输入 d EBP ,发现压入的参数内容是:”
192.168.3.150 unknown Web GET /AAAAAAAAAAAAAAAAAAAAAAAAA
“哦!就是我们发送的字符串多了一些东西!”
“越来越近了!就要水落石出了吧!”大家议论纷纷。
“嗯!我们继续。接下来是这句指令:”
0040A5F9: 51 push ECX
“输入 d ecx 命令,发现内容是时间信息。为: 2004-11-25 16:46:56 。”
“下一句: 0040A601: PUSH 0046F110 。我们输入 d 0046F110 命令,发现是 [%s] %s 格式化串!”
“最后,PUSH edx,再Call 一个函数。我们根据分析参数的内容,知道应该是执行下面类似的函数。”
wwspritnf ( edx,
[%s] %s
2004-11-25 16:46:56
### 192.168.3.150 unknown Web GET /AAAAAAAAAAAAAAAAAAAAAAAAA
)
“这个拷贝操作是把日期、时间和我们发送的过长字符串,拷贝到EDX指向的内存中;因为没有字符串长度的限制,所以把保存的EIP也覆盖了,从而导致溢出。”
“哦!原来漏洞真的是这样产生的啊!”同学们说道。
“我们通过代码来计算一下覆盖点的位置和长度。此时EDX=012A6904,为字符串保存的起始地址;而ESP=012A790C,为保存的函数返回地址。”
“两个位置相减,ESP-EDX=012A790C-012A6904=0x1008=4104。那么,就是要覆盖4104那么长的字符串,才能到达函数返回地址。”
“刚才,我们定位得到的A的长度是?”老师问道。
“4056!”古风一口报了出来。
“哇!好记性!大家看看参数,除了我们的A,还包括日期、时间、IP、unknow WEB和GET等字符串,再加上格式化输出 [%s ] %s 中的‘['字符']’字符和一个空格,大家数数有多长!”
“嗯,一共是48个字节。”古风很快的数完后说道。
“对!所以我们覆盖的A正好是:分配空间-其他字符长度=4104-48=4056!”
“哦!原来是这样啊!”
“我们继续执行。果然,保存的EIP被覆盖;所以,就是这个函数的执行导致了缓冲区溢出,分析成功!”
小结漏洞分析过程:
1.启动有漏洞程序,启动SoftICE并打开异常捕获开关(默认打开);
2.发送过长的字符串,引发程序的异常,SoftICE弹出;
3.查看此时的ESP的值并记下,假设是AAAA;
4.退回用户空间,重新启动漏洞程序;
5.按CTRL+D进入SoftICE,用 addr 命令进入程序空间;再用 bpmw AAAA w 设置写断点;
6.再次发送过长字符串;
7.SoftICE会在往AAAA地址写操作时弹出来;我们可分析是哪一个函数在该点保存了返回地址;
8.跟入该函数;注意用d命令查看里面调用的各函数参数的值;当发现某个函数有我们发送的过长字符串和‘%s’一类的参数时,就仔细分析,多半是该操作的问题!从而分析清楚漏洞产生的原因。