Windows內核分析索引目錄:https://www.cnblogs.com/onetrainee/p/11675224.html
Windows系統(tǒng)調用中API的3環(huán)部分
?
一、R3環(huán)API分析的重要性
?
二、調試代碼
1 #include "pch.h" 2 #include <iostream> 3 #include <algorithm> 4 #include <Windows.h> 5 6 int main() { 7 getchar(); 8 getchar(); 9 int a[4],t;10 printf("hello world!");11 getchar();12 getchar();13 // 依次往 p 指針中寫入數(shù)據(jù),再用ReadProcessMemory讀取數(shù)據(jù)14 for (int i = 0; i < 4; i ) {15 WriteProcessMemory(INVALID_HANDLE_VALUE, &a[i], &i, sizeof(int),NULL);16 17 }18 for (int i = 0; i < 4; i ) {19 ReadProcessMemory(INVALID_HANDLE_VALUE, &a[i], &t, sizeof(int), NULL);20 printf("%d\n", t);21 }22 getchar();23 getchar();24 25 }
?
三、調試中的關鍵匯編代碼(系統(tǒng)環(huán)境:在Windows7 32位操作系統(tǒng) / 調試器:olldbg)
?
?
?
?
1. 在exe 中 調用 kernel32.ReadProcessMemroy函數(shù)
01314E3E??? 8BF4???????? mov esi,esp
01314E40??? 6A 00??????? push 0x0
01314E42??? 6A 04??????? push 0x4
01314E44??? 8D45 DC????? lea eax,dword ptr ss:[ebp-0x24]
01314E47??? 50?????????? push eax
01314E48??? 8B4D C4????? mov ecx,dword ptr ss:[ebp-0x3C]
01314E4B??? 8D548D E8??? lea edx,dword ptr ss:[ebp ecx*4-0x18]
01314E4F??? 52?????????? push edx
01314E50??? 6A FF??????? push -0x1
01314E52??? FF15 64B0310>call dword ptr ds:[<&KERNEL32.ReadProcessMemory>]; kernel32.ReadProcessMemory
01314E58??? 3BF4???????? cmp esi,esp
2. 在 kernel32.ReadProcessMemroy函數(shù) 中調用 jmp.&API-MS-Win-Core-Memory-L1-1-0.ReadProcessMemory> 函數(shù)
// 該函數(shù)相當于什么也沒做...
7622C1CE >? 8BFF???????????? mov edi,edi
7622C1D0??? 55?????????????? push ebp
7622C1D1??? 8BEC???????????? mov ebp,esp
7622C1D3??? 5D?????????????? pop ebp?????????????????????????????????????????????????????????? ;
7622C1D4? ^ E9 F45EFCFF????? jmp <jmp.&API-MS-Win-Core-Memory-L1-1-0.ReadProcessMemory>
3. 在 API-MS-Win-Core-Memory-L1-1-0.ReadProcessMemo 中調用 KernelBa.ReadProcessMemory 函數(shù)
761F20CD? - FF25 0C191F7>jmp dword ptr ds:[<&API-MS-Win-Core-Memory-L1-1-0.ReadProcessMemo>; KernelBa.ReadProcessMemory
4. 在KernelBa.ReadProcessMemory 調用 <&ntdll.NtReadVirtualMemory> 函數(shù)
75DA9A0A >? 8BFF???????? mov edi,edi
// 這兩部分在編寫函數(shù)時就會使用
75DA9A0C??? 55?????????? push ebp
75DA9A0D??? 8BEC???????? mov ebp,esp
75DA9A0F??? 8D45 14????? lea eax,dword ptr ss:[ebp 0x14]
75DA9A12??? 50?????????? push eax
75DA9A13??? FF75 14????? push dword ptr ss:[ebp 0x14]
75DA9A16??? FF75 10????? push dword ptr ss:[ebp 0x10]
75DA9A19??? FF75 0C????? push dword ptr ss:[ebp 0xC]
75DA9A1C??? FF75 08????? push dword ptr ss:[ebp 0x8]
75DA9A1F??? FF15 C411DA7>call dword ptr ds:[<&ntdll.NtReadVirtualMemory>] ; ntdll.ZwReadVirtualMemory
5. 在 <&ntdll.NtReadVirtualMemory> 中調用 ntdll.KiFastSystemCall 函數(shù)
77A162F8 >? B8 15010000? mov eax,0x115? // 對應操作系統(tǒng)內核中某一函數(shù)的編號。
77A162FD??? BA 0003FE7F? mov edx,0x7FFE0300? // 該地方是一個函數(shù),該函數(shù)決定了什么方式進零環(huán)。
77A16302??? FF12???????? call dword ptr ds:[edx]? ; ntdll.KiFastSystemCall
6. 在 ntdll.KiFastSystemCall 中 調用sysenter
77A170B0 >? 8BD4???????? mov edx,esp
77A170B2??? 0F34???????? sysenter
77A170B4 >? C3?????????? retn
?
四、匯編代碼分析解讀(根據(jù)二中的序號依次解讀)
五、重寫ReadProcessMemory函數(shù)的思路
我們所看到的匯編代碼,本質就是Windows所執(zhí)行的步驟,我們依據(jù)上面的分析,完全可以重新寫一個該函數(shù),只需要關鍵部分。
1) 退而求其次
我們希望可以在自己的代碼中直接使用 "sysenter",但經過編寫發(fā)現(xiàn)其并沒有提供這種指令。
因此在"sysenter"無法直接使用的情況下,只能退而求其次,調用ntdll.KiFastSystemCall函數(shù)。
2)傳遞參數(shù),模擬call指令
ntdll.KiFastSystemCall函數(shù)需要借助ntdll.NtReadVirtualMemory傳遞過來的參數(shù),然后執(zhí)行call指令。
我們并不希望執(zhí)行call指令執(zhí)行,因為執(zhí)行call指令意味著又上了一層。(多一層被鉤取的風險)
我們希望自己的代碼中直接傳遞參數(shù),并且直接調用調用ntdll.KiFastSystemCall函數(shù)。
因此我們需要模擬call指令。call指令的本質就是將返回地址入棧,并跳轉。我們不需要跳轉,只需要將返回值入棧(四個字節(jié) sub esp,4)
3)手動實現(xiàn)棧平衡
我們內嵌匯編代碼后,需要手動平衡棧,我們只需要分析esp改變了多少(push、pop以及直接對esp的計算)。
經過分析共減少了24字節(jié),所以代碼最后應該有 add esp,24 來平衡棧。
?
六、ReadProcessMemory函數(shù)重寫的實現(xiàn)(重點看匯編代碼)
1 #include "pch.h" 2 #include <iostream> 3 #include <algorithm> 4 #include <Windows.h> 5 void ReadMemory(HANDLE hProcess, PVOID pAddr, PVOID pBuffer, DWORD dwSize, DWORD *dwSizeRet) 6 { 7 8 _asm 9 {10 lea eax, [ebp 0x14]11 push eax12 push[ebp 0x14]13 push[ebp 0x10]14 push[ebp 0xc]15 push[ebp 8]16 sub esp, 417 mov eax, 0x11518 mov edx, 0X7FFE0300 //sysenter不能直接調用,我間接call的19 CALL DWORD PTR[EDX]20 add esp, 2421 22 }23 }24 int main()25 {26 HANDLE hProcess = 0;27 int t = 123;28 DWORD pBuffer;29 //hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0,a);30 ReadMemory((HANDLE)-1, (PVOID)&t, &pBuffer, sizeof(int), 0);31 printf("%X\n", pBuffer);32 ReadProcessMemory((HANDLE)-1, &t, &pBuffer, sizeof(int), 0);33 printf("%X\n", pBuffer);34 35 getchar();36 return 0;37 }
?
?
?
來源:https://www.icode9.com/content-3-512401.html