-
Notifications
You must be signed in to change notification settings - Fork 1
/
Hooks.cpp
154 lines (143 loc) · 4.64 KB
/
Hooks.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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//https://github.com/nizikawa-worms/wkJellyWorm/blob/master/src/Hooks.cpp
#include "Hooks.h"
#include <stdexcept>
#include <sstream>
#include <fstream>
#include "libs/hacklib/PatternScanner.h"
#include "include/MinHook.h"
void Hooks::minhook(std::string name, DWORD pTarget, DWORD* pDetour, DWORD* ppOriginal) {
if (!pTarget)
throw std::runtime_error("Hook adress is null: " + name);
if (hookNameToAddr.find(name) != hookNameToAddr.end())
throw std::runtime_error("Hook name reused: " + name);
if (hookAddrToName.find(pTarget) != hookAddrToName.end()) {
std::stringstream ss;
ss << "The specified address is already hooked: " << name << "(0x" << std::hex << pTarget << "), " << hookAddrToName[pTarget];
throw std::runtime_error(ss.str());
}
auto wut = MH_CreateHook((LPVOID)pTarget, (LPVOID)pDetour, (LPVOID*)ppOriginal);
if (wut != MH_OK)
throw std::runtime_error("Failed to create hook: " + name);
if (MH_EnableHook((LPVOID)pTarget) != MH_OK)
throw std::runtime_error("Failed to enable hook: " + name);
hookAddrToName[pTarget] = name;
hookNameToAddr[name] = pTarget;
printf("minhook: %s 0x%X -> 0x%X\n", name.c_str(), pTarget, pDetour);
}
//Worms development tools by StepS
BOOL Hooks::PatchMemData(PVOID pAddr, size_t buf_len, PVOID pNewData, size_t data_len) {
if (!buf_len || !data_len || !pNewData || !pAddr || buf_len < data_len) {
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
DWORD dwLastProtection;
if (!VirtualProtect((void*)pAddr, data_len, PAGE_EXECUTE_READWRITE, &dwLastProtection))
return 0;
memcpy_s(pAddr, buf_len, pNewData, data_len);
return VirtualProtect((void*)pAddr, data_len, dwLastProtection, &dwLastProtection);
}
#define IJ_JUMP 0 //Insert a jump (0xE9) with InsertJump
#define IJ_CALL 1 //Insert a call (0xE8) with InsertJump
#define IJ_FARJUMP 2 //Insert a farjump (0xEA) with InsertJump
#define IJ_FARCALL 3 //Insert a farcall (0x9A) with InsertJump
#define IJ_PUSHRET 4 //Insert a pushret with InsertJump
BOOL Hooks::InsertJump(PVOID pDest, size_t dwPatchSize, PVOID pCallee, DWORD dwJumpType) {
if (dwPatchSize >= 5 && pDest) {
DWORD OpSize = 5, OpCode = 0xE9;
PBYTE dest = (PBYTE)pDest;
switch (dwJumpType) {
case IJ_PUSHRET:
OpSize = 6;
OpCode = 0x68;
break;
case IJ_FARJUMP:
OpSize = 7;
OpCode = 0xEA;
break;
case IJ_FARCALL:
OpSize = 7;
OpCode = 0x9A;
break;
case IJ_CALL:
OpSize = 5;
OpCode = 0xE8;
break;
default:
OpSize = 5;
OpCode = 0xE9;
break;
}
if (dwPatchSize < OpSize)
return 0;
PatchMemVal(dest, (BYTE)OpCode);
switch (OpSize) {
case 7:
PatchMemVal(dest + 1, pCallee);
WORD w_cseg;
__asm mov[w_cseg], cs;
PatchMemVal(dest + 5, w_cseg);
break;
case 6:
PatchMemVal(dest + 1, pCallee);
PatchMemVal<BYTE>(dest + 5, 0xC3);
break;
default:
PatchMemVal(dest + 1, (ULONG_PTR)pCallee - (ULONG_PTR)pDest - 5);
break;
}
for (size_t i = OpSize; i < dwPatchSize; i++)
PatchMemVal<BYTE>(dest + i, 0x90);
}
return 0;
}
void Hooks::hookAsm(DWORD startAddr, DWORD hookAddr) {
printf("hookAsm: 0x%X -> 0x%X\n", startAddr, hookAddr);
InsertJump((PVOID)startAddr, 6, (PVOID)hookAddr, IJ_PUSHRET);
}
void Hooks::patchAsm(DWORD addr, unsigned char* op, size_t opsize) {
printf("patchAsm: 0x%X : ", addr);
for (size_t i = 0; i < opsize; i++) {
printf("%02X ", *(unsigned char*)(addr + i));
}
printf(" -> ");
for (size_t i = 0; i < opsize; i++) {
printf("%02X ", op[i]);
}
printf("\n");
PatchMemData((PVOID)addr, opsize, (PVOID)op, opsize);
}
void Hooks::hookVtable(const char* classname, int offset, DWORD addr, DWORD hookAddr, DWORD* original) {
printf("hookVtable: %s::0x%X 0x%X -> 0x%X\n", classname, offset, *(DWORD*)addr, addr);
*original = *(DWORD*)addr;
int dest = hookAddr;
PatchMemData((PVOID)addr, sizeof(dest), &dest, sizeof(dest));
}
DWORD Hooks::scanPattern(const char* name, const char* pattern, const char* mask, DWORD expected) {
uintptr_t ret = 0;
//rebase offsets in cached file
if (!hl::PatternScanner::WAregion.base) {
hl::FindPatternMask(pattern, mask);
for (auto& it : scanNameToAddr) {
it.second = it.second + (hl::PatternScanner::WAregion.base - 0x401000);
scanAddrToName[it.second] = it.first;
}
}
auto it = scanNameToAddr.find(name);
if (it == scanNameToAddr.end()) {
ret = hl::FindPatternMask(pattern, mask);
printf("scanPattern: %s = 0x%X\n", name, ret);
if (!ret) {
std::string msg = "scanPattern: failed to find memory pattern: ";
msg += name;
throw std::runtime_error(msg);
}
scanNameToAddr[name] = ret;
scanAddrToName[ret] = name;
scanFoundNew = true;
}
else {
ret = it->second;//scanNameToAddr[name];
printf("scanCache: %s = 0x%X\n", name, ret);
}
return ret;
}