- Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBetterRandom.cpp
More file actions
Latest commit
200 lines (166 loc) · 6.51 KB
/
Copy pathBetterRandom.cpp
File metadata and controls
200 lines (166 loc) · 6.51 KB
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#include<Windows.h>
#include<detours.h>
#include<random>
#include<psapi.h>
#include<winnt.h>
#include<dbghelp.h>
// Original function pointer
typedefint(WINAPI *OriginalRandFunc)();
// Pointer to the original rand() function
OriginalRandFunc pOriginalRand = NULL;
std::random_device rd; // Non-deterministic random number generator
std::uniform_int_distribution<> dist(0, INT_MAX); // Distribute results between INT_MIN and RAND_MAX
std::mt19937 gen(rd()); // Seed Mersenne Twister generator
// Typedef for the original function
typedefint (*OriginalFunc)(int);
// Pointer to the original function
OriginalFunc pOriginalFunction = nullptr;
// Hooked function for rand()
__declspec(dllexport) int WINAPI HookedRand()
{
// Call the custom implementation instead of the original function
returndist(gen);
}
/**
* Match a pattern against data.
* @param data The data to match against.
* @param pattern The pattern to match.
* @param length The length of the pattern.
* @return True if the pattern matches the data, false otherwise.
*/
boolMatchPattern(constunsignedchar *data, constunsignedchar *pattern, int length)
{
for (int i = 0; i < length; ++i)
{
// Skip certain characters in the pattern
if (pattern[i] == '.')
continue;
// If the characters don't match, return false
if (data[i] != pattern[i])
returnfalse;
}
returntrue;
}
/**
* Find the offset of a function within a module using a pattern.
* @param hModule Handle to the module to search within.
* @param pattern The pattern to search for.
* @param length The length of the pattern.
* @return The offset of the function if found, or 0x0 if not found.
*/
LPBYTEFindFunctionOffset(HMODULE hModule, constunsignedchar *pattern, int length)
{
// Get the base address of the module
auto moduleBase = reinterpret_cast<DWORD_PTR>(hModule);
// Get the module's PE header
auto ntHeader = ImageNtHeader(hModule);
if (!ntHeader)
return0x0; // Invalid PE header
// Get the image section header
auto sectionHeader = IMAGE_FIRST_SECTION(ntHeader);
if (!sectionHeader)
return0x0; // Invalid section header
// Search within the module's code section
IMAGE_SECTION_HEADER *codeSectionHeader = nullptr;
for (int i = 0; i < ntHeader->FileHeader.NumberOfSections; ++i)
{
if (sectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE)
{
codeSectionHeader = sectionHeader;
break;
}
sectionHeader++;
}
if (!codeSectionHeader)
return0x0; // Code section not found
// Search for the pattern within the code section
auto codeSectionMemory = reinterpret_cast<constunsignedchar *>(moduleBase + codeSectionHeader->VirtualAddress);
auto endAddress = codeSectionMemory + codeSectionHeader->Misc.VirtualSize - 2;
for (; codeSectionMemory < endAddress; codeSectionMemory++)
{
if (MatchPattern(codeSectionMemory, pattern, length))
return (LPBYTE)codeSectionMemory;
}
// Pattern not found
return0x0;
}
/**
* Initialize the hook by finding the target function and attaching the custom implementation.
*/
voidInitHook()
{
// Get the address of the target function
auto hModule = GetModuleHandle(nullptr);
LPBYTE pFunctionAddress = 0x0;
// Find the offset of the target function using specific patterns
// Pattern for Baldur's Gate EE, Baldur's Gate 2 EE, Icewind Dale EE
unsignedchar pattern1[] = "\x48\x83..\xE8.......\xFD\x43\x03\x00";
if (pFunctionAddress == 0x0)
pFunctionAddress = FindFunctionOffset(hModule, pattern1, sizeof(pattern1) - 1);
// Pattern for Planescape EE
unsignedchar pattern2[] = "\xE8.......\xFD\x43\x03\x00";
if (pFunctionAddress == 0x0)
pFunctionAddress = FindFunctionOffset(hModule, pattern2, sizeof(pattern2) - 1);
// Pattern for Baldur's Gate, Baldur's Gate 2, Icewind Dale, Planescape Torment
unsignedchar pattern3[] = "\xE8....\x8B....\xFD\x43\x03\x00";
if (pFunctionAddress == 0x0)
pFunctionAddress = FindFunctionOffset(hModule, pattern3, sizeof(pattern3) - 1);
if (pFunctionAddress == 0x0)
{
MessageBoxA(NULL, "original rand() method not found!", "betterrand.dll Error", MB_OK);
throw("Error: original rand() method not found!");
}
// Obtain system information
SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo);
// Retrieve the base address of the application
auto baseAddress = systemInfo.lpMinimumApplicationAddress;
// Calculate the scan size by subtracting the minimum application address from the maximum application address
auto scanSize = reinterpret_cast<SIZE_T>(systemInfo.lpMaximumApplicationAddress) - reinterpret_cast<SIZE_T>(systemInfo.lpMinimumApplicationAddress);
// Get module info
MODULEINFO modinfo = {NULL};
GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof(modinfo));
// Create a trampoline for the original function
auto pOriginalFunction = reinterpret_cast<OriginalRandFunc>(pFunctionAddress);
// Detour the function with the custom implementation
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID &)pOriginalFunction, HookedRand);
DetourTransactionCommit();
}
/**
* Remove the hook by detaching the custom implementation from the target function.
*/
voidRemoveHook()
{
// Detach the hook
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID &)pOriginalRand, HookedRand);
DetourTransactionCommit();
}
/**
* Entry point of the DLL.
* @param hinst The handle to the DLL module.
* @param dwReason The reason for calling the DLL entry point.
* @param reserved Reserved parameter.
* @return True if the DLL was initialized successfully, false otherwise.
*/
BOOLWINAPIDllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
{
if (DetourIsHelperProcess())
{
returnTRUE;
}
if (dwReason == DLL_PROCESS_ATTACH)
{
// Initialize the hook when the DLL is loaded
InitHook();
}
elseif (dwReason == DLL_PROCESS_DETACH)
{
// Remove the hook when the DLL is unloaded
RemoveHook();
}
returnTRUE;
}