forked from mlghuskie/NoBastian
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathUtil.h
262 lines (222 loc) · 7.71 KB
/
Util.h
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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
#include "Include.h"
#undef Module32First;
#undef Module32Next
#undef MODULEENTRY32
#undef Process32First
#undef Process32Next
#undef PROCESSENTRY32
#define A(s) Util::ToA(s)
#define W(s) Util::ToW(s)
#define LC(s) Util::ToLower(s)
using namespace std;
namespace asmjs
{
class Util
{
public:
static wstring ToW(string str)
{
wstring_convert<codecvt_utf8_utf16<wchar_t>> converter;
return converter.from_bytes(str);
}
static string ToA(wstring wstr)
{
wstring_convert<codecvt_utf8_utf16<wchar_t>> converter;
return converter.to_bytes(wstr);
}
static string ToLower(string str)
{
transform(str.begin(), str.end(), str.begin(), tolower);
return str;
}
static wstring ToLower(wstring str)
{
transform(str.begin(), str.end(), str.begin(), tolower);
return str;
}
static vector<uint64_t> GetProcessIdsByName(string name)
{
vector<uint64_t> res;
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, null);
if(!snap) throw exception("CreateToolhelp32Snapshot failed");
PROCESSENTRY32 entry;
entry.dwSize = sizeof(entry);
if (!Process32First(snap, &entry)) throw exception("Process32First failed");
do
{
if (LC(entry.szExeFile) == LC(name))
{
res.push_back(entry.th32ProcessID);
}
} while (Process32Next(snap, &entry));
CloseHandle(snap);
return res;
}
static uint64_t GetProcessModuleBase(HANDLE hProcess, string moduleName)
{
return GetProcessModules(hProcess)[LC(moduleName)];
}
// Requires PROCESS_QUERY_INFORMATION access rights
static uint64_t TlHelp32GetProcessModuleBase(uint64_t processId, string moduleName)
{
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processId);
if (!hSnap) return false;
uint64_t ret = 0;
MODULEENTRY32 modEntry;
modEntry.dwSize = sizeof(MODULEENTRY32);
if (!Module32First(hSnap, &modEntry)) return false;
do
{
if (LC(modEntry.szModule) == LC(moduleName))
{
ret = (uint64_t)modEntry.modBaseAddr;
break;
}
} while (Module32Next(hSnap, &modEntry));
CloseHandle(hSnap);
return ret;
}
static DWORD GetModuleHandleArraySize(HANDLE hProcess)
{
DWORD szNeeded;
auto res = K32EnumProcessModules(hProcess, null, null, &szNeeded);
if (!res) throw exception("K32EnumProcessModules failed");
return szNeeded;
}
static map<string, uint64_t> GetProcessModules(HANDLE hProcess)
{
map<string, uint64_t> res;
if (DWORD szNeeded = GetModuleHandleArraySize(hProcess))
{
vector<uint64_t> modHandles;
modHandles.resize(szNeeded);
if (K32EnumProcessModules(hProcess, (HMODULE*)modHandles.data(), szNeeded, &szNeeded))
{
for (int i = 0; i != (szNeeded / sizeof(HMODULE)); i++)
{
char fn[1024];
if (K32GetModuleBaseNameA(hProcess, (HMODULE)modHandles[i], fn, sizeof(fn)))
{
res[LC(fn)] = modHandles[i];
}
}
}
else
{
throw exception("K32EnumProcessModules failed");
}
}
return res;
}
static ACCESS_MASK QueryHandleAccessMask(HANDLE handle)
{
typedef NTSTATUS (*NtQueryObjectFn)(
_In_opt_ HANDLE Handle,
_In_ OBJECT_INFORMATION_CLASS ObjectInformationClass,
_Out_opt_ PVOID ObjectInformation,
_In_ ULONG ObjectInformationLength,
_Out_opt_ PULONG ReturnLength
);
auto NtQueryObject = (NtQueryObjectFn)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryObject");
if (!NtQueryObject) throw exception("Couldn't get address of NtQueryObject");
PUBLIC_OBJECT_BASIC_INFORMATION objInfo;
if (!NT_SUCCESS(NtQueryObject(handle, ObjectBasicInformation, &objInfo, sizeof(objInfo), null))) throw exception("NtQueryObject failed");
return objInfo.GrantedAccess;
}
static bool HandleHasAccess(HANDLE handle, ACCESS_MASK mask)
{
return (QueryHandleAccessMask(handle) & mask) == mask;
}
#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004
#define SystemHandleInformation 16
typedef NTSTATUS(NTAPI* NtQuerySystemInformationFn)(ULONG, PVOID, ULONG, PULONG);
typedef struct _SYSTEM_HANDLE
{
ULONG ProcessId;
BYTE ObjectTypeNumber;
BYTE Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE, *PSYSTEM_HANDLE;
typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG HandleCount;
SYSTEM_HANDLE Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
// implementation 1, works well enough
static HANDLE GetProcessHandle(uint64_t targetProcessId)
{
auto NtQuerySystemInformation = reinterpret_cast<NtQuerySystemInformationFn>(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQuerySystemInformation"));
NTSTATUS status;
ULONG handleInfoSize = 0x10000;
auto handleInfo = reinterpret_cast<PSYSTEM_HANDLE_INFORMATION>(malloc(handleInfoSize));
while ((status = NtQuerySystemInformation(SystemHandleInformation, handleInfo, handleInfoSize, nullptr)) == STATUS_INFO_LENGTH_MISMATCH)
handleInfo = reinterpret_cast<PSYSTEM_HANDLE_INFORMATION>(realloc(handleInfo, handleInfoSize *= 2));
if (!NT_SUCCESS(status))
{
throw runtime_error("NtQuerySystemInformation failed!");
}
for (auto i = 0; i < handleInfo->HandleCount; i++)
{
auto handle = handleInfo->Handles[i];
const auto process = reinterpret_cast<HANDLE>(handle.Handle);
if (handle.ProcessId == GetCurrentProcessId() && GetProcessId(process) == targetProcessId)
return process;
}
free(handleInfo);
return nullptr;
}
// implmentation 2, crashes sometimes by some reason, so i don't use it
static vector<HANDLE> QueryProcessHandles(uint64_t targetProcessId, ACCESS_MASK desiredAccess)
{
#define STATUS_UNSUCCESSFUL 0xC0000001
#define SystemExtendedHandleInformation 64
#define TI_Process 7
typedef struct SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX
{
PVOID Object;
HANDLE UniqueProcessId;
HANDLE HandleValue;
ACCESS_MASK GrantedAccess;
USHORT CreatorBackTraceIndex;
USHORT ObjectTypeIndex;
ULONG HandleAttributes;
ULONG Reserved;
};
typedef struct SYSTEM_HANDLE_INFORMATION_EX
{
ULONG_PTR NumberOfHandles;
ULONG_PTR Reserved;
SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1];
};
auto NtQuerySystemInformation = (NtQuerySystemInformationFn)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQuerySystemInformation");
if (!NtQuerySystemInformation) throw exception("Coudln't resolve NtQuerySystemInformation address");
vector<HANDLE> res;
ULONG size = 0;
SYSTEM_HANDLE_INFORMATION_EX* handleInfo = nullptr;
NTSTATUS status = -1;
while (!NT_SUCCESS(status))
{
status = NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemExtendedHandleInformation, handleInfo, size, &size);
if (status == STATUS_INFO_LENGTH_MISMATCH)
{
if (handleInfo != nullptr) VirtualFree(handleInfo, 0, MEM_RELEASE);
handleInfo = (SYSTEM_HANDLE_INFORMATION_EX*)VirtualAlloc(null, size, MEM_COMMIT, PAGE_READWRITE);
}
}
for (ULONG i = 0; i < handleInfo->NumberOfHandles; i++)
{
auto handleEntry = &handleInfo->Handles[i];
if (handleEntry->ObjectTypeIndex == TI_Process // Is it a process handle or not
&& GetProcessId(handleEntry->HandleValue) == targetProcessId // Does it describe target process or describes something else
&& HandleHasAccess(handleEntry->HandleValue, desiredAccess)) // Does it have enough access rights
{
res.push_back(handleEntry->HandleValue);
}
}
VirtualFree(handleInfo, 0, MEM_RELEASE);
return res;
}
};
}