-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGetFunctionPointer.c
More file actions
77 lines (56 loc) · 3.26 KB
/
GetFunctionPointer.c
File metadata and controls
77 lines (56 loc) · 3.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <stdio.h>
#include <windows.h>
FARPROC WINAPI GetFunctionPointer(HMODULE DLLHandle, char * functionName) {
char * pBaseAddr = (char *) DLLHandle;
// get pointers to main headers/structures
// RVA by default, addition of base is needed
IMAGE_DOS_HEADER * pDosHdr = (IMAGE_DOS_HEADER *) pBaseAddr;
IMAGE_NT_HEADERS * pNTHdr = (IMAGE_NT_HEADERS *) (pBaseAddr + pDosHdr->e_lfanew); // pDosHdr.e_lfanew is the NT Header RVA
IMAGE_OPTIONAL_HEADER * pOptionalHdr = &pNTHdr->OptionalHeader; // RVA optional headers
IMAGE_DATA_DIRECTORY * pExportDataDir = (IMAGE_DATA_DIRECTORY *) (&pOptionalHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]);
IMAGE_EXPORT_DIRECTORY * pExportDirAddr = (IMAGE_EXPORT_DIRECTORY *) (pBaseAddr + pExportDataDir->VirtualAddress);
// resolve addresses to Export Address Table, table of function names and "table of ordinals"
DWORD * ExportAddressOfFunctions = (DWORD *) (pBaseAddr + pExportDirAddr->AddressOfFunctions);
DWORD * ExportAddressOfNames = (DWORD *) (pBaseAddr + pExportDirAddr->AddressOfNames);
WORD * ExportAddressOfNameOrdinals = (WORD *) (pBaseAddr + pExportDirAddr->AddressOfNameOrdinals);
WORD ordinal = (WORD) functionName & 0xFFFF; // convert to WORD (if resolution via ordinal)
DWORD base = pExportDirAddr->Base; // first ordinal number
// function address we're looking for
void *pProcAddr = NULL;
printf("DLL ordinal base: %d\n", base);
// resolve function by name
if (((DWORD_PTR)functionName >> 16) != 0) { // to undersand if name or ordinal: ordinal is 2 word long (16 byte), if shift 16 = 0 we're using ordinals instead of names
// iterate over AoN
for (DWORD i = 0; i < pExportDirAddr->NumberOfNames; i++) {
char * sTmpFuncName = (char *) pBaseAddr + (DWORD_PTR) ExportAddressOfNames[i];
if (strcmp(functionName, sTmpFuncName) == 0) {
printf("Found name index: %d\n", i);
ordinal = ExportAddressOfNameOrdinals[i] + base;
printf("Logical Ordinal: %d (hex: 0x%x)\n", ordinal, ordinal);
break;
}
}
}
// check if ordinal is not out of scope
if (ordinal < base || ordinal >= base + pExportDirAddr->NumberOfFunctions)
return NULL;
// get the function virtual address = RVA + BaseAddr
pProcAddr = (FARPROC) (pBaseAddr + (DWORD_PTR) ExportAddressOfFunctions[ordinal - base]);
// check if found VA is forwarded to external library.function
if ((char *) pProcAddr >= (char *) pExportDirAddr &&
(char *) pProcAddr < (char *) (pExportDirAddr + pExportDataDir->Size)) {
char * sFwdDLL = _strdup((char *) pProcAddr); // get a copy of library.function string
if (!sFwdDLL) return NULL;
// get external function name
char * sFwdFunction = strchr(sFwdDLL, '.');
*sFwdFunction = 0; // set trailing null byte for external library name -> library\x0function
sFwdFunction++; // shift a pointer to the beginning of function name
// load the external library
HMODULE hFwd = LoadLibraryA(sFwdDLL);
free(sFwdDLL); // release the allocated memory for lib.func string copy
if (!hFwd) return NULL;
// get the address of function the original call is forwarded to
pProcAddr = GetFunctionPointer(hFwd, sFwdFunction);
}
return (FARPROC) pProcAddr;
}