aboutsummaryrefslogtreecommitdiff
path: root/DetourHook64.cpp
blob: 47683ea45d7b5f43b3c767ea348119608885ebd6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include "DetourHook64.h"
#include <cstdio>



//Detours x64 functions. The shellcode passed is expected to be relocated already
BYTE* DetourHook64::Hook(BYTE* hookAddress, BYTE* shellcode, int shellcodeSize, uint64_t jmpBack, int length, int pageSize)
{
	//Save original to be able to unhook
	this->shellcodeSize = shellcodeSize;
	this->hookAddress = hookAddress;
	this->pageSize = pageSize;
	this->originalBytes = new BYTE[length];

	//Make original code writeable (.text segment usually read only). 
	DWORD oldProtection;
	if (!VirtualProtect(hookAddress, length, PAGE_EXECUTE_READWRITE, &oldProtection))
	{
		return NULL; //Couldn't make memory writeable
	}

	for (int i = 0; i < length; i++)
	{
		this->originalBytes[i] = hookAddress[i];
	}
	
	//Create VirtualMemoryPage somewhere (NULL) lets system decide
	trampoline = (BYTE*)VirtualAlloc(NULL, pageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);

	if (!trampoline)
	{
		return NULL; //Couldn't allocate virtual memory
	}

	//Copy shellcode into new memory page
	for (int i = 0; i < shellcodeSize; i++)
	{
		trampoline[i] = shellcode[i];
	}

	//Add jump back to original code into new memory
	trampoline[shellcodeSize] = 0xFF;								//opcodes = JMP [rip+0]
	trampoline[shellcodeSize + 1] = 0x25;							//opcodes = JMP [rip+0]
	*(uint32_t*)(&trampoline[shellcodeSize + 2]) = 0;				//relative distance from RIP (+0) 
	*(uint64_t*)(&trampoline[shellcodeSize + 2 + 4]) = jmpBack; 	//destination to jump to

	//Jump to allocated code
	hookAddress[0] = 0xFF;											//opcodes = JMP [rip+0]
	hookAddress[1] = 0x25;											//opcodes = JMP [rip+0]
	*(uint32_t*)(&hookAddress[2]) = 0;								//relative distance from RIP (+0) 
	*(uint64_t*)(&hookAddress[2 + 4]) = (uint64_t)trampoline;	//destination to jump to

	//Restore page protection
	if (!VirtualProtect(hookAddress, length, oldProtection, &oldProtection))
	{
		VirtualFree(trampoline, pageSize, MEM_RELEASE);
		return NULL; //Couldn't restore memory protection
	}

	return trampoline;
}



bool DetourHook64::Unhook()
{
	DWORD oldProtection;
	if (!VirtualProtect(hookAddress, 14, PAGE_EXECUTE_READWRITE, &oldProtection))
	{
		return false; //Couldn't make memory writeable
	}

	memcpy(hookAddress, originalBytes, 14);
	VirtualFree(trampoline, pageSize, MEM_RELEASE);
	delete[] originalBytes;

	if (!VirtualProtect(hookAddress, 14, oldProtection, &oldProtection))
	{
		return false; //Couldn't restore memory protection
	}

	return true;
}