前言
前面我们已经了解到了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() { p = (char *)TargetAddr[0]; for (int i = 0; i < 64; i++) { *p = ((char *)SystemCall)[i]; p++; } __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
的内存进行修改,达到将我们的内容进行修改的目的