用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
}
}