NtProtectVirtualMemory hook problem

06/15/2012 12:26 Lazeboy#1
Hey,
ich versuche gerade "NtProtectVirtualMemory" zu hooken und stoße auf ein ungewöhnliches Problem.

Wieso führt das zum Crash?
Code:
NTSTATUS NTAPI hkNtProtectVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddr, PULONG NumberBytes, ULONG NewAccessProt, PULONG OldAccessProt)
{
	return oNtProtectVirtualMemory(ProcessHandle, BaseAddr, NumberBytes, NewAccessProt, OldAccessProt);
}
und das nicht.

Code:
NTSTATUS NTAPI hkNtProtectVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddr, PULONG NumberBytes, ULONG NewAccessProt, PULONG OldAccessProt)
{
	return 0;
}
Ich mache ja eig. nicht besonderes ausser nen normalen hook durchzuführen.
mfg Lazeboy
06/15/2012 12:48 Dr. Coxxy#2
weil das programm dann ne protection durchführt, sich z.b. schreibrechte holt und dann beim darauffolgenden schreiben failt, da er in wirklichkeit keine rechte hat?

muss ja net unbedingt das return 0 auswerten, oder entscheidet sich für nen exit(0) bei nem fehler :P
06/15/2012 13:00 Lazeboy#3
was kann ich denn tun um das zu hooken ich will ja die Funktion normal ausführen lassen und nicht irgendwelche status werte zurückgeben.
06/15/2012 13:08 Dr. Coxxy#4
ups hab mich verlesen...

dachte das obere würde funtzen und das untere nicht - und nicht umgekehrt :P

zeig mal wie du hookst, aber eigtl komisch.

EDIT:
wahrscheinlich erstellste dein trampolin nicht richtig, oder aufm trampolin sind keine execute rechte.
06/15/2012 13:21 Lazeboy#5
Code:
typedef NTSTATUS (NTAPI* pNtProtectVirtualMemory)(HANDLE, PVOID, PULONG, ULONG, PULONG);
pNtProtectVirtualMemory oNtProtectVirtualMemory = NULL;
Detour Func
Code:
void *DetourFunc(BYTE *src, const BYTE *dst, const int len) // credits to gamedeception
{
	BYTE *jmp = (BYTE*)malloc(len+5);
	DWORD dwback;
	VirtualProtect(src, len, PAGE_READWRITE, &dwback);
	memcpy(jmp, src, len); jmp += len;
	jmp[0] = 0xE9;
	*(DWORD*)(jmp+1) = (DWORD)(src+len - jmp) - 5;
	src[0] = 0xE9;
	*(DWORD*)(src+1) = (DWORD)(dst - src) - 5;
	VirtualProtect(src, len, dwback, &dwback);
	return (jmp-len);
}
Code:
HMODULE ntdllMod = GetModuleHandle("ntdll.dll");
DWORD NtProtectVirtualMemoryAddr = (DWORD)GetProcAddress(ntdllMod, "NtProtectVirtualMemory");
if(NtProtectVirtualMemoryAddr!= 0)
	{
		oNtProtectVirtualMemory= (pNtProtectVirtualMemory)DetourFunc((PBYTE)NtProtectVirtualMemoryAddr, (PBYTE)&hkNtProtectVirtualMemory, 5);	
	}
joa und dann noch die neue Funktionen
Code:
NTSTATUS NTAPI hkNtProtectVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddr, PULONG NumberBytes, ULONG NewAccessProt, PULONG OldAccessProt)
{
	
	return oNtProtectVirtualMemory(ProcessHandle, BaseAddr, NumberBytes, NewAccessProt, OldAccessProt);
}
06/15/2012 13:24 Dr. Coxxy#6
jop, dein trampolin hat keine execute rechte, entweder du
(Data Execution Prevention) von windoof, oder du benutzst z.b. die funktion hier:
Code:
void* DetourFunc(PBYTE src, const PBYTE dst, const int len)
{
	DWORD dwback;
	BYTE* jmp = (BYTE*)malloc(len+5);
	VirtualProtect(jmp, len+5, PAGE_EXECUTE_READWRITE, &dwback);
	VirtualProtect(src, len, PAGE_READWRITE, &dwback);
	memcpy(jmp, src, len);
	jmp += len;
	jmp[0] = 0xE9;
	*(DWORD*)(jmp+1) = (DWORD)(src + len - jmp) - 5;
	src[0] = 0xE9;
	*(DWORD*)(src+1) = (DWORD)(dst - src) - 5;
	for (int i = 5; i < len; i++)
	{
		src[i] = 0x90;
	}
	VirtualProtect(src, len, dwback, &dwback);
	return (jmp - len);
}
06/15/2012 13:31 Lazeboy#7
ich bedanke mich ;)


EDIT: crasht aber leider immer noch sowohl bei der neuen detour func und beim ausschalten von DEP bei windows
06/15/2012 13:49 Dr. Coxxy#8
dann mach dep mal wieder an, gibts nicht ohne grund.

sehe jetzt so keinen fehler mehr, vllt hast du mit den parametern mist gebaut, oder in der funktion sind am anfang keine 5 bytes frei/genau am ende von nem asm befehl, musst du mal mitm debugger rübergucken.

