-
Notifications
You must be signed in to change notification settings - Fork 22
Expand file tree
/
Copy pathReloadLibrary.cpp
More file actions
144 lines (118 loc) · 3.41 KB
/
Copy pathReloadLibrary.cpp
File metadata and controls
144 lines (118 loc) · 3.41 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
#include <windows.h>
#include <string>
#include <fstream>
#include <ostream>
#include "ReloadLibrary.h"
template <class T>
bool writeMem(size_t address, T value)
{
*(T*)(address) = value;
return true;
}
template <class T>
T* pointMem(size_t address)
{
return (T*)address;
}
template <class T>
T readMem(size_t address)
{
return *(T*)address;
}
template <class T>
DWORD protectMem(size_t address, DWORD protection)
{
DWORD oldProtection;
VirtualProtect((LPVOID)address, sizeof(T), protection, &oldProtection);
return oldProtection;
}
bool getTemporaryFileName(std::wstring& output)
{
output = L"";
wchar_t tempPath[MAX_PATH + 1];
if (GetTempPath(sizeof(tempPath) / sizeof(wchar_t), &tempPath[0]) == 0)
return false;
wchar_t tempFile[MAX_PATH + 1];
if (GetTempFileName(tempPath, L"cln", 0, tempFile) == 0)
return false;
output = tempFile;
return true;
}
void copyFile(const std::wstring& source, const std::wstring& dest)
{
std::ifstream src(source, std::ios::binary);
std::ofstream dst(dest, std::ios::binary);
dst << src.rdbuf();
}
bool fileExists(const std::wstring& name) {
std::ifstream f(name.c_str());
return f.good();
}
HMODULE cloneLibrary(const char* libraryName)
{
// get the full path to the target module
auto targetMod = GetModuleHandleA(libraryName);
wchar_t targetName[MAX_PATH + 1];
if (GetModuleFileNameW(targetMod, targetName, sizeof(targetName) / sizeof(wchar_t)) == 0)
return nullptr;
// make a copy of it in the temp directory
std::wstring newdllname;
if (!getTemporaryFileName(newdllname))
return nullptr;
copyFile(targetName, newdllname);
if (!fileExists(newdllname))
return nullptr;
// load and ret
return LoadLibraryW(newdllname.c_str());
}
size_t ReloadLibrary(const char* libraryName, void* _mod)
{
auto mod = (size_t)(_mod);
if (!mod)
mod = (size_t)GetModuleHandle(NULL);
// locate PE
auto dosHeader = pointMem<IMAGE_DOS_HEADER>(mod);
if (dosHeader->e_magic != 0x5A4D)
return 0;
auto optionalHeader = pointMem<IMAGE_OPTIONAL_HEADER>(mod + dosHeader->e_lfanew + 24);
if (optionalHeader->Magic != 0x10B)
return 0;
if (optionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size == 0 ||
optionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0)
return 0;
// scan imports for the target library and clone it
HMODULE clone = nullptr;
auto importDescriptor = pointMem<IMAGE_IMPORT_DESCRIPTOR>(mod + optionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
while (importDescriptor->FirstThunk)
{
auto importLibraryName = pointMem<char>(mod + importDescriptor->Name);
if (!_stricmp(libraryName, importLibraryName))
{
clone = cloneLibrary(libraryName);
break;
}
else
importDescriptor++;
}
if (!clone || !importDescriptor || !importDescriptor->FirstThunk)
return 0;
size_t n = 0;
size_t replaced = 0;
auto thunkData = pointMem<IMAGE_THUNK_DATA>(mod + importDescriptor->OriginalFirstThunk);
while (thunkData->u1.Function)
{
auto importFunctionName = pointMem<char>(mod + thunkData->u1.AddressOfData + 2);
auto address = (size_t)pointMem<size_t>(mod + importDescriptor->FirstThunk + (n * sizeof(DWORD)));
auto newFunction = GetProcAddress(clone, importFunctionName);
if (newFunction)
{
auto old = protectMem<FARPROC>(address, PAGE_EXECUTE_READWRITE);
writeMem<FARPROC>(address, newFunction);
protectMem<FARPROC>(address, old);
replaced++;
}
n++;
thunkData++;
}
return replaced;
}