Skip to content

Commit 7be607b

Browse files
committed
reduce reliance on winapi for backend portability
1 parent 72c8a2d commit 7be607b

1 file changed

Lines changed: 94 additions & 14 deletions

File tree

memory.h

Lines changed: 94 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <vector>
66
#include <tlhelp32.h>
77
#include <unordered_map>
8+
#include <winternl.h>
89
#include <Psapi.h>
910

1011
struct processSnapshot {
@@ -68,6 +69,7 @@ namespace mem {
6869

6970
bool getProcessList();
7071
HANDLE openHandle(DWORD pid);
72+
uintptr_t getPEB();
7173
bool getModuleInfo(DWORD pid, const wchar_t* moduleName, moduleInfo* info);
7274
void getModules();
7375
void getSections(const moduleInfo& info, std::vector<moduleSection>& dest);
@@ -231,26 +233,104 @@ inline void mem::getSections(const moduleInfo& info, std::vector<moduleSection>&
231233
}
232234
}
233235

236+
237+
238+
typedef NTSTATUS(*_NtQueryInformationProcess)(IN HANDLE ProcessHandle,
239+
IN PROCESSINFOCLASS ProcessInformationClass,
240+
OUT PVOID ProcessInformation,
241+
IN ULONG ProcessInformationLength,
242+
OUT PULONG ReturnLength OPTIONAL);
243+
244+
inline uintptr_t mem::getPEB()
245+
{
246+
PROCESS_BASIC_INFORMATION processInformation;
247+
ULONG written = 0;
248+
249+
HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
250+
251+
static _NtQueryInformationProcess query = (_NtQueryInformationProcess)GetProcAddress(hNtdll, "NtQueryInformationProcess");
252+
253+
NTSTATUS result = query(memHandle, ProcessBasicInformation, &processInformation, sizeof(PROCESS_BASIC_INFORMATION), &written);
254+
255+
return reinterpret_cast<uintptr_t>(processInformation.PebBaseAddress);
256+
}
257+
234258
inline bool mem::getModuleInfo(DWORD pid, const wchar_t* moduleName, moduleInfo* info) {
235-
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);
236-
if (snapshot == INVALID_HANDLE_VALUE) {
259+
260+
uintptr_t pebAddress = getPEB();
261+
262+
if (pebAddress == NULL)
237263
return false;
238-
}
239264

240-
MODULEENTRY32W entry = {};
241-
entry.dwSize = sizeof(MODULEENTRY32W);
265+
uintptr_t PEBldrAddress = pebAddress + offsetof(PEB, PEB::Ldr);
266+
uintptr_t PEBldr = 0;
267+
read(PEBldrAddress, &PEBldr, sizeof(uintptr_t));
242268

243-
if (Module32FirstW(snapshot, &entry)) {
244-
do {
245-
if (wcsstr(moduleName, entry.szModule)) {
246-
info->base = (uintptr_t)entry.modBaseAddr;
247-
info->size = entry.modBaseSize;
248-
return true;
249-
}
250-
} while (Module32NextW(snapshot, &entry));
269+
uintptr_t moduleListHead = PEBldr + offsetof(PEB_LDR_DATA, PEB_LDR_DATA::InMemoryOrderModuleList);
270+
271+
uintptr_t currentLink = 0;
272+
read(moduleListHead, &currentLink, sizeof(uintptr_t));
273+
274+
while (currentLink != moduleListHead)
275+
{
276+
uintptr_t entryBase = currentLink - offsetof(LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
277+
278+
279+
// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntldr/ldr_data_table_entry.htm
280+
UNICODE_STRING dllString;
281+
// base dll name is directly after full dll name
282+
uintptr_t linkDllNameAddress = entryBase + offsetof(LDR_DATA_TABLE_ENTRY, LDR_DATA_TABLE_ENTRY::FullDllName) + sizeof(UNICODE_STRING);
283+
284+
// this is going to give an incorrect pointer to the string located inside dllString
285+
// however the length will be correct, so the length will be used to construct our own string with the contents
286+
// of the original
287+
read(linkDllNameAddress, &dllString, sizeof(UNICODE_STRING));
288+
289+
size_t charCount = (dllString.Length / sizeof(wchar_t)) + 1;
290+
std::vector<wchar_t> dllName(charCount, L'\0');
291+
292+
read(reinterpret_cast<uintptr_t>(dllString.Buffer), dllName.data(), dllString.Length);
293+
294+
if (wcscmp(moduleName, dllName.data()) == 0)
295+
{
296+
// found it!!!
297+
298+
uintptr_t baseAddress = 0;
299+
read(entryBase + offsetof(LDR_DATA_TABLE_ENTRY, LDR_DATA_TABLE_ENTRY::DllBase), &baseAddress, sizeof(baseAddress));
300+
301+
302+
ULONG moduleSize = 0;
303+
// reserved in winternl but SizeOfImage
304+
read(entryBase + offsetof(LDR_DATA_TABLE_ENTRY, LDR_DATA_TABLE_ENTRY::DllBase) + 0x10, &moduleSize, sizeof(moduleSize));
305+
306+
307+
info->base = baseAddress;
308+
info->size = moduleSize;
309+
310+
return true;
311+
}
312+
read(currentLink, &currentLink, sizeof(currentLink));
251313
}
252314

253-
CloseHandle(snapshot);
315+
//HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);
316+
//if (snapshot == INVALID_HANDLE_VALUE) {
317+
// return false;
318+
//}
319+
320+
//MODULEENTRY32W entry = {};
321+
//entry.dwSize = sizeof(MODULEENTRY32W);
322+
323+
//if (Module32FirstW(snapshot, &entry)) {
324+
// do {
325+
// if (wcsstr(moduleName, entry.szModule)) {
326+
// info->base = (uintptr_t)entry.modBaseAddr;
327+
// info->size = entry.modBaseSize;
328+
// return true;
329+
// }
330+
// } while (Module32NextW(snapshot, &entry));
331+
//}
332+
333+
//CloseHandle(snapshot);
254334

255335
return false;
256336
}

0 commit comments

Comments
 (0)