oder benutz die microsoft detour lib, die achtet auf sowas eigtl.
06/15/2012 14:23 Ende!#9
Das ist recht einfach zu begründen. Dein Aufruf wird ja in etwa so aussehen:
Code:
oNtProtectVirtualMemory = (oNtProtectVirtualMemory_t)DetourFunc((PBYTE)pNtPVM, (PBYTE)hkNtProtectVirtualMemory, 5);
Wenn du jetzt noch mal einen Blick auf deine Detour-Function wirfst, wird dir auffallen, dass diese VirtualProtect aufruft, welche dann wiederrum auf die NtProtectVirtualMemory Funktion der ntdll zurückgreift, NACHDEM bereits der Execution-Flow umgeleitet wurde. Der Pointer enthält folglich noch nicht den Pointer zum Trampoline, da DetourFunc noch nicht returned ist.

Add:
Code:
void DetourFunc(PBYTE src, const PBYTE dst, void **ppTramponline, const int len)
{
	DWORD dwback;
	BYTE* jmp = (BYTE*)malloc(len+5);
	VirtualProtect(jmp, len+5, PAGE_EXECUTE_READWRITE, &dwback);
	VirtualProtect(src, len, PAGE_READWRITE, &dwback);
	memcpy(jmp, src, len);
	jmp += len;
	jmp[0] = 0xE9;
	*(DWORD*)(jmp+1) = (DWORD)(src + len - jmp) - 5;
	src[0] = 0xE9;
	*(DWORD*)(src+1) = (DWORD)(dst - src) - 5;
	for (int i = 5; i < len; i++)
	{
		src[i] = 0x90;
	}
        *ppTrampoline = (jmp - len);
	VirtualProtect(src, len, dwback, &dwback);
}
Code:
DetourFunc((PBYTE)pNtPVM, (PBYTE)hkNtProtectVirtualMemory, &oNtProtectVirtualMemory, 5);
So würde das Ganze funktionieren, da der Pointer so direkt mit dem korrekten Wert gefüllt wird.

Im Übrigen möchte ich anmerken, dass DetourFunc schrecklich implementiert ist - ich empfehle dir die Verwendung einer Detour-Librarys wie die von Microsoft.
06/15/2012 14:42 Lazeboy#10
dann kann ich doch einfach die addr als ptr urückgeben also als 4. parameter oder ? :D

nur ich stell mir die frage bei der detour function wird ja zuerst das Trampolin vervollständigt und nachdem alles vorbereitet ist sozusagen wird der Execution Flow umgeleitet.

Also zuerst Trampolin
Code:
BYTE* jmp = (BYTE*)malloc(len+5);
	VirtualProtect(jmp, len+5, PAGE_EXECUTE_READWRITE, &dwback);
	VirtualProtect(src, len, PAGE_READWRITE, &dwback);
	memcpy(jmp, src, len);
	jmp += len;
	jmp[0] = 0xE9;
	*(DWORD*)(jmp+1) = (DWORD)(src + len - jmp) - 5;
und dann die umleitung aufs Trampolin also sollte doch eig. alles den richtigen weg nehmen oder ?
Code:
src[0] = 0xE9;
	*(DWORD*)(src+1) = (DWORD)(dst - src) - 5;
Achja was ich vlt vergessen habe zu sagen es crasht direkt nach dem injecten.



Edit:
ahh ok ich teste es mal ^^


Edit2:
Danke
ja es funktioniert jetzt nur bin ich mir da immer noch nicht genau im klaren wieso das davor nicht funktioniert hat, weil s.o :(

Edit3:
omg ich habs gerafft das letzte VirtualProtect vor dem return :( ok danke für die Hilfe
06/15/2012 14:53 Dr. Coxxy#11
Quote:
Originally Posted by Ende! View Post
Das ist recht einfach zu begründen. Dein Aufruf wird ja in etwa so aussehen:
Code:
oNtProtectVirtualMemory = (oNtProtectVirtualMemory_t)DetourFunc((PBYTE)pNtPVM, (PBYTE)hkNtProtectVirtualMemory, 5);
Wenn du jetzt noch mal einen Blick auf deine Detour-Function wirfst, wird dir auffallen, dass diese VirtualProtect aufruft, welche dann wiederrum auf die NtProtectVirtualMemory Funktion der ntdll zurückgreift, NACHDEM bereits der Execution-Flow umgeleitet wurde. Der Pointer enthält folglich noch nicht den Pointer zum Trampoline, da DetourFunc noch nicht returned ist.

Add:
Code:
void DetourFunc(PBYTE src, const PBYTE dst, void **ppTramponline, const int len)
{
	DWORD dwback;
	BYTE* jmp = (BYTE*)malloc(len+5);
	VirtualProtect(jmp, len+5, PAGE_EXECUTE_READWRITE, &dwback);
	VirtualProtect(src, len, PAGE_READWRITE, &dwback);
	memcpy(jmp, src, len);
	jmp += len;
	jmp[0] = 0xE9;
	*(DWORD*)(jmp+1) = (DWORD)(src + len - jmp) - 5;
	src[0] = 0xE9;
	*(DWORD*)(src+1) = (DWORD)(dst - src) - 5;
	for (int i = 5; i < len; i++)
	{
		src[i] = 0x90;
	}
        *ppTrampoline = (jmp - len);
	VirtualProtect(src, len, dwback, &dwback);
}
Code:
DetourFunc((PBYTE)pNtPVM, (PBYTE)hkNtProtectVirtualMemory, &oNtProtectVirtualMemory, 5);
So würde das Ganze funktionieren, da der Pointer so direkt mit dem korrekten Wert gefüllt wird.

Im Übrigen möchte ich anmerken, dass DetourFunc schrecklich implementiert ist - ich empfehle dir die Verwendung einer Detour-Librarys wie die von Microsoft.
hat natürlich vollkommen recht, garnicht dran gedacht, dass du da vp hookst :P