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