来源:黑客防线 作者:LoveMelody
看了ISNO大虾的《我是如何发现CCProxy漏洞的》,心里痒痒的,也想按照ISNO大虾介绍的方法,依葫芦画瓢的分析分析一个漏洞。分析什么漏洞呢?F.Zh在《菜鸟版exploit编写指南》的开山之作中,详细讲解了Cmail Server漏洞的利用过程,让我这样的菜鸟受益匪浅,以后屡用其法。但F.Zh在文章的最后,留下了一句话:“定位,如果是固定长度的话,确实可以通过两次溢出定位,但实际上这个是和安装的路径有关的,还有没有好一点的方法来定位呢?”
什么意思我不大明白,F.Zh也没有再说下去,那我们就尝试分析Cmail Server吧,看看为什么覆盖那么长的字符串正好实现溢出;也看看能不能解决F.Zh说的不定长问题;当然,更重要的,是复习总结下ISNO和F.Zh介绍的方法,并改进改进,让它更适合我们菜鸟使用。
分析
安装好一个CmailServer 4.00beta1,应该有漏洞吧,如图1所示。
图1
验证一下,进入DOS控制台,在窗口下输入Telnet 127.0.0.1 110,其中110是POP3协议所用端口,然后输入USER和一长串的a,接着回车。如图2所示。
图2
弹出出错对话框了。XP下的出错对话框和2000不同,没有直接给出报错点,如图3所示。
图3
怎么办?我们不能看到执行的地址了吗?不,还是有办法的。点击对话框中蓝色的字 “请单击此处”,系统就会给出详细的出错报告数据了。Offset:61616161,表示执行0x61616161这个地址时出现了错误。0x61就是小写的a,就是我们输入的USER中的数据,因为0x61616161地址非法,所以出错,这下XP下的定位和2000一样方便了。如图4所示。
图4
好了,到了使用ISNO方法分析漏洞的时候了。重新启动Cmail,打开SoftICE,然后再发送超长的字符串。这下SoftICE捕获异常,弹了出来,停留在这句。
001B :61616161 FFFF INVALID
意思是61616161指向的指令非法。再看看上下左右相关的数据吧,输入Data命令,会出现一个数据窗口,然后输入d EIP,就会在数据窗口中显示出如下的值。
001B : 61616161?? ?? ?? ?? ?? ??
001B : 61616171?? ?? ?? ?? ?? ??
上下左右的数据都是非法的,因为没有代码加载在这个部分,所以系统默认填充1,就是全F。原EIP和堆栈,都已经被我们过长的数据覆盖,现在无法从现今的堆栈中,找到问题代码的位置。
小知识:SoftICE默认情况下,是开了异常捕获功能的,即有什么异常发生时,会自动激活SoftICE,我们可以使用指令Fault on和Fault off来打开或关闭异常捕获功能。
使用ISNO的方法,记下这个时候ESP的值,ESP = 02AE841C,即某个函数在02AE841C附近保存了返回地址,而在函数执行的过程中,保存的返回地址被我们超长字符串覆盖,从而返回时去执行非法的0x61616161。现在的关键就是找到这个在02AE841C附近保存地址的函数。
退出SoftICE,重新启动Cmail,CTRL+D呼出SoftICE,输入Addr CmailServer进入Cmail程序的地址空间,然后下一个ISNO介绍的经典断点:bpmw 02AE841C w。意思就是当往地址02AE841C进行写操作的时候,中断下来。如果一个函数,在地址02AE841C中保存返回地址,也是一个写操作,也会被中断,我们就可以找到是那个函数出现了字符串的覆盖。
回到程序空间,再运行攻击代码,果然有写操作时,SoftICE中断弹了出来。经过了几次中断,到达了下面这句指令。
00415A61:call 004049E0
此时ESP = 02AE841C,就是004049E0这个函数,把返回地址保存在02AE841C-4=02AE8418中。如果按F8执行,马上就会弹到001B:61616161 FFFF INVALID中去,而ESP会恢复成02AE841C,我们找到了被覆盖返回地址的函数004049E0!
ISNO大虾的方法就是好,按着方法一步步的做,就成功了,大家也试试吧。找到了出问题函数后,再用Ollydbg来看004049E0处的函数。
重新启动挂掉的Cmail,用Ollydbg附加上Cmail进程,然后Ctrl+G输入地址004049E0,就可以看到如下的代码,如图5所示。
图5
直接看反汇编代码,头看裂了都看不出什么名堂来,还是动态执行,边走边看。在004049E0设一个断点,然后再运行我们的攻击程序。执行到004049E0 sub esp, 220h时,Ollydbg就会中断下来。按F8继续单步执行,在执行的时候注意查看每次调用的参数值。
00404A72 55 PUSH EBP
在内存窗口中CTRL+G然后输入EBP,发现EBP对应的是我们输入的aaaaaaaaaa……超长字符串!直觉感到马上水落石出了。下一句是:
00404A73 PUSH CMailSer.004F9640
004F9640地址是什么呢?在内存窗口中查看004F9640,是“F:\Study\课堂讲义\投稿\heifang\CMail漏洞分析”,晕,是我机器上Cmail的安装路径,早知道选个漂亮点的安装位置,免得象现在这样丢脸。算了,还是继续吧:
00404A7C PUSH CMailSer.00474498;
压入的00474498内容是“%s\mail\%s”,格式化串!看来就是作拷贝了。最后压入EAX,call一个字符串拷贝程序:
00404A81 50 PUSH EAX
00404A82 E8 18730200 CALL CMailSer.0042BD9F
明白了,调用这个函数,就大概相当于执行:
sprintf ( EAX,
"%s\mail\%s",
F:\Study\课堂讲义\投稿\heifang\CMail漏洞分析
aaaaaaaaaaaa……)
EAX中拷贝Cmail安装路径+\mail\+我们发送的USER名字,因为没有长度检查,所以导致了溢出!怪不说F.Zh说溢出点和安装路径有关,因为覆盖的字符串中,包含有Cmail的安装路径。
保存返回地址的ESP = 0x02AE8418;存放字符串的起始地址EAX = 02AE81F8,那么从EAX到ESP需要的字符串长度为:0x02AE8418-0x02AE81F8 = 0x220=544。其中安装路径“F:\Study\课堂讲义\投稿\heifang\CMail漏洞分析”是44个字节,还有“\mail\”是6个字节,那么需要覆盖a的长度为544 - 44 - 6 = 494字节!
函数执行完毕,保存地址的0x02AE8418果然被覆盖成了0x61616161,如下图6所示。
图6
当函数要返回时,就会跳到执行0x61616161的地方中去,导致了异常。如图7所示。
图7
验证
上面是通过直接分析,得到需要覆盖a的长度为494字节,但我们菜鸟心中没有底,还是使用熟悉的F.Zh黑盒法验证一下!我把F.Zh的定位方法改进了一下,分别定位百位,十位,个位,这样更容易定位比较长的溢出。利用Python写定位程序,首先定位百位:
import poplib
m = poplib.POP3('127.0.0.1')
s = 'a' * 100+'b' * 100+'c' * 100+'d' * 100+'e' * 100
m.user(s)
Python真是个写Exp和测试用的好东东,只要这几句话,就给Cmail服务器发送了100个a,100个b,100个c……的用户名,报错对话框如下图8所示:
图8
65-61=4,所以百位是4,然后定位十位。因为知道百位是4,所以先发送400个a,发送10个a,10个b……程序如下。
import poplib
m = poplib.POP3('127.0.0.1')
s = 'a'*400+'a' * 10+'b' * 10+'c' * 10+'d' * 10+'e' * 10+'f' * 10+'g' * 10+'h' * 10+'i' * 10+'j' * 10
m.user(s)
这次报错对话框变为Offset:6a6a6a6a,如图9所示。
图9
6a-61=9,所以十位为9,最后定位个位,490个a,然后是“abcdefghij”,程序如下:
import poplib
m = poplib.POP3('127.0.0.1')
s = 'a'*490+'abcdefghij'
m.user(s)
得到68676665处不能执行,如图10所示。
图10
那么个位是65-61 = 4,400+90+4=494,果然和直接算出来的一样,494字节!爽!现在不仅知其然,而且还知其所以然了。
解决不定长路径思路
因为Cmail会把大写字母变成小写字母,所以用F.Zh文章里的方法,覆盖494个a,然后是JMP ESP的地址,最后附上只有小写字母的Search代码和ShellCode,就可以完成利用了!但还有个问题,就是覆盖494字节的a,是在安装路径为“F:\Study\课堂讲义\投稿\heifang\CMail漏洞分析”时,即44个字节的情况下造成的。如果别人的安装路径不是44个字节,比如43个字节,那么就不会导致溢出;如果是45个字节,覆盖的返回点没有对正,就会导致Cmail挂掉而不能利用成功,而我们写Exp,就是想成功攻击别人的机器。如果只能攻击自己的机子,怎么也说不过去吧?
怎么办呢?想来想去有几个办法:
第一:不管长度为多少,想法让JMP ESP的地址对正返回溢出点;
第二:想办法知道对方的安装路径,精确计算出覆盖长度;
第三:如果字符串较短,虽然不会成功,但不会有挂掉的问题,就可以再次攻击。所以可以一个字节一个字节的增加字符串,直到成功为止。
第一种方法比较困难,因为在Cmail中不存在对其机制,一个字节的偏差都会导致失败。但对一些如果有8字节,16字节对其的服务中,可以考虑用JMP ESP地址+JMP08指令进行大片连续覆盖,这样只需要一个覆盖成功,就可以跳入到最后的ShellCode中。
第二种方法在ISNO的CCProxy漏洞利用中使用过,但CCProxy的变长字符串是本方的公网IP地址,所以我们可以准确的知道长度;而Cmail中对方的安装路径,好像还不容易探测到,可以考虑使用社会工程学,先挂掉对方的Cmail,然后去给他好心的说:“独哥啊,你的Cmail挂了,可能和安装目录有问题哦,是在那个目录下啊?”等亲爱的WTF/独行者大哥说出来路径并重启Cmail后……嘿嘿!
第三种方法看来最可行,假设路径的长度最大是128,那就从544-128-6=410个a开始覆盖。如果不成功,对方的Cmail也还会工作,就加长一个字节,即411个a攻击,再412个a攻击,直到成功为止。
其实在Webdav漏洞中,也有一个安装路径的问题,解决的办法也是这样,从小到大一个一个的试,不过Webdav只有4种可利用长度,所以测试的过程少的多,Cmail就比较麻烦了。你还有更好的办法吗?欢迎指教!
|