-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathReflectiveTransformer.c
163 lines (140 loc) · 5.95 KB
/
ReflectiveTransformer.c
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include "ReflectiveTransformer.h"
static PIMAGE_NT_HEADERS ImageNTHeadersFromDOSHeader(PDOS_HEADER pDosHeader) {
PIMAGE_NT_HEADERS pImgNtHeaders = NULL;
if (DEREF_32(pDosHeader) != 0x00905a4d) {
return NULL;
}
pImgNtHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)pDosHeader + pDosHeader->e_lfanew);
if (pImgNtHeaders->Signature != 0x4550) {
return NULL;
}
return pImgNtHeaders;
}
BOOL DOSHeaderIsDLL(PDOS_HEADER pDosHeader) {
// Check the FileHeader Characteristics field to determine whether the PE
// image is marked as both executable (IMAGE_FILE_EXECUTABLE_IMAGE) and
// a DLL (IMAGE_FILE_DLL).
//
// PDOS_HEADER pDosHeader: A pointer to the DOS header to analyze.
// Returns: TRUE if pDosHeader is a DLL.
PIMAGE_NT_HEADERS pImgNtHeaders = NULL;
WORD wCharacteristics = 0;
pImgNtHeaders = ImageNTHeadersFromDOSHeader(pDosHeader);
if (!pImgNtHeaders) {
return FALSE;
}
wCharacteristics = pImgNtHeaders->FileHeader.Characteristics;
wCharacteristics &= (IMAGE_FILE_DLL | IMAGE_FILE_EXECUTABLE_IMAGE);
return wCharacteristics == (IMAGE_FILE_DLL | IMAGE_FILE_EXECUTABLE_IMAGE);
}
BOOL DOSHeaderIsEXE(PDOS_HEADER pDosHeader) {
// Check the FileHeader Characteristics field to determine whether the PE
// image is marked as both executable (IMAGE_FILE_EXECUTABLE_IMAGE) and
// not a DLL (IMAGE_FILE_DLL).
//
// PDOS_HEADER pDosHeader: A pointer to the DOS header to analyze.
// Returns: TRUE if pDosHeader is an EXE.
PIMAGE_NT_HEADERS pImgNtHeaders = NULL;
WORD wCharacteristics = 0;
pImgNtHeaders = ImageNTHeadersFromDOSHeader(pDosHeader);
if (!pImgNtHeaders) {
return FALSE;
}
wCharacteristics = pImgNtHeaders->FileHeader.Characteristics;
wCharacteristics &= (IMAGE_FILE_DLL | IMAGE_FILE_EXECUTABLE_IMAGE);
return wCharacteristics == IMAGE_FILE_EXECUTABLE_IMAGE;
}
BOOL ReflectiveTransformerToDLL(PDOS_HEADER pDosHeader, DWORD dwAddressOfEntryPoint) {
// Transform the PE image pDosHeader into a DLL. This updates the FileHeader
// Characteristics field as necessary, updates the OptionalHeader ImageBase
// to the default value for DLL files and sets a new entry point.
//
// PDOS_HEADER pDosHeader: A pointer to the DOS header transform.
// DWORD dwAddressOfEntryPoint: The RVA of the new entry point for the PE
// image.
// Returns: TRUE on success.
PIMAGE_NT_HEADERS pImgNtHeaders = NULL;
pImgNtHeaders = ImageNTHeadersFromDOSHeader(pDosHeader);
if (!pImgNtHeaders) {
return FALSE;
}
if (RebaseImage(pDosHeader, (ULONG_PTR)(pImgNtHeaders->OptionalHeader.ImageBase), IMAGE_BASE_DLL)) {
ShadowSectionUpdate(pDosHeader);
}
pImgNtHeaders->FileHeader.Characteristics |= IMAGE_FILE_DLL;
pImgNtHeaders->FileHeader.Characteristics |= IMAGE_FILE_EXECUTABLE_IMAGE;
pImgNtHeaders->OptionalHeader.ImageBase = IMAGE_BASE_DLL;
pImgNtHeaders->OptionalHeader.AddressOfEntryPoint = dwAddressOfEntryPoint;
return TRUE;
}
BOOL ReflectiveTransformerToEXE(PDOS_HEADER pDosHeader, DWORD dwAddressOfEntryPoint) {
// Transform the PE image pDosHeader into an EXE. This updates the FileHeader
// Characteristics field as necessary, updates the OptionalHeader ImageBase
// to the default value for EXE files and sets a new entry point.
//
// PDOS_HEADER pDosHeader: A pointer to the DOS header transform.
// DWORD dwAddressOfEntryPoint: The RVA of the new entry point for the PE
// image.
// Returns: TRUE on success.
PIMAGE_NT_HEADERS pImgNtHeaders = NULL;
pImgNtHeaders = ImageNTHeadersFromDOSHeader(pDosHeader);
if (!pImgNtHeaders) {
return FALSE;
}
if (RebaseImage(pDosHeader, (ULONG_PTR)(pImgNtHeaders->OptionalHeader.ImageBase), IMAGE_BASE_EXE)) {
ShadowSectionUpdate(pDosHeader);
}
pImgNtHeaders->FileHeader.Characteristics &= ~IMAGE_FILE_DLL;
pImgNtHeaders->FileHeader.Characteristics |= IMAGE_FILE_EXECUTABLE_IMAGE;
pImgNtHeaders->OptionalHeader.ImageBase = IMAGE_BASE_EXE;
pImgNtHeaders->OptionalHeader.AddressOfEntryPoint = dwAddressOfEntryPoint;
return TRUE;
}
DWORD RVAFromExportName(PDOS_HEADER pDosHeader, LPCSTR lpProcName) {
// Get the relative virtual address (RVA) of an exported function by it's
// name from an unloaded PE image. The return value can then be used as the
// dwAddressOfEntryPoint argument to the ReflectiveTransformerTo* set of
// functions.
//
// PDOS_HEADER pDosHeader: A pointer to the DOS header of the PE image to
// resolve the export from.
// LPCSTR lpProcName: A pointer to the name of the exported function to
// resolve the RVA for.
// Returns: The function returns a non-zero value on success.
PIMAGE_NT_HEADERS pImgNtHeaders = NULL;
PIMAGE_EXPORT_DIRECTORY pImgExDir = NULL;
PIMAGE_DATA_DIRECTORY pImgDataDir = NULL;
PDWORD pdwExAddress = NULL;
PDWORD pdwExName = NULL;
LPCSTR lpExportName;
DWORD dwCursor;
pImgNtHeaders = ImageNTHeadersFromDOSHeader(pDosHeader);
if (!pImgNtHeaders) {
return 0;
}
pImgDataDir = (PIMAGE_DATA_DIRECTORY)&pImgNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
if (!pImgDataDir->Size) {
return 0;
}
pImgExDir = (PIMAGE_EXPORT_DIRECTORY)PAFromRVA(pDosHeader, (ULONG_PTR)pImgDataDir->VirtualAddress);
if (!pImgExDir) {
return 0;
}
(ULONG_PTR)pImgExDir += (ULONG_PTR)pDosHeader;
(ULONG_PTR)pdwExAddress = PAFromRVA(pDosHeader, pImgExDir->AddressOfFunctions);
(ULONG_PTR)pdwExAddress += (ULONG_PTR)pDosHeader;
(ULONG_PTR)pdwExName = PAFromRVA(pDosHeader, pImgExDir->AddressOfNames);
(ULONG_PTR)pdwExName += (ULONG_PTR)pDosHeader;
for (dwCursor = 0; dwCursor < pImgExDir->NumberOfFunctions; dwCursor++) {
lpExportName = (LPSTR)PAFromRVA(pDosHeader, (ULONG_PTR)pdwExName[dwCursor]);
if (!lpExportName) {
continue;
}
lpExportName += (ULONG_PTR)pDosHeader;
if (memcmp(lpProcName, lpExportName, strlen(lpProcName))) {
continue;
}
return pdwExAddress[dwCursor];
}
return 0;
}