用DEP实现BreakOnExecute
以前抄过OllyBone,但不大好用,很多时候停不下来,似乎在PTE上做的手脚没起作用。后来看到
DEP,这不就是我想要的功能么,又重新试了一次。
打开DEP后,系统工作在PAE下,PTE为64位。不过改了以后,还是存在拦不住的情况,用SoftIce跟了一下,
PTE的确被动过。Hook KeInterlockedSwapPte就可以了,估计OllyBone不好用也是同样道理。
前段时间写的东西,细节已经记不起来了。反正代码都贴出来了。功能跟OllyBone一样的。在xp sp2/sp3下测试可以用。
代码:
#define MiGetPteAddressPAE(va) ((PMMPTE)(PTE_BASE + ((((ULONG)(va)) >> 12) << 3))) typedef struct _HARDWARE_PTE_X86PAE { union { struct { ULONGLONG Valid : 1; ULONGLONG Write : 1; ULONGLONG Owner : 1; ULONGLONG WriteThrough : 1; ULONGLONG CacheDisable : 1; ULONGLONG Accessed : 1; ULONGLONG Dirty : 1; ULONGLONG LargePage : 1; ULONGLONG Global : 1; ULONGLONG CopyOnWrite : 1; // software field ULONGLONG Prototype : 1; // software field ULONGLONG reserved0 : 1; // software field ULONGLONG PageFrameNumber : 26; //ULONGLONG reserved1 : 26; // software field ULONGLONG reserved1 : 25; // software field ULONGLONG ExecuteDisable : 1; // 这个 }; struct { ULONG LowPart; ULONG HighPart; }; }; } HARDWARE_PTE_X86PAE, *PHARDWARE_PTE_X86PAE; VOID HookMemory(ULONG address, ULONG size) { ULONG i; g_HookMem = TRUE; g_HookStart = address; g_HookEnd = address + size; g_PteStart = (ULONG)MiGetPteAddressPAE(g_HookStart); g_PteEnd = (ULONG)MiGetPteAddressPAE(g_HookEnd); //DbgPrint("PteStart = %08X, PteEnd = %08X", g_PteStart, g_PteEnd); KeAttachProcess(g_ObjProc); for (i = address; i < address+size; i += PAGE_SIZE) //4KB Pages only HookPage((PUCHAR)i); KeDetachProcess(); } VOID HookPage(PUCHAR Page) { PHARDWARE_PTE_X86PAE PointerPte; __try { __asm { mov eax, Page mov eax, [eax] } PointerPte = (PHARDWARE_PTE_X86PAE)MiGetPteAddressPAE(Page); if (PointerPte->Valid == 1) { PointerPte->ExecuteDisable = 1; DbgPrint("HookPage = %08X", Page); } } __except(EXCEPTION_EXECUTE_HANDLER) { DbgPrint("Exception captured while hooking page"); } } VOID UnhookPage(PUCHAR Page) { PHARDWARE_PTE_X86PAE PointerPte; __try { __asm { mov eax, Page mov eax, [eax] } PointerPte = (PHARDWARE_PTE_X86PAE)MiGetPteAddressPAE(Page); if (PointerPte->Valid == 1) { PointerPte->ExecuteDisable = 0; } } __except(EXCEPTION_EXECUTE_HANDLER) { DbgPrint("Exception captured while unhooking page"); } } VOID UnhookMemory(ULONG address, ULONG size) { ULONG i; KeAttachProcess(g_ObjProc); for (i = address; i < address+size; i += PAGE_SIZE) UnhookPage((PUCHAR)i); KeDetachProcess(); } NTSTATUS FindSwapPte(ULONG ntosbase, PULONG result) { // // Search KeInterlockedSwapPte in kernel space:) // there are some lock cmpxchg8b, but this is the only one followed // by a jnz // UCHAR code[] = { 0xF0, 0x0F, 0xC7, 0x0E, // lock cmpxchg8b qword ptr [esi] 0x75, 0xFA, // jnz short loc_46EC60 0x5E, // pop esi 0x5B, // pop ebx 0xC2, 0x08, 0x00 // retn 8 }; NTSTATUS status = STATUS_UNSUCCESSFUL; PIMAGE_DOS_HEADER mz; PIMAGE_NT_HEADERS pe; ULONG current, end, i; SIZE_T size = sizeof(code); mz = (PIMAGE_DOS_HEADER)ntosbase; pe = (PIMAGE_NT_HEADERS)((ULONG)ntosbase + mz->e_lfanew); *result = 0; current = ntosbase; end = ntosbase + pe->OptionalHeader.SizeOfImage - sizeof(code); __try { while (current < end) { if (RtlCompareMemory((PVOID)current, code, size) == size) { // WARNING! // the hook func CAN'T work in Win2K3! refer to wrk, // the ULONG64 was pushed in stack instead of the pointer // for (i = 0; i < 32; i++) { if (*(PUSHORT)(current - i) == 0x5653) { *result = current - i; DbgPrint("KeInterlockedSwapPte = %08X", *result); status = STATUS_SUCCESS; break; } } } current++; } } __except(EXCEPTION_EXECUTE_HANDLER) { DbgPrint("Failed to retrive KeInterlockedSwapPte"); *result = 0; return STATUS_FAIL_GET_KESWAPPTE; } return status; } VOID HookKeInterlockedSwapPte() { ULONG func = g_KeInterlockedSwapPte; ULONG newlowpart, newhighpart; UCHAR opcode[8] = {0x90}; opcode[0] = 0xE9; *(PULONG)&opcode[1] = (ULONG)KeInterlockedSwapPte - (func+5); newlowpart = *(PULONG)&opcode[0]; newhighpart = *(PULONG)&opcode[4]; DisableWP __asm { pushad mov esi, func mov edi, offset g_SavedSwapPte mov edx, [esi+4] mov [edi+4], edx // save the old opcode mov eax, [esi] mov [edi], eax mov ecx, newhighpart mov ebx, newlowpart __swapagain: lock cmpxchg8b qword ptr [esi] jne __swapagain popad } EnableWP DbgPrint("Hook KeInterlockedSwapPte OK"); } VOID __declspec(naked) KeInterlockedSwapPte() { // // 这里的代码适用于xp,WRK压栈的是ULONG64,不是指针,要修改 // // ; ULONGLONG // ; InterlockedExchangePte ( // ; IN OUT PMMPTE Destination, // ; IN ULONGLONG Exchange // ; ) // // push ebx // push esi // mov ebx, [esp] + 16 ; ebx = NewPteContents lowpart // mov ecx, [esp] + 20 ; ecx = NewPteContents highpart // mov esi, [esp] + 12 ; esi = PtePointer __asm { push ebx push esi mov ebx, dword ptr [esp+10h] // ebx = pointer to Exchange mov esi, dword ptr [esp+0Ch] // esi = PtePointer mov ecx, dword ptr [ebx+4] // ecx = NewPteContents highpart mov ebx, dword ptr [ebx] // ebx = NewPteContents lowpart mov edx, dword ptr [esi+4] // edx = OldPteContents highpart mov eax, dword ptr [esi] // eax = OldPteContents lowpart, return old contents in edx:eax __swapagain: lock cmpxchg8b qword ptr [esi] jne __swapagain // if z clear, exchange failed pushad // if debuggee, fuck up nx call dword ptr [IoGetCurrentProcess] cmp eax, g_ObjProc jne __end cmp esi, g_PteStart jb __end cmp esi, g_PteEnd ja __end or dword ptr [esi+4], 80000000h //管用的就是这句 __end: popad pop esi pop ebx ret 8 } } volatile __declspec(naked) void NewInt0E_PAE() { // // - Interrupt 0E Handler - // // offset | contains // ---------+----------------------------- // esp : Error Code // esp + 4 : EIP Context // esp + 8 : CS Context // esp + C : EFLAGS // __asm { pushad push fs push ds push es mov eax, 30h mov fs, ax mov eax, 23h mov ds, ax mov es, ax call dword ptr [IoGetCurrentProcess] cmp eax, g_ObjProc // debuggee? jne __oldint0e mov eax, [esp+20h+0Ch] // error code test eax, 1 // not present je __oldint0e test eax, 4 je __oldint0e // skip kernel mode page fault cmp g_HookMem, 0 je __oldint0e mov eax, cr2 // the faulting address cmp eax, g_HookStart jb __oldint0e cmp eax, g_HookEnd jae __oldint0e cmp eax, [esp+20h+0Ch+4] // eip jne __oldint0e // because of execution pop es pop ds pop fs popad add esp, 4 // discard error code jmp g_KiTrap01 // fuck up int1 __oldint0e: pop es pop ds pop fs popad jmp g_KiTrap0E } }