22#include < spdlog/spdlog.h>
33#include " memory.hpp"
44#include " globals.hpp"
5+
56namespace ManualMapper {
67 struct Detour {
7- ULONGLONG stubAddr;
8- ULONGLONG stubSize;
9- ULONGLONG targetAddr;
8+ ULONGLONG allocAddr;
9+ ULONGLONG size;
10+ ULONGLONG originalJmp;
11+ };
12+ struct Allocation {
13+ ULONGLONG base;
14+ ULONGLONG size;
15+ };
16+ struct FunctionResult {
17+ std::vector<UCHAR> funcBytes;
18+ ULONGLONG base;
1019 };
1120 enum Status {
12- STATUS_BUSY ,
21+ STATUS_UNSET ,
1322 STATUS_1,
1423 STATUS_2,
1524 STATUS_3,
@@ -18,156 +27,27 @@ namespace ManualMapper {
1827 };
1928
2029 // allocates and writes the dll to the target process
21- HMODULE _allocDll (HANDLE handle, const std::string& dllPath);
22-
30+ Allocation _allocDll (HANDLE handle, const std::string& dllPath);
2331 // alloctes a piece of memory to hold the status of the hook, for communication internal and external
2432 LPVOID _createStatus (HANDLE handle);
2533
2634 // this detour will be jmped to by our hooked function which will then jmp to our dll :D
2735 // this function writes the function bytes of the detour and allocates valuable data with it
2836 // return statement exclusive
37+ FunctionResult _parseFunction (ULONGLONG funcBase, ULONGLONG size);
2938 ULONGLONG _calculateLocalFuncSize (ULONGLONG funcBase);
3039
31- template <typename RetType, typename ...Args>
32- ULONGLONG _createDetour (HANDLE handle, RetType(*targetFunction)(Args...), ULONGLONG dllAddr, ULONGLONG stub, ULONGLONG f) {
33-
34- MemExternal::suspendByfronThreads (handle);
35- ULONGLONG targetFuncSize = _calculateLocalFuncSize ((ULONGLONG)targetFunction);
36- ULONGLONG statusAddr = (ULONGLONG)_createStatus (handle);
37- ULONGLONG originalJmp = MemExternal::readJmpAbs (handle, stub);
38-
39- // get func bytes
40- UCHAR* funcBytes = new UCHAR[targetFuncSize+200 ];
41- // restore the original jump
42- // mov rax, stub
43- *(UCHAR*)funcBytes = 0x48 ;
44- *(UCHAR*)(funcBytes + 1 ) = 0xB8 ;
45- *(ULONGLONG*)(funcBytes + 2 ) = stub + 6 ;
46-
47- // mov rcx, original
48- *(UCHAR*)(funcBytes + 10 ) = 0x48 ;
49- *(UCHAR*)(funcBytes + 11 ) = 0xB9 ;
50- *(ULONGLONG*)(funcBytes + 12 ) = originalJmp;
51-
52- // mov [rax], rcx
53- *(UCHAR*)(funcBytes + 20 ) = 0x48 ;
54- *(UCHAR*)(funcBytes + 21 ) = 0x89 ;
55- *(UCHAR*)(funcBytes + 22 ) = 0x08 ;
56-
57- UCHAR* targetFunctionBytes = funcBytes + 23 ;
58-
59- // set the status to the hook was ran
60- *(UCHAR*)targetFunctionBytes = 0x48 ;
61- *(UCHAR*)(targetFunctionBytes + 1 ) = 0xB8 ;
62- *(ULONGLONG*)(targetFunctionBytes + 2 ) = statusAddr;
63- *(UCHAR*)(targetFunctionBytes + 10 ) = 0xC7 ;
64- *(UCHAR*)(targetFunctionBytes + 11 ) = 0x00 ;
65- *(ULONG*)(targetFunctionBytes + 12 ) = Status::STATUS_1;
66-
67- targetFunctionBytes += 16 ;
68- // copy the detour function bytes
69- memcpy (targetFunctionBytes, (LPVOID)((ULONGLONG)targetFunction), targetFuncSize);
70-
71- // allocate memory for entire detour
72- LPVOID detourFunctionAlloc = VirtualAllocEx (handle, nullptr , 0x1000 , MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
73-
74- // replace its stack placeholders with the real addr were going to use
75- // stack is located in the allocation right after the function
76-
77- ULONGLONG stackAddr = (ULONGLONG)detourFunctionAlloc + targetFuncSize+200 ;
78-
79- for (ULONGLONG offset = 0 ; offset < targetFuncSize; offset++) {
80- UCHAR* currentBytes = targetFunctionBytes + offset;
81- if (*(ULONGLONG*)(currentBytes) == SCF_STACK_PLACEHOLDER) {
82- *(ULONGLONG*)(currentBytes) = stackAddr;
83- offset += sizeof (ULONGLONG);
84- continue ;
85- }
86- }
87-
88-
89- {
90- // right at the end
91- UCHAR* currentBytes = targetFunctionBytes + targetFuncSize;
92-
93- // set the status
94- *(UCHAR*)currentBytes = 0x48 ;
95- *(UCHAR*)(currentBytes + 1 ) = 0xB8 ;
96- *(ULONGLONG*)(currentBytes + 2 ) = statusAddr;
97- *(UCHAR*)(currentBytes + 10 ) = 0xC7 ;
98- *(UCHAR*)(currentBytes + 11 ) = 0x00 ;
99- *(ULONG*)(currentBytes + 12 ) = Status::STATUS_SUCCESS;
100-
101- UCHAR* currentBytes1 = currentBytes + 16 ;
102-
103- // redirect control flow back to where it was supposed to go
104- *(UCHAR*)(currentBytes1) = 0xFF ;
105- *(UCHAR*)(currentBytes1 + 1 ) = 0x25 ;
106- *(ULONG*)(currentBytes1 + 2 ) = 0x00000000 ;
107- *(ULONGLONG*)(currentBytes1 + 6 ) = ((ULONGLONG)originalJmp);
108-
109- }
110-
111-
112- // fill the stack with actual data
113- std::vector<ULONGLONG> stack = {};
114- stack.push_back (dllAddr);
115- stack.push_back (statusAddr);
116-
117- HMODULE kernelBase = MemExternal::getLoadedModule (handle," KERNELBASE.dll" );
118- ULONGLONG pLoadLibraryA = (ULONGLONG)GetProcAddress (kernelBase, " LoadLibraryA" );
119- stack.push_back (pLoadLibraryA);
120- ULONGLONG pGetProcAddress = (ULONGLONG)GetProcAddress (kernelBase, " GetProcAddress" );
121- stack.push_back (pGetProcAddress);
122- ULONGLONG pGetModuleHandleA = (ULONGLONG)GetProcAddress (kernelBase, " GetModuleHandleA" );
123- stack.push_back (pGetModuleHandleA);
124-
125- // write the stack
126- ULONGLONG stackAddrEnum = stackAddr;
127- for (ULONGLONG each : stack) {
128- if (!WriteProcessMemory (handle, (LPVOID)stackAddrEnum, &each, sizeof (ULONGLONG), 0 )) {
129- spdlog::error (" Failed to write stack data! Err: {}" , GetLastError ());
130- break ;
131- }
132- stackAddrEnum += sizeof (ULONGLONG);
133- }
134-
135- if (!WriteProcessMemory (handle, detourFunctionAlloc, funcBytes, targetFuncSize + 200 , 0 )) {
136- spdlog::error (" Failed to write target func byte data! Err: {}" , GetLastError ());
137- }
138-
139- MemExternal::writeJmpAbs (handle, stub, (ULONGLONG)detourFunctionAlloc);
140- FlushInstructionCache (handle, (LPVOID)stub, 12 );
141-
142- // we have to make the piece of memory that had our original jump writable so that our detour code and restore it
143- ULONG oldProt;
144- VirtualProtectEx (handle, (LPVOID)(stub + 6 ), sizeof (ULONGLONG), PAGE_EXECUTE_READWRITE, &oldProt);
145-
146- ULONG lastStatus = -1 ;
147- while (true ) {
148- ULONG status = 0 ;
149- if (!ReadProcessMemory (handle, (LPVOID)statusAddr, &status, sizeof (status), 0 )) {
150- spdlog::error (" Failed to read status! Err: {}" , GetLastError ());
151- break ;
152- }
153- if (lastStatus != status) {
154- spdlog::info (" Status: {}" , status);
155- }
156- if (status == Status::STATUS_SUCCESS) {
157- spdlog::info (" successfully reached the end of the hook" );
158- MemExternal::resumeByfronThreads (handle);
159-
160- // VirtualFreeEx(handle, detourFunctionAlloc, targetFuncSize + 200, MEM_RELEASE);
161- // VirtualProtectEx(handle, (LPVOID)(stub + 6), sizeof(ULONGLONG), PAGE_EXECUTE, &oldProt);
162-
163- break ;
164- }
165- lastStatus = status;
166- }
167-
168- delete[] funcBytes;
169- return (ULONGLONG)detourFunctionAlloc;
170- }
40+ Detour _createDetour (
41+ Allocation optPreAllocatedData, // if you already allocated memory in the target process you can pass it in here
42+ HANDLE handle,
43+ LPVOID detourLocal, // the base address of the local detour function
44+ ULONGLONG stub, // the place where the absolute jmp were overriding is
45+ std::vector<ULONGLONG> stack, // the variables that the detour can use
46+ ULONGLONG statusAddr = 0 // during the hook, will move numbers into this address to signal the step in the hook its in
47+ // if status addr is set, it will also automatically restore the hook when its run once
48+ );
49+
50+ Detour _createDllDetour (HANDLE handle, LPVOID detourLocal, ULONGLONG stub, ULONGLONG dllAddr);
17151
17252 // the main function, does all the shit
17353 void inject (HANDLE handle, const std::string& dllPath);
0 commit comments