// PE文件解析.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#define _CRT_SECURE_NO_WARNINGS
#include
#include
//函数向前声明
DWORD RvaToFoa(DWORD dwRva, const char* szBuffer);
char* LoadFile(const char* szFilePath);
void LoadDosHeader(const char* szBuffer);
void LoadFileHeader(const char* szBuffer);
void LoadOptionalHeader(const char* szBuffer);
void LoadDirectories(const char*szBuffer);
void LoadImportTable(const char* szBuffer);
void LoadSectionHeader(const char* szBuffer);
//数据目录表名称
const char* DataDirName[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]{
"EXPORT"
"IMPORT"
"RESOURCE",
"EXCEPTION",
"SECURITY",
"BASERELOC",
"DEBUG",
"COPYRIGHT",
"ARCHITECTURE",
"GLOBALPTR",
"TLS",
"LOAD_CONFIG",
"BOUND_IMPORT",
"IAT",
"DELAY_IMPORT",
"COM_DESCRIPTOR"
};
int main()
{
const char* FileBuffer = LoadFile("C:\\Users\\lenovo\\Desktop\\目标程序.exe");
printf("Dos Header:\r\n:");
LoadDosHeader(FileBuffer);
printf("File Header:");
LoadFileHeader(FileBuffer);
printf("OptionalHeader Header:");
LoadOptionalHeader(FileBuffer);
printf("Directories:\r\n");
LoadDirectories(FileBuffer);
printf("Sections Header:");
LoadSectionHeader(FileBuffer);
system("pause");
return 0;
}
DWORD RvaToFoa(DWORD dwRva, const char * szBuffer)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)szBuffer;
PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(szBuffer + pDosHeader->e_lfanew);
PIMAGE_FILE_HEADER pFileHeader = (PIMAGE_FILE_HEADER)&pNtHeaders->FileHeader;
PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)&pNtHeaders->OptionalHeader;
PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(pNtHeaders);
if (dwRva < pFileHeader->SizeOfOptionalHeader) {
return dwRva;
}
for (int i = 0; i < pFileHeader->NumberOfSections; i++) {
if (dwRva > pSectionHeader->VirtualAddress&&dwRva <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData) {
return dwRva - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
}
}
}
char* LoadFile(const char* szFilePath)
{
HANDLE hFile = CreateFileA(szFilePath, GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
return FALSE;
}
DWORD dwFileSize = GetFileSize(hFile, NULL);
char* szBuffer = new char[dwFileSize];
memset(szBuffer, 0, dwFileSize);
DWORD dwReadSize = 0;
BOOL bRet = ReadFile(hFile, szBuffer, dwFileSize, &dwReadSize, NULL);
if (bRet) {
return szBuffer;
}
else {
return NULL;
}
}
void LoadDosHeader(const char * szBuffer)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)szBuffer;
printf("Dos Tag:", pDosHeader->e_magic);
printf("PE Headers offset:%X\r\n", pDosHeader->e_lfanew);
}
void LoadFileHeader(const char * szBuffer)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)szBuffer;
PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(szBuffer + pDosHeader->e_lfanew);
printf("PE Tag:", pNtHeaders->Signature);
PIMAGE_FILE_HEADER pFileHeader = (PIMAGE_FILE_HEADER)&pNtHeaders->FileHeader;
printf("区段数目:%08X\t\n", pFileHeader->NumberOfSections);
printf("日期时间标志:%08X\t\n", pFileHeader->TimeDateStamp);
printf("可选PE头大小:%08X\t\n", pFileHeader->SizeOfOptionalHeader);
printf("特征值:%08X\t\n", pFileHeader->Characteristics);
}
void LoadOptionalHeader(const char * szBuffer)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)szBuffer;
PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(szBuffer + pDosHeader->e_lfanew);
PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)&pNtHeaders->OptionalHeader;
printf("入口点:%08X\t\n", pOptionalHeader->AddressOfEntryPoint);
printf("镜像地址:%08X\t\n", pOptionalHeader->ImageBase);
printf("镜像大小:%08X\t\n", pOptionalHeader->SizeOfImage);
printf("代码基址:%08X\t\n", pOptionalHeader->BaseOfCode);
printf("内存对齐:%08X\t\n", pOptionalHeader->SectionAlignment);
printf("文件对齐:%08X\t\n", pOptionalHeader->FileAlignment);
printf("标志:%08X\t\n", pOptionalHeader->Magic);
printf("子系统:%08X\t\n", pOptionalHeader->Subsystem);
printf("部首大小:%08X\t\n", pOptionalHeader->SizeOfHeaders);
printf("校验和:%08X\t\n", pOptionalHeader->CheckSum);
printf("数据目录表的个数:%08X\t\n", pOptionalHeader->NumberOfRvaAndSizes);
}
void LoadDirectories(const char * szBuffer)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)szBuffer;
PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(szBuffer + pDosHeader->e_lfanew);
PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)&pNtHeaders->OptionalHeader;
for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) {
printf("Name:%s\r\n", DataDirName[i]);
printf("VirtualAddress:0x%X\r\n", pOptionalHeader->DataDirectory[i].VirtualAddress);
printf("Size:0x%X\r\n\r\n",pOptionalHeader->DataDirectory[i].Size);
}
}
void LoadImportTable(const char * szBuffer)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)szBuffer;
PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(szBuffer + pDosHeader->e_lfanew);
PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)&pNtHeaders->OptionalHeader;
PIMAGE_DATA_DIRECTORY pImportDir = pOptionalHeader->DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT;
PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)(RvaToFoa(pImportDir->VirtualAddress, szBuffer) + szBuffer);
while (pImport->Name != NULL) {
char* szModuleName = (char*)(RvaToFoa(pImport->Name, szBuffer) + szBuffer);
printf("模块名称:%s\r\n", szModuleName);
printf("日期时间标志:%08X\r\n", pImport->TimeDateStamp);
printf("ForwarderChain:%08X\r\n", pImport->ForwarderChain);
printf("FirstThunk:%08X\r\n", pImport->FirstThunk);
printf("OriginaFirstThunk:%08X\r\n", pImport->OriginalFirstThunk);
//IAT表:
PIMAGE_THUNK_DATA pIAT = (PIMAGE_THUNK_DATA)(RvaToFoa(pImport->OriginalFirstThunk, szBuffer) + szBuffer);
DWORD dwIndex = 0;
while (pIAT->u1.Ordinal != 0) {
printf("ThunkRVA:%08X\r\n", pImport->OriginalFirstThunk + dwIndex);
printf("ThunkOffset:%08X\r\n", RvaToFoa(pImport->OriginalFirstThunk, szBuffer) + dwIndex);
dwIndex += 4;
if ((pIAT->u1.Ordinal & 0x80000000) != 1) {
PIMAGE_IMPORT_BY_NAME pName = (PIMAGE_IMPORT_BY_NAME)(RvaToFoa(pIAT->u1.AddressOfData, szBuffer) + szBuffer);
__try {
printf("API名称:%s\r\n", pName->Name);
printf("HINT:%04X\r\n", pName->Hint);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
int nOun = pIAT->u1.Function - 0x80000000;
char szNameBuffer[MAX_PATH] = { 0 };
sprintf(szNameBuffer, "序号:%Xh %dd", nOun, nOun);
printf("API名称:%s\r\n",szNameBuffer);
printf("HINT:-\r\n");
}
printf("ThunkValue:%08X\r\n\r\n", pIAT->u1.Function);
}
pIAT++;
}
pImport++;
}
}
void LoadSectionHeader(const char * szBuffer)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)szBuffer;
PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(szBuffer + pDosHeader->e_lfanew);
PIMAGE_FILE_HEADER pFileHeader = (PIMAGE_FILE_HEADER)&pNtHeaders->FileHeader;
PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)&pNtHeaders->OptionalHeader;
PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(pNtHeaders);
for (int i = 0; i < pFileHeader->NumberOfSections; i++) {
printf("Section %d:\r\n", i);
char szName[9] = { 0 };
memcpy(szName, pSectionHeader[i].Name, 8);
printf("VOffset(虚拟相对地址):%08X\r\n", pSectionHeader[i].VirtualAddress);
printf("VSIZE(区段大小):%d\r\n", pSectionHeader[i].Misc.VirtualSize);
printf("ROFFSET(文件偏移):%08X\r\n", pSectionHeader[i].PointerToRawData);
printf("RSIZE(文件中区段的大小):%X\r\n", pSectionHeader[i].SizeOfRawData);
printf("标记:%X\r\n\r\n", pSectionHeader[i].Characteristics);
}
}
dllmain:
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
//LPVOID OldMessageBoxW = NULL;
typedef int
(WINAPI *FuncMessageBoxW)(
_In_opt_ HWND hWnd,
_In_opt_ LPCWSTR lpText,
_In_opt_ LPCWSTR lpCaption,
_In_ UINT uType);
FuncMessageBoxW OldMessageBoxW = NULL;
int
WINAPI
MyMessageBoxW(
_In_opt_ HWND hWnd,
_In_opt_ LPCWSTR lpText,
_In_opt_ LPCWSTR lpCaption,
_In_ UINT uType) {
return OldMessageBoxW(hWnd, L"我的MessageBox", L"提示", NULL);
}
VOID IATHook() {
//保存原来的函数地址
OldMessageBoxW = (FuncMessageBoxW)GetProcAddress(GetModuleHandle(L"user32.dll"), "MessageBoxW");
//这里GetModuleHandle如果传入参数位NULL,那么就会获取.exe的基址
//获取头部信息
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle(NULL);
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)&pNtHeader->OptionalHeader;
//获取导出表地址偏移(这里时进程中获取的内存,所以我们之际使用RVA就可以)
DWORD dwImportTable = pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pDosHeader + dwImportTable);
PIMAGE_THUNK_DATA pFirstThunk;
while (pImport->Characteristics && pImport->FirstThunk != NULL) {
pFirstThunk = (PIMAGE_THUNK_DATA)(pImport->FirstThunk + (DWORD)pDosHeader);
while (*(DWORD*)pFirstThunk != NULL) {
if (*(DWORD*)pFirstThunk == (DWORD)OldMessageBoxW) {
DWORD dwOldProtect = 0;
VirtualProtectEx(GetCurrentProcess(), pFirstThunk, 0x8, PAGE_EXECUTE_READWRITE, &dwOldProtect);
DWORD dwFuncAddr = (DWORD)MyMessageBoxW;
memcpy(pFirstThunk, (DWORD*)&dwFuncAddr, 4);
VirtualProtectEx(GetCurrentProcess(), pFirstThunk, 0x8, PAGE_EXECUTE_READWRITE, &dwOldProtect);
}
pFirstThunk++;
}
pImport++;
}
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
IATHook();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
我们首先运行目标程序:
#include
#include
int main()
{
MessageBox(NULL, L"WdIg111", L"提示", NULL);
system("pause");
MessageBox(NULL, L"WdIg222", L"提示", NULL);
}