23#define TO_LOWERCASE(c1) c1 = (c1 <= 'Z' && c1 >= 'A') ? c1 = (c1 - 'A') + 'a': c1;
28 bool is_wanted_func(LPCSTR curr_name, LPCSTR wanted_name)
30 if (curr_name == NULL || wanted_name == NULL)
return false;
32 size_t wanted_name_len = strlen(wanted_name);
33 size_t curr_name_len = strlen(curr_name);
35 if (curr_name_len != wanted_name_len)
return false;
37 for (
size_t i = 0; i < wanted_name_len; i++) {
38 char c1 = curr_name[i];
39 char c2 = wanted_name[i];
42 if (c1 != c2)
return false;
47 bool is_ordinal(IMAGE_EXPORT_DIRECTORY* exp, LPCSTR func_name)
49 ULONGLONG base = exp->Base;
50 ULONGLONG max_ord = base + exp->NumberOfFunctions;
51 ULONGLONG name_ptr_val = (ULONGLONG)func_name;
52 if (name_ptr_val >= base && name_ptr_val < max_ord) {
58 FARPROC get_export_by_ord(LPVOID modulePtr, IMAGE_EXPORT_DIRECTORY* exp, DWORD wanted_ordinal)
60 SIZE_T functCount = exp->NumberOfFunctions;
61 DWORD funcsListRVA = exp->AddressOfFunctions;
62 DWORD ordBase = exp->Base;
67 for (DWORD i = 0; i < functCount; i++) {
68 DWORD ordinal = ordBase + i;
69 if (ordinal != wanted_ordinal)
continue;
71 DWORD* funcRVA = (DWORD*)(funcsListRVA + (BYTE*)modulePtr + i *
sizeof(DWORD));
73 LOG_ERROR(
"Invalid RVA of exported function");
76 BYTE* fPtr = (BYTE*)modulePtr + (*funcRVA);
78 LOG_ERROR(
"Invalid pointer to exported function");
82 LOG_WARNING(
"Forwarded function: [%lu -> %p] cannot be resolved.", wanted_ordinal, fPtr);
94 if (!modSize)
return 0;
97 if (!exp || !
validate_ptr(modulePtr, modSize, exp,
sizeof(IMAGE_EXPORT_DIRECTORY))) {
101 SIZE_T namesCount = exp->NumberOfNames;
102 DWORD funcNamesListRVA = exp->AddressOfNames;
105 DWORD* nameRVAs = (DWORD*)(funcNamesListRVA + (ULONG_PTR)modulePtr);
107 for (i = 0; i < namesCount; i++) {
108 if (!
validate_ptr(modulePtr, modSize, &nameRVAs[i],
sizeof(DWORD))) {
111 DWORD nameRVA = nameRVAs[i];
115 LPSTR name = (LPSTR)(nameRVA + (BYTE*) modulePtr);
119 names_list.push_back(name);
128 if (!modSize)
return nullptr;
131 if (!exp || !
validate_ptr(modulePtr, modSize, exp,
sizeof(IMAGE_EXPORT_DIRECTORY))) {
135 SIZE_T namesCount = exp->NumberOfNames;
137 DWORD funcsListRVA = exp->AddressOfFunctions;
138 DWORD funcNamesListRVA = exp->AddressOfNames;
139 DWORD namesOrdsListRVA = exp->AddressOfNameOrdinals;
141 if (is_ordinal(exp, wanted_name)) {
142 LOG_DEBUG(
"Getting function by ordinal.");
144 return get_export_by_ord(modulePtr, exp, ordinal);
147 LOG_ERROR(
"Invalid pointer to the name.");
151 for (SIZE_T i = 0; i < namesCount; i++) {
152 DWORD* nameRVA = (DWORD*)(funcNamesListRVA + (BYTE*) modulePtr + i *
sizeof(DWORD));
153 WORD* nameIndex = (WORD*)(namesOrdsListRVA + (BYTE*) modulePtr + i *
sizeof(WORD));
154 if (!
validate_ptr(modulePtr, modSize, nameRVA,
sizeof(DWORD))
155 || !
validate_ptr(modulePtr, modSize, nameIndex,
sizeof(WORD)))
157 LOG_ERROR(
"Invalid pointer to exported name RVA or index");
160 DWORD* funcRVA = (DWORD*)(funcsListRVA + (BYTE*) modulePtr + (*nameIndex) *
sizeof(DWORD));
161 if (!
validate_ptr(modulePtr, modSize, funcRVA,
sizeof(DWORD))) {
162 LOG_ERROR(
"Invalid pointer to exported function RVA");
165 LPSTR name = (LPSTR)(*nameRVA + (BYTE*) modulePtr);
167 LOG_ERROR(
"Invalid pointer to exported function name");
170 if (!is_wanted_func(name, wanted_name)) {
173 BYTE* fPtr = (BYTE*)modulePtr + (*funcRVA);
175 LOG_ERROR(
"Invalid pointer to exported function");
179 LOG_WARNING(
"Forwarded function: [%s -> %p] cannot be resolved.", name, fPtr);
182 return (FARPROC) fPtr;
192 if (libBasePtr == NULL) {
193 LOG_ERROR(
"Could not load the library.");
199 LOG_WARNING(
"Could could not get function from exports. Falling back to the default resolver.");
202 LOG_ERROR(
"Loading function from %s failed.", lib_name);
215 if (!exp || !
validate_ptr(modulePtr, modSize, exp,
sizeof(IMAGE_EXPORT_DIRECTORY))) {
218 const LPSTR module_name = (
char*)((ULONGLONG)modulePtr + exp->Name);
#define MASK_TO_DWORD(val)
virtual FARPROC resolve_func(LPCSTR lib_name, LPCSTR func_name)
virtual HMODULE load_library(LPCSTR lib_name)
virtual FARPROC resolve_func(LPCSTR lib_name, LPCSTR func_name)
Searching specific functions in PE's Exports Table.
Compile-time configurable logging macros for peconv.
#define LOG_DEBUG(fmt,...)
#define LOG_ERROR(fmt,...)
#define LOG_WARNING(fmt,...)
bool is_valid_string(LPVOID modulePtr, const size_t moduleSize, const CHAR_T *name_ptr, const size_t max_len=260)
LPSTR read_dll_name(HMODULE modulePtr)
size_t forwarder_name_len(BYTE *fPtr)
bool validate_ptr(IN const void *buffer_bgn, IN size_t buffer_size, IN const void *field_bgn, IN size_t field_size)
DWORD get_image_size(IN const BYTE *payload)
FARPROC get_exported_func(LPVOID modulePtr, LPCSTR wanted_name)
bool is_bad_read_ptr(LPCVOID areaStart, SIZE_T areaSize)
size_t get_exported_names(LPVOID modulePtr, std::vector< std::string > &names_list)
IMAGE_EXPORT_DIRECTORY * get_export_directory(IN HMODULE modulePtr)
Miscellaneous utility functions.