【C++】PE头、区段块、输入表分析
刚刚开始学C++,想找个东西练练手。索性一不做二不休先拿PE格式开刀。所以代码写得糊的地方欢迎各位大佬指正!
这份代码主要演示了PE头、区块段、输入表这三部分。窃以为是PE文件格式中最重要的。输出表、TLS、重定向等内容扫了一眼感觉没有输入表复杂。所以写完了输入表就告一段落了。以及为了方便移植到别的程序里,这份代码没有使用w32api。我总感觉读入和读出还有再优化的空间。如果移植的话可能要处理一下两个头文件的定义
最后,这段代码兼容了x64的PE格式,x64和x86大同小异,但其实有一些坑,比如x64在header里面没有BaseOfData,如果用x86的定义就会翻车。给一起学习的朋友提个醒
来52发的第一篇文章,请多指教!
// PEStudy.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <fstream>
#include <string>
#include <Windows.h>
#include <winnt.h>
void debugOut(std::string outstr);
char (*readFile(std::string strPath, int intStart, int intLength));
char (*readFile(std::string strPath, int intStart, int intLength)) {
char* lpBuffer = new char;
std::ifstream objInstream;
objInstream.open(strPath, std::ios::in + std::ios::binary);
objInstream.seekg(intStart, std::ios::beg);
objInstream.read(lpBuffer, intLength);
return lpBuffer;
}
void debugOut(std::string outstr, long value) {
std::cout << outstr << std::hex << value << std::endl;
}
int main()
{
IMAGE_DOS_HEADER* lpDosheader;
IMAGE_NT_HEADERS* lpNtheader;
IMAGE_NT_HEADERS64* lpNtheader64;
IMAGE_SECTION_HEADER* lpSection;
IMAGE_IMPORT_DESCRIPTOR* lpImport;
IMAGE_THUNK_DATA* lpThunk = NULL;
IMAGE_THUNK_DATA64* lpThunk64 = NULL;
IMAGE_IMPORT_BY_NAME* lpImportByName;
int intNumberofSection = 0;
int intSectiontablePointer = 0;
int intImportVA = 0;
int intImportDiff = 0; //the difference of VA and file_offset in the section that Import-Table belongs to.
int intImportTableLoc = 0;
int intImportSize = 0;
int i = 0;
int j = 0;
std::string strPath = "d:\\temp\\Display.dll";
lpDosheader = (IMAGE_DOS_HEADER*)readFile(strPath, 0, sizeof(IMAGE_DOS_HEADER));
debugOut("DOSHeader->e_lfanew: ", (*lpDosheader).e_lfanew);
lpNtheader = (IMAGE_NT_HEADERS*)readFile(strPath, (*lpDosheader).e_lfanew, sizeof(IMAGE_NT_HEADERS));
debugOut("NTheader->Signature: ", (*lpNtheader).Signature);
if ((*lpNtheader).OptionalHeader.Magic == 0x10) {
//x86
std::cout << " x86" << std::endl;
debugOut("NTheader->FileHeader->NumberOfSections: ", (*lpNtheader).FileHeader.NumberOfSections);
debugOut("NTheader->FileHeader->Characteristics: ", (*lpNtheader).FileHeader.Characteristics);
debugOut("NTheader->OptionalHeader->Magic (x86/x64: )", (*lpNtheader).OptionalHeader.Magic);
debugOut("NTheader->OptionalHeader->BaseOfCode: ", (*lpNtheader).OptionalHeader.BaseOfCode);
debugOut("NTheader->OptionalHeader->BaseOfData: ", (*lpNtheader).OptionalHeader.BaseOfData);
debugOut("NTheader->OptionalHeader->ImageBase: ", (*lpNtheader).OptionalHeader.ImageBase);
debugOut("NTheader->OptionalHeader->SectionAlignment: ", (*lpNtheader).OptionalHeader.SectionAlignment);
debugOut("NTheader->OptionalHeader->FileAlignment: ", (*lpNtheader).OptionalHeader.FileAlignment);
debugOut("NTheader->OptionalHeader->DataDirectory.Size (Import Table Size):", (*lpNtheader).OptionalHeader.DataDirectory.Size);
debugOut("NTheader->OptionalHeader->DataDirectory.VA (Import Table VA):", (*lpNtheader).OptionalHeader.DataDirectory.VirtualAddress);
intSectiontablePointer = (*lpDosheader).e_lfanew + sizeof(IMAGE_NT_HEADERS32);
intNumberofSection = (*lpNtheader).FileHeader.NumberOfSections;
intImportVA = (*lpNtheader).OptionalHeader.DataDirectory.VirtualAddress;
intImportSize = (*lpNtheader).OptionalHeader.DataDirectory.Size;
}
else {
//x64 slightly different from x86
std::cout << " x64" << std::endl;
lpNtheader64 = (IMAGE_NT_HEADERS64*)lpNtheader;
debugOut("NTheader->FileHeader->NumberOfSections: ", (*lpNtheader64).FileHeader.NumberOfSections);
debugOut("NTheader->FileHeader->Characteristics: ", (*lpNtheader64).FileHeader.Characteristics);
debugOut("NTheader->OptionalHeader->Magic (x86/x64: )", (*lpNtheader64).OptionalHeader.Magic);
debugOut("NTheader->OptionalHeader->BaseOfCode: ", (*lpNtheader64).OptionalHeader.BaseOfCode);
debugOut("NTheader->OptionalHeader->ImageBase: ", (*lpNtheader64).OptionalHeader.ImageBase);
debugOut("NTheader->OptionalHeader->SectionAlignment: ", (*lpNtheader64).OptionalHeader.SectionAlignment);
debugOut("NTheader->OptionalHeader->FileAlignment: ", (*lpNtheader64).OptionalHeader.FileAlignment);
debugOut("NTheader->OptionalHeader->DataDirectory.Size (Import Table Size):", (*lpNtheader64).OptionalHeader.DataDirectory.Size);
debugOut("NTheader->OptionalHeader->DataDirectory.VA (Import Table VA):", (*lpNtheader64).OptionalHeader.DataDirectory.VirtualAddress);
intSectiontablePointer = (*lpDosheader).e_lfanew + sizeof(IMAGE_NT_HEADERS64);
intNumberofSection = (*lpNtheader64).FileHeader.NumberOfSections;
intImportVA = (*lpNtheader64).OptionalHeader.DataDirectory.VirtualAddress;
intImportSize = (*lpNtheader64).OptionalHeader.DataDirectory.Size;
}
lpSection = (IMAGE_SECTION_HEADER*)readFile(strPath, intSectiontablePointer, intNumberofSection * sizeof(IMAGE_SECTION_HEADER));
std::cout << "--Section--" << std::endl;
for (int i = 0; i < intNumberofSection; i++) {
std::cout <<"Name:" << lpSection.Name << std::endl;
std::cout << "VirtualAddress: " << lpSection.VirtualAddress << std::endl;
std::cout << "PointerToRawdata: " << lpSection.PointerToRawData << std::endl;
std::cout << "Characteristics: " << lpSection.Characteristics << std::endl;
}
std::cout << "--Import Table--" << std::endl;
//Step1: Get Location of Import Table in Sections
int intFlag = 0;
for (i = 0; i < intNumberofSection; i++) {
if ((lpSection.VirtualAddress <= intImportVA) && (intImportVA <= lpSection.VirtualAddress + lpSection.SizeOfRawData)) {
intFlag = i;
break;
}
}
std::cout << "Import Table in section: " << lpSection.Name << std::endl;
//Step2: Calculate the diff of VA and file_offset
intImportDiff = lpSection.VirtualAddress - lpSection.PointerToRawData;
//Step3: Calculate the file_offset of Import-Table
intImportTableLoc = intImportVA - intImportDiff;
lpImport = (IMAGE_IMPORT_DESCRIPTOR*)readFile(strPath, intImportTableLoc, intImportSize);
i = 0;
do {
std::cout << "IID #" << i << std::endl;
debugOut("IID->OriginalFirstThunk(file_offset): ", lpImport.OriginalFirstThunk - intImportDiff);
std::cout << "IID->Name: " << readFile(strPath, lpImport.Name - intImportDiff, 255) << std::endl; //may memoryleak
debugOut("IID->FirstChunk(file_offset): ", lpImport.FirstThunk - intImportDiff);
lpThunk = (IMAGE_THUNK_DATA*)readFile(strPath, lpImport.FirstThunk - intImportDiff, 2000); //may bug
lpThunk64 = (IMAGE_THUNK_DATA64*)lpThunk;
j = 0;
if ((*lpNtheader).OptionalHeader.Magic == 0x10) {
//x86
do {
if (lpThunk.u1.AddressOfData & IMAGE_ORDINAL_FLAG32) {
//the top digit equaling 1 indicates that the THUNK_DATA is ordinal
debugOut("->By Ordinal, value = ", lpThunk.u1.AddressOfData & 0xfffffff);
}
else {
lpImportByName = (IMAGE_IMPORT_BY_NAME*)readFile(strPath, lpThunk.u1.AddressOfData - intImportDiff, 257); //note: may bug when import table isn't located in the same section as thunk, which is rare.
std::cout << "#" << (*lpImportByName).Hint << " -> " << (*lpImportByName).Name << std::endl;
}
j++;
} while (lpThunk.u1.AddressOfData != 0);
}
else {
//x64
do {
if (lpThunk64.u1.AddressOfData & IMAGE_ORDINAL_FLAG64) {
//the top digit equaling 1 indicates that the THUNK_DATA is ordinal
debugOut("->By Ordinal, value = ", lpThunk64.u1.AddressOfData & 0xfffffffffffffff);
}
else {
lpImportByName = (IMAGE_IMPORT_BY_NAME*)readFile(strPath, lpThunk64.u1.AddressOfData - intImportDiff, 257); //note: may bug when import table isn't located in the same section as thunk, which is rare.
std::cout << "#" << (*lpImportByName).Hint << " -> " << (*lpImportByName).Name << std::endl;
}
j++;
} while (lpThunk64.u1.AddressOfData != 0);
}
i++;
} while (lpImport.Name != 0);
delete lpSection;
delete lpDosheader;
delete lpNtheader;
}
页:
[1]