-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTrampoline.cpp
82 lines (68 loc) · 1.94 KB
/
Trampoline.cpp
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
#include "pch.h"
#include "Trampoline.h"
#include <Windows.h>
#include <exception>
#include <vector>
#include <cstdint>
#include "MemAccess.h"
Trampoline::Trampoline(intptr_t start, intptr_t end, void* func, bool destructRevert)
: target(reinterpret_cast<void*>(start))
, detour(func)
, codeData(nullptr)
, originalSize(0)
, revert(destructRevert)
{
if (start > end)
{
throw std::exception("Start address cannot exceed end address.");
}
if (end - start < 5)
{
throw std::exception("Length cannot be less than 5 bytes.");
}
originalSize = end - start;
// Copy original instructions
codeData = VirtualAlloc(nullptr, originalSize + 5, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (codeData == nullptr)
{
throw std::exception("VirtualAlloc failure.");
}
// memcpy() can be used instead of ReadProcessMemory
// because we're not reading memory from another process.
memcpy(codeData, target, originalSize);
const auto ptr = static_cast<uint8_t*>(codeData);
if (ptr[0] == 0xE8)
{
// If the start address has a function call right off the bat,
// just repair it for the sake of convenience.
intptr_t addr = start + 5 + *reinterpret_cast<intptr_t*>(&ptr[1]);
WriteCall(ptr, (void*)addr);
}
else if (ptr[0] == 0xE9)
{
// If an existing (hopefully) trampoline has been applied to this address,
// correct the jump offset for it.
intptr_t addr = start + 5 + *reinterpret_cast<intptr_t*>(&ptr[1]);
WriteJump(ptr, (void*)addr);
}
// Append jump
WriteJump(&ptr[originalSize], (void*)end);
// NOP the original code.
// NOTE: This is in .text, so we have to use WriteData().
// Using memset() will crash.
std::vector<uint8_t> nop(originalSize, 0x90);
WriteData(target, nop.data(), nop.size());
// Write a Jump to the new target function.
WriteJump(target, func);
}
Trampoline::~Trampoline()
{
if (codeData)
{
if (revert)
{
WriteData(target, codeData, originalSize);
}
VirtualFree(codeData, 0, MEM_RELEASE);
}
}