0%

C-12_PE结构

前面在github上写过这个pe基础 在看下这个复习下 https://mamor5409.github.io/posts/d8527941/

看了下滴水三期的PE 并参考一位师傅的滴水笔记 https://github.com/gh0stkey/Binary-Learning

RVA_2_FOA

img
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
DWORD RVAToFOA(HANDLE imageBase, DWORD dwRVA)
{
PIMAGE_NT_HEADERS pNtHead = NULL;
PIMAGE_FILE_HEADER pFileHead = NULL;
PIMAGE_SECTION_HEADER pSection = NULL;
DWORD NumberOfSectinsCount = 0;
DWORD dwImageBase = 0;

pNtHead = GetNtHeader(imageBase);
pSection = IMAGE_FIRST_SECTION(pNtHead);

dwImageBase = pNtHead->OptionalHeader.ImageBase;
NumberOfSectinsCount = pNtHead->FileHeader.NumberOfSections;
for (int each = 0; each < NumberOfSectinsCount; each++)
{
DWORD Section_Start = pSection[each].VirtualAddress; // 计算RVA开始位置
DWORD Section_Ends = pSection[each].VirtualAddress + pSection[each].Misc.VirtualSize; // 计算RVA结束位置

if (dwRVA >= Section_Start && dwRVA <= Section_Ends)
{
DWORD VA = pNtHead->OptionalHeader.ImageBase + dwRVA; // 得到VA地址
DWORD FOA = pSection[each].PointerToRawData + (dwRVA - pSection[each].VirtualAddress); // 得到FOA
return FOA;
}
}
return -1;
}

简单实现PEview

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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#include <Windows.h>
#include <stdio.h>
#include <DbgHelp.h>

#pragma comment(lib,"DbgHelp.lib")

HANDLE OpenPe(char* filename) {

HANDLE hfile = NULL;
HANDLE hMapfile = NULL;
HANDLE 起始基地址 = NULL;
DWORD size = 0;
hfile = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
size = GetFileSize(hfile, NULL);
hMapfile = CreateFileMapping(hfile, NULL, PAGE_READONLY, 0, size, NULL);

起始基地址 = MapViewOfFile(hMapfile, FILE_MAP_READ, 0, 0, size);
if(起始基地址 != NULL){
return 起始基地址;
}
printf("未能成功打开!\n");
return FALSE;
}

void showDosHeadInfo(HANDLE imageBase) {
PIMAGE_DOS_HEADER DosHaeder = imageBase;
printf("DOS头:%x \n", DosHaeder->e_magic);
printf("PE偏移:%x \n", DosHaeder->e_lfanew);

}

BOOL isPE(HANDLE imageBase) {
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)imageBase;

if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
return FALSE;
}

PIMAGE_NT_HEADERS pNthead = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew); //e_lfanew偏移

if (pNthead->Signature != IMAGE_NT_SIGNATURE) {
return FALSE;
}
return TRUE;

}

PIMAGE_NT_HEADERS GetNTHead(HANDLE imageBase) {
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)imageBase;
PIMAGE_NT_HEADERS pNthead = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew); //e_lfanew偏移

return pNthead;
}

void 读取PE文件头(HANDLE imageBase) {
PIMAGE_NT_HEADERS pNthead = GetNTHead(imageBase);
PIMAGE_FILE_HEADER pFileHeader = &pNthead->FileHeader;

printf("运行平台: %x\n", pFileHeader->Machine);
printf("节区数目: %x\n", pFileHeader->NumberOfSections);
printf("创建日期: %lu\n", pFileHeader->TimeDateStamp);
printf("可选头大小: %x\n", pFileHeader->SizeOfOptionalHeader);
printf("文件属性: %0x\n", pFileHeader->Machine);
printf("运行平台: 0x%08x\n", pFileHeader->Characteristics);

}

void 读取PE可选头(HANDLE imageBase) {
PIMAGE_NT_HEADERS pNthead = GetNTHead(imageBase);
PIMAGE_OPTIONAL_HEADER pOptionalHeader = &pNthead->OptionalHeader;

printf("入口点: %x\n", pOptionalHeader->AddressOfEntryPoint);
printf("基地址: %x\n", pOptionalHeader->ImageBase);
}

