MS08_067漏洞学习研究
p197 MS08-067漏洞渗透攻击
按照书上的设置做,exploit得到错误信息:
Exploit failed [unreachable]: Rex::ConnectionRefused The connection was refused by the remote host (10.10.10.130:445).
在2k3下输入netstat -an看到445端口是开着的,而且也没有设置防火墙。
可是在kali 上用nmap 也扫不到445这个端口,奇怪!
(补充:后来就成功了,我也没弄过什么啊。。有点莫名其妙)
p205 MS08-067漏洞机理分析:
(每次运行堆栈中的地址会不同,但各函数的地址一样)
首先通过IDA Pro打开c:\windows\system32\netapi32.dll,找到漏洞所在的NetpwPathCanonicalize函数并双击。
书上说通过观察其流程图CFG可知,此函数并没有直接进行输入路径和规范化,而是调用了下级函数CanonicalizePathName。(我并不太会看)
打开OllyDbg,点击file->attach,附着到svchost.exe进程上(通过wmic查看命令行参数为svchost.exe -k netsvcs的进程pid)
view->executable modules双击netapi32,在cpu指令窗口右键选Search for,找到函数NetpwPathCanonicalize,地址为71C44A3E
按照书上说的在此处下了断点,然后点F9运行,从攻击机那里通过metasploit进行exploit。
回到OllyDbg中程序运行到断点,即NetpwPathCanonicalize函数入口处。
查看栈中的参数,结合网上查阅的NetpwPathCanonicalize函数信息可知每个参数的意义。
结合IDA Pro分析可知,NetpwPathCanonicalize函数将在地址0x71C44A9E处调用下级函数CanonicalizePathName。在此处下断点。
按F9继续运行至此断点,然后按F7跟踪函数。查看当前esp内的参数:
esp [esp]
其意义依次为:
指向prefix,值为\x5c\x00,即unicode '\'
指向待整理路径
指向输出路径的buffer
输出buffer的长度
WORD Flag保留字,值为0
从这些参数的意义可以大概知道,CanonicalizePathName函数就是将路径整理后,输出到预先分配的buffer上 。
于是我们研究它对路径做了哪些处理。
在待整理路径000C0F50处下断点。(待整理路径的形如:"\**********\..\..\***")
按F9运行,会中断3次,第三次是在调用msvcrt.dll模块中的wcscat函数。
分析栈中两个参数
第一个是目的地址,指向一段以\x5c\x00开头的内存空间;第二个是源地址,指向上述待整理路径前两字节\x5c\x00后的内容。
因此,程序把待整理路径全部复制到strDestination即0x001572F6处。在此4字节设断点,类型选择"Hardware, on access"Word。
按F9运行,中断多次后停在内存0x77bd4d36处,通过栈可知此处属于wcscpy函数。此处调用该函数进行第一次路径规范化。
这是wcscpy函数的代码:
分析代码可知,此时wcscpy源地址在edx寄存器中:
指向"\..\***"
目的地址在ecx寄存器中:
指向待整理路径第一个字符"\"
可知此次规范化即把待整理路径中第一个字符"\"和第一个"\..\"相对路径之间的内容抛弃。
第一次规范化后,待整理路径形如:"\..\***"
由于还有"\..\",还需进行一次规范化。这第二次规范化才是玄机所在。
接下来移除0x00F0F4DC处4字节的硬件断点,直接在wcscpy入口地址处下断点。
(以下为后续补充,内存地址有所改变)
运行中断后,停在wcscpy函数开头处,栈中为
而栈顶指针ESP为0x00CBF4A8,指向返回地址0x71C52FD4。
这就是栈溢出的地方:ESP到dest只有0x14字节,通过向dest写入0x64字节的字符串,则栈上的返回地址会被覆盖掉,变成0x0100129E:
从而跳转到我们构造的字符串上
进而执行shellcode,成功利用漏洞。
在攻击中重要的一步是在待整理路径复制到的目的地址前写入一个'\'(0x5c),从而在路径规范化时向前溢出。所以接下来研究这个'\'是怎么写入的。
通过断点将程序中断在wcscat函数处,从栈中获得目的地址0x00F0F4DC。
从上文我们分析出最终wcscpy的目的地址,也就是写入'\'的地方,在0x00F0F4DC前0x48的位置处。我们对该内存下写入断点:
关注往此内存写入0x5c的操作,有2处,在同一函数中,如下图所示:
通过Execute till return (Ctrl+F9),可以倒推出函数调用关系:
然后我们查阅这些函数的相关信息,从而得知是函数RtlIsDosDeviceName_Ustr函数检查DOS设备,并将设备部分字符串的长度保存到一个局部变量中。
所以通过构造出0x5C的长度,可以达到向指定内存写入'\'的目的。
总结
漏洞原理
路径规范化中,会把 "\AB\CD\..\EF" 规范为 "\AB\EF"。
所以若构造出"\(缓冲区之外)\..\**"的路径,则会覆盖掉缓冲区之外的数据,造成向前溢出。
这主要是在复制字符串时缺乏正确的边界检查造成的。
漏洞利用
- 构造出以 "\..\" 开头的待整理路径,可以绕过边界检查。
- 在缓冲区前面的内存中写入一个 "\" ,从而在路径规范化时覆盖掉这个 "\" 到缓冲区间的内容。