Windows内核实验:跨进程内存读写
一个进程访问的虚拟内存都是靠页的各种表来管理的嘛,他的根源就是cr3寄存器,所以理论上我们把某个进程的cr3换过来就可以实现读写这个进程
打开一个notepad
用ce找到他的字符串内存地址为0xaab30
kd> !process 0 0 notepad.exe Failed to get VadRoot PROCESS 8165f350 SessionId: 0 Cid: 0688 Peb: 7ffd8000 ParentCid: 04a4 DirBase: 08bd0240 ObjectTable: e14bcae8 HandleCount: 46. Image: notepad.exe
|
我们很自然的就会写出这样的代码
#include <stdio.h> #include <stdlib.h> #include <windows.h> void __declspec(naked) IdtEntry() { __asm { mov eax,cr3 mov ds:[0x8003f130],eax mov eax,0x8bd0240 mov cr3,eax mov eax,0x12345678 mov ds:[0xaab30],eax mov eax,ds:[0x8003f130] mov cr3,eax iretd } } void interrupt() { __asm { int 0x20 } } int main() { if (0x401040 != IdtEntry) { printf("IdtRntry address wrong"); system("pause"); exit(-1); } interrupt(); system("pause"); }
|
但是其实mov cr3,eax 后面的指令压根不会执行,切换cr3后,我eip去取指令,但是现在已经是notepad的cr3了,自然不会取到我们程序的eip处指令,而是notepad的eip处指令,所以这段指令应该放到内核中每个进程都相同的地方,依旧选取gdt表里的空闲位置0x8003f140
#include <stdio.h> #include <stdlib.h> #include <windows.h> char* Address = (char *)0x8003f140; size_t i; void EditNotepad(); void __declspec(naked) IdtEntry() { for ( i = 0; i < 0x40; i++) { Address[i] = ((char*)EditNotepad)[i]; } __asm { push 0x8003f140 ret } } void __declspec(naked) EditNotepad() { __asm { mov eax, cr3 mov ds : [0x8003f130] , eax mov eax, 0x8bd0240 mov cr3, eax mov eax, 0x12345678 mov ds : [0xaab30] , eax mov eax, ds : [0x8003f130] mov cr3, eax iretd } } void interrupt() { __asm { int 0x20 } } int main() { if (0x401040 != IdtEntry) { printf("IdtRntry address wrong"); system("pause"); exit(-1); } interrupt(); system("pause"); }
|
还可以用我们之前的做系统调用的方法去实现一个系统调用或中断来做