Skip to content

Commit 1e31416

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

1 file changed

Lines changed: 125 additions & 14 deletions

File tree

memory.h

Lines changed: 125 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,135 @@ 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+
258+
//size_t GetModuleSize(uintptr_t targetModuleBase) {
259+
// uintptr_t pebAddr = Peb();
260+
//
261+
// uintptr_t ldrAddr = 0;
262+
// Read(pebAddr + 0x18, &ldrAddr, sizeof(ldrAddr));
263+
//
264+
// uintptr_t moduleListHead = ldrAddr + 0x20;
265+
//
266+
// uintptr_t currentLink = 0;
267+
// Read(moduleListHead, &currentLink, sizeof(currentLink));
268+
//
269+
// while (currentLink != moduleListHead) {
270+
// uintptr_t entryAddr = currentLink - 0x10;
271+
//
272+
// uintptr_t dllBase = 0;
273+
// Read(entryAddr + 0x30, &dllBase, sizeof(dllBase));
274+
//
275+
// if (dllBase == targetModuleBase) {
276+
//
277+
// size_t sizeOfImage = 0;
278+
// Read(entryAddr + 0x40, &sizeOfImage, sizeof(sizeOfImage));
279+
//
280+
// return sizeOfImage;
281+
// }
282+
//
283+
// Read(currentLink, &currentLink, sizeof(currentLink));
284+
// }
285+
//
286+
// return 0;
287+
//}
288+
234289
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) {
290+
291+
uintptr_t pebAddress = getPEB();
292+
293+
if (pebAddress == NULL)
237294
return false;
238-
}
239295

240-
MODULEENTRY32W entry = {};
241-
entry.dwSize = sizeof(MODULEENTRY32W);
296+
uintptr_t PEBldrAddress = pebAddress + offsetof(PEB, PEB::Ldr);
297+
uintptr_t PEBldr = 0;
298+
read(PEBldrAddress, &PEBldr, sizeof(uintptr_t));
242299

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));
300+
uintptr_t moduleListHead = PEBldr + offsetof(PEB_LDR_DATA, PEB_LDR_DATA::InMemoryOrderModuleList);
301+
302+
uintptr_t currentLink = 0;
303+
read(moduleListHead, &currentLink, sizeof(uintptr_t));
304+
305+
while (currentLink != moduleListHead)
306+
{
307+
uintptr_t entryBase = currentLink - offsetof(LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
308+
309+
310+
// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntldr/ldr_data_table_entry.htm
311+
UNICODE_STRING dllString;
312+
// base dll name is directly after full dll name
313+
uintptr_t linkDllNameAddress = entryBase + offsetof(LDR_DATA_TABLE_ENTRY, LDR_DATA_TABLE_ENTRY::FullDllName) + sizeof(UNICODE_STRING);
314+
315+
// this is going to give an incorrect pointer to the string located inside dllString
316+
// however the length will be correct, so the length will be used to construct our own string with the contents
317+
// of the original
318+
read(linkDllNameAddress, &dllString, sizeof(UNICODE_STRING));
319+
320+
size_t charCount = (dllString.Length / sizeof(wchar_t)) + 1;
321+
std::vector<wchar_t> dllName(charCount, L'\0');
322+
323+
read(reinterpret_cast<uintptr_t>(dllString.Buffer), dllName.data(), dllString.Length);
324+
325+
if (wcscmp(moduleName, dllName.data()) == 0)
326+
{
327+
// found it!!!
328+
329+
uintptr_t baseAddress = 0;
330+
read(entryBase + offsetof(LDR_DATA_TABLE_ENTRY, LDR_DATA_TABLE_ENTRY::DllBase), &baseAddress, sizeof(baseAddress));
331+
332+
333+
ULONG moduleSize = 0;
334+
// reserved in winternl but SizeOfImage
335+
read(entryBase + offsetof(LDR_DATA_TABLE_ENTRY, LDR_DATA_TABLE_ENTRY::DllBase) + 0x10, &moduleSize, sizeof(moduleSize));
336+
337+
338+
info->base = baseAddress;
339+
info->size = moduleSize;
340+
341+
return true;
342+
}
343+
read(currentLink, &currentLink, sizeof(currentLink));
251344
}
252345

253-
CloseHandle(snapshot);
346+
//HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);
347+
//if (snapshot == INVALID_HANDLE_VALUE) {
348+
// return false;
349+
//}
350+
351+
//MODULEENTRY32W entry = {};
352+
//entry.dwSize = sizeof(MODULEENTRY32W);
353+
354+
//if (Module32FirstW(snapshot, &entry)) {
355+
// do {
356+
// if (wcsstr(moduleName, entry.szModule)) {
357+
// info->base = (uintptr_t)entry.modBaseAddr;
358+
// info->size = entry.modBaseSize;
359+
// return true;
360+
// }
361+
// } while (Module32NextW(snapshot, &entry));
362+
//}
363+
364+
//CloseHandle(snapshot);
254365

255366
return false;
256367
}

0 commit comments

Comments
 (0)