|
Windows內(nèi)核分析索引目錄:https://www.cnblogs.com/onetrainee/p/11675224.html Windows系統(tǒng)調(diào)用中API的3環(huán)部分 ? 一、R3環(huán)API分析的重要性
? 二、調(diào)試代碼 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 指針中寫(xiě)入數(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 }
? 三、調(diào)試中的關(guān)鍵匯編代碼(系統(tǒng)環(huán)境:在Windows7 32位操作系統(tǒng) / 調(diào)試器:olldbg)
? ? ? ? 1. 在exe 中 調(diào)用 kernel32.ReadProcessMemroy函數(shù) 2. 在 kernel32.ReadProcessMemroy函數(shù) 中調(diào)用 jmp.&API-MS-Win-Core-Memory-L1-1-0.ReadProcessMemory> 函數(shù) 3. 在 API-MS-Win-Core-Memory-L1-1-0.ReadProcessMemo 中調(diào)用 KernelBa.ReadProcessMemory 函數(shù) 4. 在KernelBa.ReadProcessMemory 調(diào)用 <&ntdll.NtReadVirtualMemory> 函數(shù) 5. 在 <&ntdll.NtReadVirtualMemory> 中調(diào)用 ntdll.KiFastSystemCall 函數(shù) 6. 在 ntdll.KiFastSystemCall 中 調(diào)用sysenter ? 四、匯編代碼分析解讀(根據(jù)二中的序號(hào)依次解讀)
五、重寫(xiě)ReadProcessMemory函數(shù)的思路 我們所看到的匯編代碼,本質(zhì)就是Windows所執(zhí)行的步驟,我們依據(jù)上面的分析,完全可以重新寫(xiě)一個(gè)該函數(shù),只需要關(guān)鍵部分。 1) 退而求其次 我們希望可以在自己的代碼中直接使用 "sysenter",但經(jīng)過(guò)編寫(xiě)發(fā)現(xiàn)其并沒(méi)有提供這種指令。 因此在"sysenter"無(wú)法直接使用的情況下,只能退而求其次,調(diào)用ntdll.KiFastSystemCall函數(shù)。 2)傳遞參數(shù),模擬call指令 ntdll.KiFastSystemCall函數(shù)需要借助ntdll.NtReadVirtualMemory傳遞過(guò)來(lái)的參數(shù),然后執(zhí)行call指令。 我們并不希望執(zhí)行call指令執(zhí)行,因?yàn)閳?zhí)行call指令意味著又上了一層。(多一層被鉤取的風(fēng)險(xiǎn)) 我們希望自己的代碼中直接傳遞參數(shù),并且直接調(diào)用調(diào)用ntdll.KiFastSystemCall函數(shù)。 因此我們需要模擬call指令。call指令的本質(zhì)就是將返回地址入棧,并跳轉(zhuǎn)。我們不需要跳轉(zhuǎn),只需要將返回值入棧(四個(gè)字節(jié) sub esp,4) 3)手動(dòng)實(shí)現(xiàn)棧平衡 我們內(nèi)嵌匯編代碼后,需要手動(dòng)平衡棧,我們只需要分析esp改變了多少(push、pop以及直接對(duì)esp的計(jì)算)。 經(jīng)過(guò)分析共減少了24字節(jié),所以代碼最后應(yīng)該有 add esp,24 來(lái)平衡棧。 ? 六、ReadProcessMemory函數(shù)重寫(xiě)的實(shí)現(xiàn)(重點(diǎ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 eax
12 push[ebp 0x14]
13 push[ebp 0x10]
14 push[ebp 0xc]
15 push[ebp 8]
16 sub esp, 4
17 mov eax, 0x115
18 mov edx, 0X7FFE0300 //sysenter不能直接調(diào)用,我間接call的
19 CALL DWORD PTR[EDX]
20 add esp, 24
21
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 }
? ? ?
來(lái)源:https://www./content-3-512401.html |
|
|
來(lái)自: 印度阿三17 > 《開(kāi)發(fā)》