
打印上图所示的导出表, 导入表, 重定位表以及所有的头部的信息
代码如下
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<Windows.h>
FILE* OpenFile(char path[]);
char* GetMemory(FILE* file_point);
void FreeMemory(FILE* file_point, char* memory_point[], int memory_size);
void conversion(PIMAGE_SECTION_HEADER section);
PIMAGE_DOS_HEADER dos_ptr(char* memory);
PIMAGE_NT_HEADERS nt_ptr(char* memory);
PIMAGE_FILE_HEADER file_ptr(char* memory);
PIMAGE_OPTIONAL_HEADER optional_ptr(char* memory);
PIMAGE_SECTION_HEADER section_ptr(char* memory);
PIMAGE_SECTION_HEADER last_section_ptr(char* memory);
void export_file(char* memory);
char* transform_to_file(char* memory, char* first);
char* transform_to_memory(char* memory, char* first);
DWORD get_largest_size(DWORD virtual_size, DWORD file_size);
DWORD* data_directory(char* memory);
void analysize(char path[]);
void print(char* memory);
void print_reloc(char* memory);
void print_export(char* memory);
void print_import(char* memory);
void conversion2(PIMAGE_SECTION_HEADER section);
FILE* OpenFile(char path[]) {
//打开文件
FILE* file_point;
int return1 = fopen_s(&file_point, path, "rb");
if (return1 != 0) {
printf("获取文件指针错误\n");
}
return file_point;
}
char* GetMemory(FILE* file_point) {
//开辟空间
fseek(file_point, 0, SEEK_END);
int file_size = ftell(file_point);
fseek(file_point, 0, SEEK_SET);
DWORD needed_size = sizeof(char) * file_size;
char* enter_memory = (char*)malloc(needed_size);
memset(enter_memory, 0, needed_size);
fread(enter_memory, file_size, 1, file_point);
return enter_memory;
}
void FreeMemory(FILE* file_point, char* memory_point[], int memory_size) {
for (int i = 0; i < memory_size; i++) {
free(memory_point[i]);
}
fclose(file_point);
}
void conversion(PIMAGE_SECTION_HEADER section) {
char* point = (char*)section;
printf("节表: ");
for (int i = 0; i < 8; i++) {
printf("%c", *point);
point++;
}
}
PIMAGE_DOS_HEADER dos_ptr(char* memory) {
return (PIMAGE_DOS_HEADER)(memory);
}
PIMAGE_NT_HEADERS nt_ptr(char* memory) {
return (PIMAGE_NT_HEADERS)((DWORD)dos_ptr(memory) + dos_ptr(memory)->e_lfanew);
}
PIMAGE_FILE_HEADER file_ptr(char* memory) {
return (PIMAGE_FILE_HEADER)((DWORD)nt_ptr(memory) + 4);
}
PIMAGE_OPTIONAL_HEADER optional_ptr(char* memory) {
return (PIMAGE_OPTIONAL_HEADER)((DWORD)file_ptr(memory) + 20);
}
PIMAGE_SECTION_HEADER section_ptr(char* memory) {
return (PIMAGE_SECTION_HEADER)(optional_ptr(memory) + 1);
}
PIMAGE_SECTION_HEADER last_section_ptr(char* memory) {
PIMAGE_SECTION_HEADER section = section_ptr(memory);
PIMAGE_FILE_HEADER file = file_ptr(memory);
int circle_num = file->NumberOfSections;
for (int i = 0; i < circle_num - 1; i++) {
section++;
}
return section;
}
void export_file(char* memory) {
FILE* win_file = NULL;
fopen_s(&win_file, "D:\\Ddisk\\last_memory.exe", "wb");
fseek(win_file, 0, SEEK_SET);
PIMAGE_OPTIONAL_HEADER optional = optional_ptr(memory);
//先导出头部数据
int sizeofHeaders = optional->SizeOfHeaders;
int fileAlignment = optional->FileAlignment;
if ((sizeofHeaders % fileAlignment) > 0) {
DWORD header_data = fileAlignment * ((sizeofHeaders / fileAlignment) + 1);
fwrite(memory, 1, header_data, win_file);
}
else if ((sizeofHeaders % fileAlignment) == 0) {
DWORD header_data2 = fileAlignment * (sizeofHeaders / fileAlignment);
fwrite(memory, 1, header_data2, win_file);
}
//导出各个
int section_num = file_ptr(memory)->NumberOfSections;
PIMAGE_SECTION_HEADER section = section_ptr(memory);
for (int i = 0; i < section_num; i++) {
fseek(win_file, section->PointerToRawData, SEEK_SET);
fwrite((char*)(section->PointerToRawData + (DWORD)memory), 1, section->SizeOfRawData, win_file);
section++;
}
fclose(win_file);
}
//转换rva到foa
//first代表文件开始地址, 根据开始地址找到内存基址和alignment, 节表个数
// if(memory-first>=内存基址){memory=memory-内存基址}
// if(memory<alignment){memory存在于header中, return memory}
// 定位到节表
//遍历节表信息, 依次比较if(VirtualAddress+VirtualSize>=memory>=VirtualAddress){
// 锁定节表序号, offset: memory-virtualAddress;
// 根据节表序号找到文件中的偏移, 文件偏移加offset为foa
char* transform_to_file(char* memory, char* first) {
//定位file并获取节表数量
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)first;
PIMAGE_FILE_HEADER file = (PIMAGE_FILE_HEADER)((DWORD)dos + dos->e_lfanew + 4);
int table_num = file->NumberOfSections;
//定位optional并获取内存基址与对齐
PIMAGE_OPTIONAL_HEADER optional = (PIMAGE_OPTIONAL_HEADER)(DWORD(file) + 20);
DWORD image_base = optional->ImageBase;
DWORD align = optional->SectionAlignment;
if ((int)(memory - first) >= (int)image_base) { memory = memory - image_base; }
if ((int)memory < (int)align) { return memory; }
PIMAGE_SECTION_HEADER section = NULL;
section = (PIMAGE_SECTION_HEADER)(optional + 1);
for (int i = 0; i < table_num; i++) {
if ((section->VirtualAddress + get_largest_size(section->Misc.VirtualSize, section->SizeOfRawData)) >= (DWORD)memory && (DWORD)memory >= section->VirtualAddress) {
return (char*)((DWORD)section->PointerToRawData + ((DWORD)memory - (DWORD)section->VirtualAddress));
break;
}
section++;
}
return (char*)-1;
}
char* transform_to_memory(char* memory, char* first) {
//定位file并获取节表数量
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)first;
PIMAGE_FILE_HEADER file = (PIMAGE_FILE_HEADER)((DWORD)dos + dos->e_lfanew + 4);
int table_num = file->NumberOfSections;
//定位optional并获取内存基址与对齐
PIMAGE_OPTIONAL_HEADER optional = (PIMAGE_OPTIONAL_HEADER)(DWORD(file) + 20);
DWORD image_base = optional->ImageBase;
DWORD align = optional->SectionAlignment;
if ((int)(memory - first) >= (int)image_base) { memory = memory - image_base; }
if ((int)memory < (int)align) { return memory; }
PIMAGE_SECTION_HEADER section = NULL;
section = (PIMAGE_SECTION_HEADER)(optional + 1);
for (int i = 0; i < table_num; i++) {
if (section->PointerToRawData + get_largest_size(section->Misc.VirtualSize, section->SizeOfRawData) >= (DWORD)memory && (DWORD)memory >= section->PointerToRawData) {
return (char*)((DWORD)section->VirtualAddress + ((DWORD)memory - (DWORD)section->PointerToRawData));
break;
}
section++;
}
return (char*)-1;
}
DWORD get_largest_size(DWORD virtual_size, DWORD file_size) {
if (virtual_size > file_size) {
return virtual_size;
}
else {
return file_size;
}
return 0;
}
//得到数据目录表存储的各个表的数据
DWORD* data_directory(char* memory) {
PIMAGE_OPTIONAL_HEADER optional = optional_ptr(memory);
DWORD* data_directory = (DWORD*)&optional->DataDirectory;
int directory_circle = optional->NumberOfRvaAndSizes;
DWORD sum_arr[32] = { 0 };
for (int i = 0; i < directory_circle; i++) {
sum_arr[i + 16] = *data_directory;
sum_arr[i] = (DWORD)(transform_to_file((char*)*data_directory, memory));
data_directory = data_directory + 2;
}
return sum_arr;
}
//翻译字符串
void conversion2(PIMAGE_SECTION_HEADER section) {
char* point = (char*)section;
printf("===================开始查找节表");
for (int i = 0; i < 8; i++) {
printf("%c", *point);
point++;
}printf("中信息=========================\n");
}
//打印重定位表
void print_reloc(char* memory) {
//打印重定位表
// 1.根据table_address[5]的的地址找到重定位表
DWORD* first_data = data_directory(memory);
DWORD table_address[32] = { 0 };
for (int i = 0; i < 32; i++) {
table_address[i] = *first_data;
first_data++;
}
printf("===================开始查找数据目录->重定位表中信息=========================\n");
if (table_address[5] == 0) { printf("不存在重定位表\n"); }
else {
printf("%x\n", table_address[5]);
printf("%x\n", memory);
printf("%x\n", (DWORD)memory + table_address[5]);
PIMAGE_BASE_RELOCATION reloc = (PIMAGE_BASE_RELOCATION)((DWORD)memory + table_address[5]);
int sign = 1;
WORD shift_pos = 0;
WORD judge = 0;
while (reloc->VirtualAddress != 0 && reloc->SizeOfBlock != 0) {
printf("%-2d: VirtualAddress:%-8x", sign, reloc->VirtualAddress);
printf("FOA:%-8x", ((DWORD)(reloc)-(DWORD)(memory)));
printf("SizeOfBlock:%x\n", reloc->SizeOfBlock);
printf("具体项数据为: \n");
DWORD times = (reloc->SizeOfBlock - 8) / 2;
short* position = (short*)((DWORD)reloc + 8);
for (int i = 1; i <= times; i++) {
shift_pos = *position;
judge = shift_pos;
shift_pos = shift_pos << 4;
shift_pos = shift_pos >> 4;
judge = judge >> 12;
if (judge == 3) {
printf("(%-3d)%-6x ", i, reloc->VirtualAddress + shift_pos);
}
position++;
}
printf("\n");
printf("废弃项数据为: \n");
short* position2 = (short*)((DWORD)reloc + 8);
for (int i = 1; i <= times; i++) {
shift_pos = *position2;
judge = shift_pos;
shift_pos = shift_pos << 4;
shift_pos = shift_pos >> 4;
judge = judge >> 12;
if (judge != 3) {
printf("(%-3d)%x ", i, reloc->VirtualAddress + shift_pos);
}
position2++;
}
printf("\n");
reloc = (PIMAGE_BASE_RELOCATION)((DWORD)reloc + reloc->SizeOfBlock);
sign++;
}
}
}
//打印导出表
void print_export(char* memory) {
// 1.根据table_address中的地址找到导出表的地址
// 2. 打印导出表的信息
DWORD* first_data = data_directory(memory);
DWORD table_address[32] = { 0 };
for (int i = 0; i < 32; i++) {
table_address[i] = *first_data;
first_data++;
}
printf("===================开始查找数据目录->导出表中信息=========================\n");
if (table_address[0] == 0) { printf("不存在导出表\n"); }
else {
PIMAGE_EXPORT_DIRECTORY export_table = (PIMAGE_EXPORT_DIRECTORY)((DWORD)table_address[0] + (DWORD)memory);
printf("Name(存储导出表文件名字符串的地址): %x\n", (DWORD)transform_to_file((char*)(export_table->Name), memory));
printf("Base(导出函数起始序号): %x\n", export_table->Base);
printf("NumberOfFunction(所有导出函数个数): %x\n", export_table->NumberOfFunctions);
printf("NumberOfNames(以函数名字导出的函数的个数): %x\n", export_table->NumberOfNames); printf("\n");
//打印导出表->地址表
printf("AddressOfFunction(导出函数地址表(FOA))地址: %x\n", (DWORD)transform_to_file((char*)(export_table->AddressOfFunctions), memory));
printf("AddressOfFunction(导出函数地址表(FOA))数据\n");
DWORD* export_address_data = (DWORD*)((DWORD)memory + (DWORD)transform_to_file((char*)export_table->AddressOfFunctions, memory));
int num = export_table->NumberOfFunctions;
for (int i = 0; i < num; i++) {
printf("RVA: %-8x", *export_address_data);
printf("FOA: %x\n", (DWORD)transform_to_file((char*)*export_address_data, memory));
export_address_data++;
}
printf("\n");
//打印导出表->名称表
printf("AddressOfNames(导出函数名称表(FOA)): %x\n", (DWORD)transform_to_file((char*)(export_table->AddressOfNames), memory));
printf("AddressOfFunction(导出函数名称表(FOA))数据\n");
DWORD* export_name_data = (DWORD*)((DWORD)memory + (DWORD)transform_to_file((char*)export_table->AddressOfNames, memory));
int num2 = export_table->NumberOfNames;
for (int i = 0; i < num2; i++) {
printf("RVA: %-8x", *export_name_data);
DWORD name_foa = (DWORD)transform_to_file((char*)*export_name_data, memory);
printf("FOA: %-8x", name_foa);
printf("FOA对应函数名称:");
char* new_name_foa = (memory + name_foa);
while (*new_name_foa != 0) {
printf("%c", *new_name_foa);
new_name_foa++;
}
export_name_data++;
printf("\n");
}
printf("\n");
//打印导出表->序号表
printf("AddressOfNameOrdinals(导出函数序号表RVA: %x, FOA: %x\n", export_table->AddressOfNameOrdinals, (DWORD)transform_to_file((char*)(export_table->AddressOfNameOrdinals), memory));
printf("AddressOfFunction(导出函数序号数据\n");
WORD* export_order_data = (WORD*)((DWORD)memory + (DWORD)transform_to_file((char*)export_table->AddressOfNameOrdinals, memory));
int num3 = export_table->NumberOfNames;
for (int i = 0; i < num3; i++) {
printf("%d: ", i);
printf("序号: %d ", *export_order_data);
printf("导出序号=序号+Base=%d+%d=%d\n", *export_order_data, export_table->Base, *export_order_data + export_table->Base);
printf("\n");
export_order_data++;
}
}
}
void print_import(char* memory) {
DWORD* first_data = data_directory(memory);
DWORD table_address[32] = { 0 };
for (int i = 0; i < 32; i++) {
table_address[i] = *first_data;
first_data++;
}
//打印导入表
printf("===================开始查找数据目录->导入表中信息=========================\n");
if (table_address[1] == 0) {
printf("不存在导入表\n");
}
else {
PIMAGE_IMPORT_DESCRIPTOR pimport = (PIMAGE_IMPORT_DESCRIPTOR)(table_address[1] + (DWORD)memory);
int i = 1;
while (pimport->Name != 0) {
//打印dll名字
printf("导入表%d所在FOA:%x\n", i, ((DWORD)pimport - (DWORD)memory));
printf("%-2d:", i);
char* name = (char*)(transform_to_file((char*)pimport->Name, memory) + (DWORD)memory);
printf("----------------------");
while (*name != 0) {
printf("%c", *name);
name++;
}
printf("---");
printf("TimeDateStamp: %x ", pimport->TimeDateStamp);
printf("----------------------");
printf("\n");
//打印OriginalFirstThunk
DWORD* oring_thunk = (DWORD*)transform_to_file((char*)pimport->OriginalFirstThunk, memory);
printf("OriginalFirstThunk所在: RVA:%-8xRVA->FOA:%-8x\n", pimport->OriginalFirstThunk, oring_thunk);
int j = 1;
printf("OrinGinalFirstThunk→ INT(导入名称表)\n");
DWORD* file_oring_thunk = (DWORD*)((DWORD)oring_thunk + (DWORD)memory);
while (*file_oring_thunk != 0) {
if ((*file_oring_thunk & 0x80000000) == 0x80000000) {
printf("(%-2d):%-4x\n", j, 0x7FFFFFFF & *file_oring_thunk);
}
else {
char* real_file_oring_thunk = (char*)((DWORD)(transform_to_file((char*)*file_oring_thunk, memory) + (DWORD)memory));
printf("(%-2d):RVA:%x, FOA:%x: ", j, *file_oring_thunk, transform_to_file((char*)*file_oring_thunk, memory));
PIMAGE_IMPORT_BY_NAME import_byname = (PIMAGE_IMPORT_BY_NAME)(real_file_oring_thunk);
printf("%x,%s\n", import_byname->Hint, import_byname->Name);
}
j++;
file_oring_thunk++;
}
printf("\n");
//打印FirstThunk
DWORD* firstThunk = (DWORD*)transform_to_file((char*)pimport->FirstThunk, memory);
printf("FirstThunk: RVA:%-8xRVA->FOA:%-8x\n", pimport->FirstThunk, firstThunk);
DWORD* file_firstThunk = (DWORD*)((DWORD)firstThunk + (DWORD)memory);
int k = 1;
printf("FirstThunk→ IAT(导入地址表)\n");
while (*file_firstThunk != 0) {
if ((*file_firstThunk & 0x80000000) == 0x80000000) {
printf("(%-2d):%-4x ", k, 0x7FFFFFFF & *file_firstThunk);
}
else {
printf("(%-2d):%x: ", k, transform_to_file((char*)*file_firstThunk, memory));
PIMAGE_IMPORT_BY_NAME import_byname = (PIMAGE_IMPORT_BY_NAME)(file_firstThunk);
printf("%x,%s\n", import_byname->Hint, import_byname->Name);
}
k++;
file_firstThunk++;
}
printf("\n");
printf("\n");
pimport++;
i++;
}
}
}
void print(char* memory) {
//打印dos头
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)memory;
printf("===================开始查找DOS头中信息=========================\n");
printf("Dos->e_magic: %x\n", dos->e_magic);
printf("Dos->e_lfanew: %x\n", dos->e_lfanew);
printf("\n");
//打印NT->PE标记头
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((DWORD)dos + dos->e_lfanew);
printf("===================开始查找NT->PE标记头中信息=========================\n");
printf("NT->PE标记: %x\n", *nt);
//打印NT->标准PE头
PIMAGE_FILE_HEADER file = (PIMAGE_FILE_HEADER)((DWORD)(nt)+4);
printf("\n");
printf("===================开始查找NT->标准PE头中信息=========================\n");
printf("Machine: %x\n", file->Machine);
printf("NumberOfSections(节表个数): %x\n", file->NumberOfSections);
printf("SizeOfOptionalHeader(可选PE头大小): %x\n", file->SizeOfOptionalHeader);
printf("\n");
//打印NT->可选PE头
PIMAGE_OPTIONAL_HEADER optional = (PIMAGE_OPTIONAL_HEADER)(DWORD(file) + 20);
printf("===================开始查找NT->可选PE头中信息=========================\n");
printf("PE->magic: %x\n", optional->Magic);
printf("Address Of EntryPoint(程序入口地址偏移): %x\n", optional->AddressOfEntryPoint);
printf("Image Base(内存基址): %x\n", optional->ImageBase);
printf("Section Alighment(内存对齐): %x\n", optional->SectionAlignment);
printf("File Alignment(文件对齐): %x\n", optional->FileAlignment);
printf("Size Of Image(内存大小): %x\n", optional->SizeOfImage);
printf("Size Of Headers(头文件大小): %x\n", optional->SizeOfHeaders);
printf("Number Of Rva And Sizes: %x\n", optional->NumberOfRvaAndSizes);
printf("\n");
//打印数据目录的偏移
DWORD* directory = (DWORD*)&optional->DataDirectory;
printf("===================开始查找NT->数据目录中信息=========================\n");
//打印各个数据目录的信息,创建table_address=table_p存储各个数据目录的地址(foa), table_before=table_p2存储rva
DWORD table_address[16] = { 0 };
DWORD table_before[16] = { 0 };
DWORD* table_p = table_address;
DWORD* table_p2 = table_before;
//数据目录终1
for (int i = 0; i < 16; i++) {
printf("内存偏移: %-8x ", *directory);
*table_p2 = (DWORD)*directory;
*table_p = (DWORD)transform_to_file((char*)*directory, memory);
printf("RVA->FOA: %-12x", *table_p);
table_p++;
table_p2++;
directory++;
printf("大小: %x\n", *directory++);
}printf("\n");
//打印节表
printf("\n");
PIMAGE_SECTION_HEADER section = (PIMAGE_SECTION_HEADER)(DWORD(optional) + file->SizeOfOptionalHeader);
for (int i = 0; i < file->NumberOfSections; i++) {
conversion(section);
printf("VirtualSize(对齐前所占大小(内存)): %x\n", section->Misc.VirtualSize);
printf("SizeOfRawData(对齐后所占大小(文件)): %x\n", section->SizeOfRawData);
printf("VirtualAddress(在内存中偏移(RVA)): %x\n", section->VirtualAddress);
printf("PointerToRawData(在文件中偏移(FOA)): %x\n", section->PointerToRawData);
printf("Characteristics(标志(块属性)): %x\n", section->Characteristics);
section++;
printf("\n");
}
}
void analysize(char path[]) {
FILE* file_point = OpenFile(path);
char* memory_point = GetMemory(file_point);
print(memory_point);
print_export(memory_point);
print_import(memory_point);
print_reloc(memory_point);
char* memory[] = { memory_point };
int num = (sizeof(memory)) / 4;
FreeMemory(file_point, memory, num);
}
int main() {
char dll[] = "D:\\Ddisk\\逆向\\AutoUpdateUtil.dll";
char last_memory[] = "D:\\Ddisk\\last_memory.exe";
char notepad[] = "C:\\Windows\\System32\\notepad.exe";
char crack[] = "D:\\Ddisk\\逆向\\CrackMe.exe";
analysize(notepad);
}
部分运行结果如下



这段代码主要实现了对PE文件的解析,包括打开文件、读取内存、释放内存等操作。它详细处理了PE文件的DOS头、NT头、可选头、节表,以及重定位表、导出表和导入表的信息。通过对内存地址的转换,代码能够打印出各种表的详细内容,如节名、虚拟地址、文件偏移等,并能将导出表的内容写入新的文件。
942

被折叠的 条评论
为什么被折叠?



