Windows内核实验 ——— Inline Hook

前言

之前的实验让我们学习到了如何调用内核的API,我们可以通过创建一个稳定的零环到三环之前的切换环境,而在此次实验中我们将把从三环到零环的_KiFastCallEntry进行Hook,通过该操作来达到在三环到零环之前切换前执行相应的代码

实验过程

我们还是利用上次的代码逻辑,不同的是在本次实验中我们需要使用两个exe来完成对应的Hook

第一个exe将对应_KiFastCallEntry的地址空间进行修改,通过把前几个字节替换为jmp(0xe9)进行跳转到我们构造的代码上,第二个则是将构造的代码写入到内核的某个全局位置,在第一个exe跳转的时候进行执行我们构造的特殊内容,同时执行原有的_KiFastCallEntry的内容,避免内核崩溃,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

#define Part 1
#if Part
// 0x80542520 KiFastCallEntry
// 0x8054252D KiFastCallEntry + 13 ret addr
// 0x8003f120 GDTR addr
// eq 8003f500 0040ee00`00081040
void __declspec(naked) IdtEntry() {
__asm {
mov eax, cr0
and eax, not 10000h
mov cr0, eax; 关闭写保护

mov al, 0xe9; jmp
mov ds : [0x80542520] , al
mov eax, 0xFFAFCBFB; 计算相应偏移量 0x8003f120 - 0x80542525 = 0xFFAFCBFB
mov ds : [0x80542521] , eax

mov eax, cr0
or eax, 10000h
mov cr0, eax; 打开写保护
iretd
}
}
void crash() {
while (1) {
__asm {
int 0x20
}
}
}
int main() {

if ((DWORD)IdtEntry != 0x00401040) {
printf("wrong addr : %p \n", IdtEntry);
exit(-1);
}
crash();
system("pause");
return 0;
}
#else
void hook();
int i = 0;
char* p = (char*)0x8003f120;
// eq 8003f500 0040ee00`00081040
void __declspec(naked) IdtEntry() {
// 覆写代码
for (i = 0; i < 64; i++) {
*p = ((char*)hook)[i];
p++;
}
__asm {
iretd
}
}
void crash() {
__asm {
int 0x20
}
}
void __declspec(naked) hook() {
__asm {
pushad
pushfd

mov eax, ds: [0x8003f1f0]
inc eax
mov ds : [0x8003f1f0] , eax ;每当执行一次零环到三环的切换时对应的值便会加一

popfd
popad

mov cx, 0x23
push 0x30
pop fs
mov ds, cx
mov es, cx
mov ecx, 0x8054252D; 跳回去执行后续代码
jmp ecx
}
}
int main() {
if ((DWORD)IdtEntry != 0x00401040) {
printf("wrong addr : %p \n", IdtEntry);
exit(-1);
}
crash();
system("pause");
return 0;
}
#endif

在上述的代码过程中我们使用的内核的GDTR表中的空字节数据,将我们的构造的代码进行填充。同时把我们在GDTR0x8003f1f0处设定了一个变量(虽然没初始化),每当有三环到零环的切换其值便会增加一。

上面的代码使用#if#else#endif的宏来进行控制对应的代码生成,因为笔者环境莫名其妙的在开多个工程文件的时候会出现编译问题

总结

在此过程中我们并没有实现太多的东西,只是简单的对三环到零环切换次数进行计算,此次实验中对于jmp的地址调试以及忘记将Hook函数设置为裸函数而导致花费了挺长时间(归根还是菜QwQ),以及一些细节方面的小问题。

相信通过上述的简单逻辑介绍各位师傅可以实现更实用的功能。此处便不再往后讲解了。


Windows内核实验 ——— Inline Hook
https://equinox-shame.github.io/2023/04/25/Windows内核实验 — Inline Hook/
作者
梓曰
发布于
2023年4月25日
许可协议