Windows内核实验:系统调用(system call)
实现两个系统调用,读和申请内核空间
DWORD ReadMem(DWORD address) DWORD AllocMem(DWORD size)
|
ExAllocatePool分配一块内存或者在内核里找一块安全的内核不会用到的内存来存放指令
选取下面的空余内核内存
kd> dq @gdtr l80 8003f000 00000000`00000000 00cf9b00`0000ffff ....... SystemCallEntry 8003f120 00000000`8003f128 00000000`8003f130 8003f130 00000000`8003f138 00000000`8003f140 8003f140 00000000`8003f148 00000000`8003f150 8003f150 00000000`8003f158 00000000`8003f160 8003f160 00000000`8003f168 00000000`8003f170 8003f170 00000000`8003f178 00000000`8003f180 8003f180 00000000`8003f188 00000000`8003f190 8003f190 00000000`8003f198 00000000`8003f1a0 8003f1a0 00000000`8003f1a8 00000000`8003f1b0 8003f1b0 00000000`8003f1b8 00000000`8003f1c0 8003f1c0 00000000`8003f1c8 00000000`8003f1d0 ........ ReadMem 8003f1d0 00000000`8003f1d8 00000000`8003f1e0 8003f1e0 00000000`8003f1e8 00000000`8003f1f0 8003f1f0 00000000`8003f1f8 00000000`8003f200 8003f200 00000000`8003f208 00000000`8003f210 ........ AllocMem 8003f210 00000000`8003f218 00000000`8003f220 8003f220 00000000`8003f228 00000000`8003f230 8003f230 00000000`8003f238 00000000`8003f240 8003f240 00000000`8003f248 00000000`8003f250 ........ 8003f250 00000000`8003f258 00000000`8003f260 8003f260 00000000`8003f268 00000000`8003f270 ........Service Table 8003f270 00000000`8003f278 00000000`8003f280
|
系统调用入口函数SystemCallEntry来通过eax的值在系统调用表Service Table里确定系统函数做系统调用
makeKernel.exe
#include <stdio.h> #include <stdlib.h> #include <windows.h> enum { AD_CALLENTRY, AD_READ, AD_ALLOC }; DWORD Address[3] = { 0x8003f120 ,0x8003f1d0,0x8003f210 }; PDWORD ServiceTable = (PDWORD)0x8003f270; PDWORD IdtAddress = (PDWORD)0x8003f508; size_t i; char* des; void SystemCallEntry(); void ReadMem(); void AllocMem(); void __declspec(naked) IdtEntry() { __asm { push 0x30 pop fs sti } des = (char*)Address[AD_CALLENTRY]; for (i = 0; i < 0xb0; i++) { *des = ((char*)SystemCallEntry)[i]; des++; } des = (char*)Address[AD_READ]; for (i = 0; i < 0x40; i++) { *des = ((char*)ReadMem)[i]; des++; } des = (char*)Address[AD_ALLOC]; for (i = 0; i < 0x40; i++) { *des = ((char*)AllocMem)[i]; des++; } ServiceTable[0] = Address[AD_READ]; ServiceTable[1] = Address[AD_ALLOC]; IdtAddress[0] = 0x0008f120; IdtAddress[1] = 0x8003ee00; __asm { cli push 0x3B pop fs iretd } } void __declspec(naked) SystemCallEntry() { __asm { push 0x30 pop fs sti mov ebx, ss: [esp + 0xc] mov edi, ds: [ebx + 4] mov ebx, 0x8003f270 mov edx, [ebx + eax * 4] call edx
cli push 0x3b pop fs iretd } } void __declspec(naked) ReadMem() { __asm { mov eax, ds: [edi] ret } } void __declspec(naked) AllocMem() { __asm { push edi push 0 mov edx, 0x80533708 call edx ret } }
void interrupt() { __asm { int 0x20 } } int main() { if (0x401040 != (DWORD)IdtEntry) { printf("IdtRntry address wrong"); system("pause"); exit(-1); } interrupt(); system("pause"); }
|
三环测试程序ntdll.exe
#include <stdio.h> #include <stdlib.h> #include <Windows.h> DWORD __declspec(naked) ReadMem(DWORD address) { __asm { mov eax,0 int 0x21 ret } } DWORD __declspec(naked) AllocMem(DWORD size) { __asm { mov eax, 1 int 0x21 ret } } int main() { printf("0x%x\n",ReadMem(0x8003f00c)); printf("0x%x",AllocMem(0x10)); system("pause"); }
|