void 读取节表(HANDLE imageBase){
PIMAGE_NT_HEADERS pNthead = GetNTHead(imageBase);
PIMAGE_FILE_HEADER pFileHeader = &pNthead->FileHeader;
DWORD NumberOfSectionsCount = pFileHeader->NumberOfSections; //节表数量

PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNthead); //IMAGE_FIRST_SECTION 找到第一个节
printf("节区名称\tRVA_偏移\t节区大小\tRaw_尺寸\tRaw_偏移\t节区属性\t\n ");
for (size_t i = 0; i < NumberOfSectionsCount; i++, section++)
{
printf("%s\t", section->Name);
printf("0x%08x\t", section->VirtualAddress);
printf("0x%08x\t", section->Misc.VirtualSize);
printf("0x%08x\t", section->SizeOfRawData);
printf("0x%08x\t", section->PointerToRawData);
printf("0x%08x\t\n", section->Characteristics);
}

}


void 读取导入表(HANDLE imageBase) {
PIMAGE_NT_HEADERS pNthead = GetNTHead(imageBase);
PIMAGE_IMPORT_DESCRIPTOR dll描述符 = ImageRvaToVa(pNthead, imageBase, pNthead->OptionalHeader.DataDirectory[1].VirtualAddress, NULL); //存放各种dll

PIMAGE_THUNK_DATA stthunk = NULL;
DWORD dwthunk = NULL;
USHORT Hint;

printf("导入表为:\n");
printf("函数地址\t模块名称\t函数名称\t\n");
while (dll描述符->Name != NULL)
{
char* 模块名称 = ImageRvaToVa(pNthead, imageBase, dll描述符->Name, NULL);
stthunk = ImageRvaToVa(pNthead, imageBase, dll描述符->OriginalFirstThunk, NULL);
dwthunk = dll描述符->OriginalFirstThunk;
while (stthunk->u1.AddressOfData != NULL)
{
PIMAGE_IMPORT_BY_NAME funname = stthunk->u1.AddressOfData;
char* 函数名称 = ImageRvaToVa(pNthead, imageBase, funname->Name, NULL);
if (函数名称 != NULL) {
printf("%0.8x\t%s\t%s\n", dwthunk, 模块名称, 函数名称); //dwthunk 函数地址
}
dwthunk += 4;
stthunk++;
}
dll描述符++;
}

}



VOID 读取导出表(HANDLE ImageBase)
{
PIMAGE_EXPORT_DIRECTORY pExport;
PIMAGE_NT_HEADERS pNtHead = GetNTHead(ImageBase);

pExport = ImageRvaToVa(pNtHead, ImageBase, pNtHead->OptionalHeader.DataDirectory[0].VirtualAddress, NULL);
if (pExport == NULL) {
printf("导出表为空\n");
return;
}

DWORD NumberOfNames = pExport->NumberOfNames;
DWORD** ppdwNames = pExport->AddressOfNames;

ppdwNames = ImageRvaToVa(pNtHead, ImageBase, ppdwNames, NULL);

DWORD** ppdwAddr = pExport->AddressOfFunctions;

ppdwAddr = ImageRvaToVa(pNtHead, ImageBase, ppdwAddr, NULL);

char* szFunction = ImageRvaToVa(pNtHead, ImageBase, *ppdwNames, NULL);
printf("导出表为:\n");
printf("RVA_地址\t函数名称\t\n");

for (DWORD i = 0; i < NumberOfNames; i++)
{
printf("%0.8x\t%s\n", *ppdwAddr, szFunction); // RVA 函数名称
szFunction = szFunction + strlen(szFunction) + 1;
ppdwAddr++;
}
}




void main() {

HANDLE 基地址 = NULL;
基地址 = OpenPe("C:\\Users\\test\\Desktop\\menuedit.dll");
//基地址 = OpenPe("C:\\Users\\test\\Desktop\\32injectdll.dll");

//showDosHeadInfo(基地址);

if (isPE(基地址) == TRUE) {
读取PE文件头(基地址);
读取PE可选头(基地址);
读取节表(基地址);
读取导入表(基地址);
读取导出表(基地址);
}
else
{
printf("不是PE结构\n");
}

system("pause");
}

欢迎关注我的其它发布渠道

------------- 💖 🌞 本 文 结 束 😚 感 谢 您 的 阅 读 🌞 💖 -------------