PE头分析详解和VC++代码实现
看雪论坛作者ID:菜鸟m号
//取得文件路径部分
TCHAR szFilePath[MAX_PATH];
OPENFILENAME ofn = { 0 };
memset(szFilePath, 0, MAX_PATH);
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.hInstance = GetModuleHandle(NULL);
ofn.nMaxFile = MAX_PATH;
ofn.lpstrInitialDir = L".";
ofn.lpstrFile = szFilePath;
ofn.lpstrTitle = L"选择PE文件";
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrFilter = L"(*.*)\0*.exe;*.dll\0";
GetOpenFileName(&ofn);
if (szFilePath == NULL)
{
MessageBox(NULL, L"打开文件错误", NULL, NULL);
return 0;
}
//创建文件句柄
HANDLE hFile = CreateFile(szFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
MessageBox(NULL, L"创建PE内核失败", NULL, NULL);
return 0;
}
//创建文件映射内核对象
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (NULL == hMapping)
{
CloseHandle(hFile);
hFile = NULL;
return 0;
}
//获得映射基地址
LPVOID ImageBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
if (NULL == ImageBase)
{
CloseHandle(hMapping);
CloseHandle(hFile);
hMapping = NULL;
hFile = NULL;
return FALSE;
}
//下面是DOS头分析/////////////////////////////////////////////////
PIMAGE_DOS_HEADER pDosHeader = NULL;
pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
MessageBox(NULL, TEXT("PE文件错误"), NULL, MB_OK);
}
//下面是获得NT头/////////////////////////////////////////////////////
PIMAGE_NT_HEADERS pNtHeader = NULL;
pNtHeader = (PIMAGE_NT_HEADERS)((DWORD)(pDosHeader->e_lfanew) + (DWORD)ImageBase);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
{
MessageBox(NULL, TEXT("PE文件错误"), NULL, MB_OK);
}
PIMAGE_FILE_HEADER pFileHeader = NULL;
pFileHeader = &pNtHeader->FileHeader;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
pOptionHeader = &pNtHeader->OptionalHeader;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
pSectionHeader = IMAGE_FIRST_SECTION(pNtHeader);
/***************** 显示需要的数据部分 *******************/
cout << "所有需要的关键信息如下:" << endl;
cout << "_IMAGE_DOS_HEADER RVA地址:" << hex << pDosHeader << endl;
cout << "e_magic值:" << hex << pDosHeader->e_magic << endl;
cout << "e_lfarlc值:" << hex << pDosHeader->e_lfarlc << endl << endl;
cout << "_IMAGE_NT_HEADERS RVA地址:" << hex << pNtHeader << endl;
cout << "Signature 值:" << hex << pNtHeader->Signature << endl << endl;
cout << "_IMAGE_FILE_HEADERS RVA地址:" << hex << pFileHeader << endl;
cout << "Machine 值:" << hex << pFileHeader->Machine << endl;
cout << "NumberOfSections 值:" << hex << pFileHeader->NumberOfSections << endl;
cout << "Characteristics 值:" << hex << pFileHeader->Characteristics << endl << endl;
cout << "_IMAGE_OPTION_HEADERS RVA地址:" << hex << pOptionHeader << endl;
cout << "Magic 值:" << hex << pOptionHeader->Magic << endl;
cout << "SizeOfCode 值:" << hex << pOptionHeader->SizeOfCode << endl;
cout << "AddressOfEntryPoint 值" << hex << pOptionHeader->AddressOfEntryPoint << endl;
cout << "ImageBase 值:" << hex << pOptionHeader->ImageBase << endl;
cout << "SectionAlignment 值" << hex << pOptionHeader->SectionAlignment << endl;
cout << "FileAlignment 值" << hex << pOptionHeader->FileAlignment << endl;
cout << "SizeOfImage 值:" << hex << pOptionHeader->SizeOfImage << endl << endl;
cout << "_IMAGE_SECTION_HEADERS RVA地址:" << pSectionHeader << endl;
for (int i = 0; i < pFileHeader->NumberOfSections; i++) //循环打印各个区段的值
{
cout << " Section Name:" << pSectionHeader->Name << endl;
cout << " VirtualAddress:" << hex << pSectionHeader->VirtualAddress << endl;
cout << " SizeOfRawData:" << hex << pSectionHeader->SizeOfRawData << endl;
cout << " PointerToRelocations:" << hex << pSectionHeader->PointerToRelocations << endl;
cout << " NumberOfLinenumbers:" << hex << pSectionHeader->NumberOfLinenumbers << endl;
cout << " Characteristics:" << hex << pSectionHeader->Characteristics << endl;
++pSectionHeader;
cout << endl;
}
{
char* szFuncName;
DWORD * pdwThunkRVA = NULL;
PIMAGE_IMPORT_BY_NAME pByName = NULL;
pdwThunkRVA = (DWORD*)ImageRvaToVa(pNtHeader, ImageBase, pImport->FirstThunk, NULL); //取出o指向的IAT地址,并转换成DWORD指针
if (!pdwThunkRVA)
{
return 0;
}
while (*pdwThunkRVA)
{
if (HIWORD(*pdwThunkRVA) == 0x8000)
{
cout << "函数序号:" << hex << *pdwThunkRVA << endl;
}
else
{
pByName = (PIMAGE_IMPORT_BY_NAME)ImageRvaToVa(pNtHeader, ImageBase, (DWORD)(*pdwThunkRVA), NULL);
if (pByName)
cout << "funName:" << (char*)pByName->Name << endl;
}
++pdwThunkRVA;
}
return 0;
}
void showIIDandIED( LPVOID ImageBase, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_OPTIONAL_HEADER pOptionHeader)
{
PIMAGE_IMPORT_DESCRIPTOR pImport = NULL;
DWORD IIDRVA;
IIDRVA = pOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; //记住是数组的第二项开始的,保存的是RVA值
pImport = (PIMAGE_IMPORT_DESCRIPTOR)ImageRvaToVa(pNtHeader, ImageBase, IIDRVA,NULL);//调用 imagehlp中的ImageRvaToVA
string name = "";
if (!pImport)
{
int error = GetLastError();
if (error == 0)
MessageBox(NULL, TEXT("文件没有输入表"), NULL, MB_OK);
else
MessageBox(NULL, TEXT("无法获得Import Directory"), NULL, MB_OK);
return;
}
while (pImport->FirstThunk)
{
cout << " DLLName: " << (char*)ImageRvaToVa(pNtHeader, ImageBase, pImport->Name, NULL) << endl; //四个参数
cout << " Characteristics: " << hex << pImport->Characteristics << endl;
cout << " ForwarderChain: " << hex << pImport->ForwarderChain << endl;
cout << " TimeDateStamp: " << hex << pImport->TimeDateStamp << endl;
cout << " OriginalFirstThunk(INT): " << hex << pImport->OriginalFirstThunk << endl;
cout << " FirstThunk(IAT):" << hex << pImport->FirstThunk << endl;
showIAT(pImport, ImageBase, pNtHeader, pOptionHeader);
cout << endl;
++pImport;
}
////////////////////////////////////////IED/////////////////////////////////////////////////////
cout << "//////////////////////////////文件导出表部分/////////////////////////////////////////" << endl;
PIMAGE_EXPORT_DIRECTORY pExportDir = NULL; //指向IED指针
pExportDir = (PIMAGE_EXPORT_DIRECTORY)ImageRvaToVa(pNtHeader, ImageBase, pOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress,NULL);
if (!pExportDir)
{
int error = GetLastError();
if (error == 0)
MessageBox(NULL, TEXT("文件没有输出表"), NULL, MB_OK);
else
MessageBox(NULL, TEXT("无法获得Export Directory"), NULL, MB_OK);
return;
}
cout << " AddressOfFunctions: " << hex << pExportDir->AddressOfFunctions << endl;
cout << " AddressOfNameOrdinals: " << hex << pExportDir->AddressOfNameOrdinals << endl;
cout << " AddressOfNames: " << hex << pExportDir->AddressOfNames << endl;
cout << " Base: " << hex << pExportDir->Base << endl;
cout << " MajorVersion: " << hex << pExportDir->MajorVersion << endl;
cout << " MinorVersion: " << hex << pExportDir->MinorVersion << endl;
cout << " Characteristics: " << hex << pExportDir->Characteristics << endl;
cout << " Name: " << hex << pExportDir->Name << endl;
cout << " NumberOfFunctions: " << hex << pExportDir->NumberOfFunctions << endl;
cout << " NumberOfNames: " << hex << pExportDir->NumberOfNames << endl;
cout << " TimeDateStamp: " << hex << pExportDir->TimeDateStamp << endl;
//cout << " pExportDir->Name: " << (char*)ImageRvaToVa(pNTH, LocalImageBase, pExportDir->Name, NULL) << endl;
char* szFuncName;
UINT NumOfName = 0;
PDWORD pEAT, pENT;
PWORD pEOT;
UINT i = 0, j = 0, k = 0;
pEOT = (PWORD)ImageRvaToVa(pNtHeader, ImageBase, pExportDir->AddressOfNameOrdinals,NULL);
pEAT = (PDWORD)ImageRvaToVa(pNtHeader, ImageBase, pExportDir->AddressOfFunctions,NULL);
pENT = (PDWORD)ImageRvaToVa(pNtHeader, ImageBase, pExportDir->AddressOfNames,NULL);
NumOfName = pExportDir->NumberOfNames; //函数名字数量
if (!pEAT)
return;
for (i = 0; i < pExportDir->NumberOfFunctions; i++)
{
if (*pEAT)
{
for (j = 0; j < NumOfName; j++)
{
if (i == pEOT[j])
{
szFuncName = (char*)ImageRvaToVa(pNtHeader, ImageBase, pENT[j],NULL);
cout <<"FunctioRVA:"<< pEAT[i] <<'\t'<<"FunctionName:"<< szFuncName<<endl;
}
}
}
++pEAT;
}
}
using namespace std;
string TCHAR2STRING(TCHAR* STR) //tchar转string
{
int iLen = WideCharToMultiByte(CP_ACP, 0, STR, -1, NULL, 0, NULL, NULL);
char* chRtn = new char[iLen * sizeof(char)];
WideCharToMultiByte(CP_ACP, 0, STR, -1, chRtn, iLen, NULL, NULL);
std::string str(chRtn);
return str;
}
HMODULE GetProcessModuleHandle(DWORD pid, CONST TCHAR* moduleName) { // 根据 PID 、模块名(需要写后缀,如:".dll"),获取模块入口地址。
MODULEENTRY32 moduleEntry;
HANDLE handle = NULL;
handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid); // 获取进程快照中包含在th32ProcessID中指定的进程的所有的模块。
if (!handle) {
CloseHandle(handle);
return NULL;
}
ZeroMemory(&moduleEntry, sizeof(MODULEENTRY32));
moduleEntry.dwSize = sizeof(MODULEENTRY32);
if (!Module32First(handle, &moduleEntry)) {
CloseHandle(handle);
return NULL;
}
do {
if (_tcscmp(moduleEntry.szModule, moduleName) == 0) { return moduleEntry.hModule; }
} while (Module32Next(handle, &moduleEntry));
CloseHandle(handle);
return 0;
}
string NameOfexe(string name) //自定义一个取出文件地址绝对路径剔除多余参数函数
{
string exeName;
int k=0;
for (int i = 0; i< name.length(); i++)
{
if (name[i] == '\\'){
k = i;
for (int j = i; j < name.length() - i; j++)
{
if (name[j] == '\\')
break;
}
}
}
int k2 = 0;
int i = k+1;
for(i; i < name.length(); i++)
{
exeName+= name[i];
k2++;
}
return exeName;
}
TCHAR* char2TCAHR(const char* str) //char*转tchar*
{
int size = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
TCHAR* retStr = new TCHAR[size * sizeof(TCHAR)];
MultiByteToWideChar(CP_ACP, 0, str, -1, retStr, size);
return retStr;
}
void showAllImageBase(TCHAR *name, LPVOID ImageBase, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_OPTIONAL_HEADER pOptionHeader){
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // 进程快照句柄
PROCESSENTRY32 process = { sizeof(PROCESSENTRY32) }; // 存放进程快照的结构体
/*下面这部分是取出导入表DLL名字,保存起来用来,和之前实验的一样。*/
PIMAGE_IMPORT_DESCRIPTOR pImport = NULL;
DWORD IIDRVA;
IIDRVA = pOptionHeader->DataDirectory[1].VirtualAddress; //记住是数组的第二项开始的,保存的是RVA值
pImport = (PIMAGE_IMPORT_DESCRIPTOR)ImageRvaToVa(pNtHeader, ImageBase, IIDRVA, NULL);//调用 imagehlp中的ImageRvaToVA
// 遍历进程
char* a;
int k = 0;
while (Process32Next(hProcessSnap, &process)) {
// .exe 进程
string s_szExeFile = TCHAR2STRING(process.szExeFile); // char* 转 string
if (s_szExeFile == NameOfexe(TCHAR2STRING(name)))
{
cout << NameOfexe(TCHAR2STRING(name)) <<'\t'<<"基地址:"<< ImageBase << endl;
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process.th32ProcessID); // 进程句柄
while (pImport->FirstThunk)
{
a= (char*)ImageRvaToVa(pNtHeader, ImageBase, pImport->Name,NULL) ;
cout << a;
cout <<'\t'<< "模块VA地址:" << GetProcessModuleHandle(process.th32ProcessID, char2TCAHR(a)) << endl;
++pImport;
}
k = 1;
}
}
if (k == 0) //程序没有运行
{
STARTUPINFO si; //一些必备参数设置
memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW;
PROCESS_INFORMATION pi; //必备参数设置结束
if (!CreateProcess(NULL, name, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) //
{
cout << "Create Fail!" << endl;
}
Sleep(1000);
HANDLE hProcessSnap1 = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // 进程快照句柄
PROCESSENTRY32 process1 = { sizeof(PROCESSENTRY32) }; // 存放进程快照的结构体
char* a;
while (Process32Next(hProcessSnap1, &process1)) {
// .exe 进程
string s_szExeFile = TCHAR2STRING(process1.szExeFile); // char* 转 string
if (s_szExeFile == NameOfexe(TCHAR2STRING(name)))
{
cout << NameOfexe(TCHAR2STRING(name)) << ImageBase << endl;
HANDLE hProcess1 = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process1.th32ProcessID); // 进程句柄
while (pImport->FirstThunk)
{
a = (char*)ImageRvaToVa(pNtHeader, ImageBase, pImport->Name, NULL);
cout << a;
cout <<'\t'<< "模块VA地址:" << GetProcessModuleHandle(process1.th32ProcessID, char2TCAHR(a)) << endl;
++pImport;
}
k = 1;
}
}
}
}
int FindPID(string name)
{
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE) {
cout << "CreateToolhelp32Snapshot Error!" << endl;;
return false;
}
BOOL bResult = Process32First(hProcessSnap, &pe32);
int num(0);
while (bResult)
{
if (TCHAR2STRING(pe32.szExeFile) == NameOfexe(name))
{
return pe32.th32ProcessID;
}
bResult = Process32Next(hProcessSnap, &pe32);
}
CloseHandle(hProcessSnap);
return -1;
}
/*int string2tchar(std::string& src, TCHAR* buf)
{
#ifdef UNICODE
_stprintf_s(buf, MAX_PATH, _T("%S"), src.c_str());//%S宽字符
#else
_stprintf_s(buf, MAX_PATH, _T("%s"), src.c_str());//%s单字符
#endif
return 0;
}*/
void showAllImageBase2(TCHAR* name, LPVOID ImageBase, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_OPTIONAL_HEADER pOptionHeader)
{
//std::cout << FindPID(TCHAR2STRING(name));
STARTUPINFO si; //一些必备参数设置
memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW;
PROCESS_INFORMATION pi; //必备参数设置结束
string vmmapName = "S:\\14-VMMap.exe";
vmmapName += " ";
vmmapName += to_string(FindPID(TCHAR2STRING(name)));
//cout << vmmapName << endl;
TCHAR wc[MAX_PATH];
_stprintf_s(wc, MAX_PATH, _T("%S"), vmmapName.c_str());//%S宽字符
_stprintf_s(wc, MAX_PATH, _T("%s"), vmmapName.c_str());//%s单字符
if (!CreateProcess(NULL,wc , NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) //
{
cout << "Create Fail!" << endl;
}
}
看雪ID:菜鸟m号
https://bbs.pediy.com/user-856851.htm
推荐文章++++
进阶安全圈,不得不读的一本书