libPeConv
A library to load, manipulate, dump PE files.
Loading...
Searching...
No Matches
util.cpp
Go to the documentation of this file.
1#include "peconv/util.h"
2
3#define USE_OLD_BADPTR
4
5namespace peconv {
6
7 HMODULE g_kernel32Hndl = nullptr;
8 HMODULE g_ntdllHndl = nullptr;
9
10 bool fetch_or_load_dll(IN const char *mod_name, IN OUT HMODULE &mod)
11 {
12 if (!mod) {
13 mod = GetModuleHandleA(mod_name);
14 if (!mod) {
15 mod = LoadLibraryA(mod_name);
16 }
17 }
18 return mod ? true : false;
19 }
20
22 {
23 fetch_or_load_dll("kernel32.dll", g_kernel32Hndl);
24 return g_kernel32Hndl;
25 }
26
28 {
29 fetch_or_load_dll("ntdll.dll", g_ntdllHndl);
30 return g_ntdllHndl;
31 }
32};
33
34DWORD ntdll_get_process_id(HANDLE hProcess)
35{
36#if !defined PROCESSINFOCLASS
37 typedef LONG PROCESSINFOCLASS;
38#endif
39
40 NTSTATUS(WINAPI *_ZwQueryInformationProcess)(
41 IN HANDLE ProcessHandle,
42 IN PROCESSINFOCLASS ProcessInformationClass,
43 OUT PVOID ProcessInformation,
44 IN ULONG ProcessInformationLength,
45 OUT PULONG ReturnLength
46 ) = NULL;
47
48 HINSTANCE hNtDll = peconv::get_ntdll_hndl();
49 if (!hNtDll) {
50 return 0;
51 }
52
53 FARPROC procPtr = GetProcAddress(hNtDll, "ZwQueryInformationProcess");
54 if (!procPtr) {
55 return 0;
56 }
57
58 _ZwQueryInformationProcess = (NTSTATUS(WINAPI *)(
59 HANDLE,
60 PROCESSINFOCLASS,
61 PVOID,
62 ULONG,
63 PULONG)
64 ) procPtr;
65
66 typedef struct _PROCESS_BASIC_INFORMATION {
67 PVOID Reserved1;
68 PVOID PebBaseAddress;
69 PVOID Reserved2[2];
70 ULONG_PTR UniqueProcessId;
71 PVOID Reserved3;
72 } PROCESS_BASIC_INFORMATION;
73
74 PROCESS_BASIC_INFORMATION pbi = { 0 };
75 if (_ZwQueryInformationProcess(hProcess, 0, &pbi, sizeof(PROCESS_BASIC_INFORMATION), NULL) == S_OK) {
76 const DWORD pid = static_cast<DWORD>(pbi.UniqueProcessId);
77 return pid;
78 }
79 return 0;
80}
81
82DWORD peconv::get_process_id(HANDLE hProcess)
83{
84 static DWORD(WINAPI *_GetProcessId)(IN HANDLE Process) = nullptr;
85
86 DWORD processID = 0;
87 if (!_GetProcessId) {
88 HMODULE kernelLib = peconv::get_kernel32_hndl();
89 if (kernelLib) {
90 FARPROC procPtr = GetProcAddress(kernelLib, "GetProcessId");
91 if (procPtr) {
92 _GetProcessId = (DWORD(WINAPI *) (IN HANDLE))procPtr;
93 }
94 }
95 }
96 if (_GetProcessId) {
97 processID = _GetProcessId(hProcess);
98 }
99 if (processID == 0) {
100 //could not retrieve Pid using GetProcessId, try using NTDLL:
101 processID = ntdll_get_process_id(hProcess);
102 }
103 return processID;
104}
105
106bool peconv::is_padding(const BYTE *cave_ptr, size_t cave_size, const BYTE padding)
107{
108 for (size_t i = 0; i < cave_size; i++) {
109 if (cave_ptr[i] != padding) {
110 return false;
111 }
112 }
113 return true;
114}
115
116bool peconv::is_mem_accessible(LPCVOID areaStart, SIZE_T areaSize, DWORD dwAccessRights)
117{
118 if (!areaSize) return false; // zero-sized areas are not allowed
119
120 const DWORD dwForbiddenArea = PAGE_GUARD | PAGE_NOACCESS;
121
122 MEMORY_BASIC_INFORMATION mbi = { 0 };
123 const size_t mbiSize = sizeof(MEMORY_BASIC_INFORMATION);
124
125 SIZE_T sizeToCheck = areaSize;
126 LPCVOID areaPtr = areaStart;
127
128 while (sizeToCheck > 0) {
129 //reset area
130 memset(&mbi, 0, mbiSize);
131
132 // query the next area
133 if (VirtualQuery(areaPtr, &mbi, mbiSize) != mbiSize) {
134 return false; // could not query the area, assume it is bad
135 }
136 // check the privileges
137 bool isOk = (mbi.State & MEM_COMMIT) // memory allocated and
138 && !(mbi.Protect & dwForbiddenArea) // access to page allowed and
139 && (mbi.Protect & dwAccessRights); // the required rights
140 if (!isOk) {
141 return false; //invalid access
142 }
143 SIZE_T offset = (ULONG_PTR)areaPtr - (ULONG_PTR)mbi.BaseAddress;
144 SIZE_T queriedSize = mbi.RegionSize - offset;
145 if (queriedSize >= sizeToCheck) {
146 return true; // it is fine
147 }
148 // move to the next region
149 sizeToCheck -= queriedSize;
150 areaPtr = LPCVOID((ULONG_PTR)areaPtr + queriedSize);
151 }
152 // by default assume it is inaccessible
153 return false;
154}
155
156bool peconv::is_bad_read_ptr(LPCVOID areaStart, SIZE_T areaSize)
157{
158#ifdef USE_OLD_BADPTR // classic IsBadReadPtr is much faster than the version using VirtualQuery
159 return (IsBadReadPtr(areaStart, areaSize)) ? true : false;
160#else
161 const DWORD dwReadRights = PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY;
162 bool isAccessible = peconv::is_mem_accessible(areaStart, areaSize, dwReadRights);
163 if (isAccessible) {
164 // the area has read access rights: not a bad read pointer
165 return false;
166 }
167 return true;
168#endif
169}
DWORD get_process_id(HANDLE hProcess)
Definition util.cpp:82
bool is_mem_accessible(LPCVOID areaStart, SIZE_T areaSize, DWORD accessRights)
Definition util.cpp:116
bool fetch_or_load_dll(IN const char *mod_name, IN OUT HMODULE &mod)
Definition util.cpp:10
HMODULE g_ntdllHndl
Definition util.cpp:8
bool is_padding(const BYTE *cave_ptr, size_t cave_size, const BYTE padding_char)
Definition util.cpp:106
HMODULE get_kernel32_hndl()
Definition util.cpp:21
bool is_bad_read_ptr(LPCVOID areaStart, SIZE_T areaSize)
Definition util.cpp:156
HMODULE g_kernel32Hndl
Definition util.cpp:7
HMODULE get_ntdll_hndl()
Definition util.cpp:27
DWORD ntdll_get_process_id(HANDLE hProcess)
Definition util.cpp:34
Miscellaneous utility functions.