Windows内核实验 ——— 进程切换

前言

前面我们已经了解到了CR3是控制进程的一个核心资源,相当于访问内存的一把钥匙,理论上我们可以通过其访问任何进程的内存,此次实验中我们将编写代码将一个notepad中的内存信息进行修改

实验过程

我们首先创建一个notepad程序,在里面随便写入点内容,通过CE来找到其字符串对应的地址空间

我们找到对应地址空间后我们通过使用notepad的CR3寄存器来获取对应的地址空间,我们使用Windbg来进行获取

1
!process 0 0 notepad.exe

可以看到其CR3值为0x0aac01a0,接下来我们将CR3进行切换到notepad的空间中,随后对Hello0所在的地址进行修改值我们便可以完成相应的操作

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
#include <stdio.h>
#include <Windows.h>

void SystemCall();

DWORD* TargetAddr = (DWORD *)0x8003f150;
char* p;

void __declspec(naked) IdtEntry() {

// 将 Systemcall 的地址写入GDT
p = (char *)TargetAddr[0];
for (int i = 0; i < 64; i++) {
*p = ((char *)SystemCall)[i];
p++;
}
// eq 0x8003f508 8003ee00`0008f158
__asm {
; 构造 int 21h 来完成对 SystemCall 的调用
; int 21 addr: 0x8003f508

mov eax, 0x0008f158
mov ds : [0x8003f508] , eax
mov eax, 0x8003ee00
mov ds : [0x8003f50c] , eax

iretd
}
}

void __declspec(naked) SystemCall() {
__asm {

; 保存当前 cr3 到 0x8003f3e0
mov eax, cr3
mov ds:[0x8003f3e0], eax

; 切换 cr3 到 notepad.exe 的 cr3
mov eax, 0x0aac02e0
mov cr3, eax

; 修改 notepad 中字符
mov eax, 0xAABBCCDD
mov ds:[0x01102330], eax

; 恢复 cr3
mov eax, ds:[0x8003f3e0]
mov cr3, eax

iretd
}
}

void crash() {
__asm {
int 0x20
}
}

int main() {
if ((DWORD*)IdtEntry != 0x00401040) {
printf("IdtEntry addr %p", IdtEntry);
return 0;
}
crash();
system("pause");
}

我们可以成功的看到int 21H已经被写入到了系统中断向量表中,我们使用Windbg来进行查看SystemCall对应的汇编是否写入到0x8003f158

可以看到我们的汇编代码已经成功的写入

之后我们构建一个int 21H的中断程序之后进行观察对应的内存

可以成功的看到我们的进程内存被修改了,成功设置为了我们想要的0xAABBCCDD

总结

在上述的实验过程中我们并没有简单的直接使用以下代码作为IdtEntry

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
__asm {

; 保存当前 cr3 到 0x8003f3e0
mov eax, cr3
mov ds:[0x8003f3e0], eax

; 切换 cr3 到 notepad.exe 的 cr3
mov eax, 0x0aac02e0
mov cr3, eax

; 修改 notepad 中字符
mov eax, 0xAABBCCDD
mov ds:[0x01102330], eax

; 恢复 cr3
mov eax, ds:[0x8003f3e0]
mov cr3, eax

iretd
}

这是因为存在页保护的机制,对于每一个程序来说有一个属于自己的私有地址空间,外部程序是无法进行访问的,我们如果直接在程序中使用上述代码时,我们的所有代码都是在该程序的地址空间内。而当我们切换cr3的一瞬间,我们已经进入了notepad的私有内存中,我们的下一句的mov eax, 0xAABBCCDD以及后面的所有汇编代码都不会存在于notepad这个程序中,进而会引发异常

对此的解决方式我们是将我们的代码写入到如GDT等公有空间内,当我们切换进程的时候仍然拥有原来的代码,进而可以通过cr3来对notepad的内存进行修改,达到将我们的内容进行修改的目的


Windows内核实验 ——— 进程切换
https://equinox-shame.github.io/2023/06/06/Widnows内核实验 — 进程切换/
作者
梓曰
发布于
2023年6月6日
许可协议