遍歷導入表和導出表見另一篇文章
運行效果如下:
代碼如下,獲取的是主要信息:
#include <stdio.h>
#include <windows.h>
#pragma warning(disable : 4996)
IMAGE_DOS_HEADER DosHeader;
PIMAGE_DOS_HEADER pDosHeader;
IMAGE_NT_HEADERS NtHeader;
PIMAGE_NT_HEADERS pNtHeader;
IMAGE_FILE_HEADER FileHeader;
PIMAGE_FILE_HEADER pFileHeader;
IMAGE_OPTIONAL_HEADER OptionHeader;
PIMAGE_OPTIONAL_HEADER pOptionHeader;
PIMAGE_DATA_DIRECTORY pDataDirectory;
IMAGE_SECTION_HEADER SectionHeader;
char * filepath = "atl.dll"; // 寫死
long e_lfanew;
DWORD RvaToRaw(PIMAGE_NT_HEADERS pNtHeader, DWORD Rva){
PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)IMAGE_FIRST_SECTION(pNtHeader);
for (int i = 0; i < pNtHeader->FileHeader.NumberOfSections; i++){
DWORD SectionBeginRva = pSectionHeader[i].VirtualAddress;
DWORD SectionEndRva = pSectionHeader[i].VirtualAddress + pSectionHeader[i].SizeOfRawData;
if (Rva >= SectionBeginRva && Rva <= SectionEndRva){
DWORD Temp = Rva - SectionBeginRva;
DWORD Rwa = Temp + pSectionHeader[i].PointerToRawData;
return Rwa;
}
}
}
void main(int argc, char * agrv[]){
HANDLE hFile = CreateFileA(filepath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
PVOID pbFile = MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (hFile == INVALID_HANDLE_VALUE || hMapping == NULL || pbFile == NULL){
printf("\n>>> 文件不存在\n");
if (hFile != INVALID_HANDLE_VALUE){
CloseHandle(hFile);
}
if (hMapping != NULL){
CloseHandle(hMapping);
}
if (pbFile != NULL){
UnmapViewOfFile(pbFile);
}
}
// 獲取DOS頭信息
puts("=================DOS_HEADER======================");
pDosHeader = (PIMAGE_DOS_HEADER)pbFile;
printf("e_magic(MZ頭): %X ", pDosHeader->e_magic);
char arry_dosheader_e_magic[sizeof(pDosHeader->e_magic)]; // 申請一塊MZ頭字段大小的空間,將MZ頭複製到該內存
memcpy(arry_dosheader_e_magic, &pDosHeader->e_magic, sizeof(pDosHeader->e_magic));
for (int i = 0; i < sizeof(pDosHeader->e_magic) && arry_dosheader_e_magic[i] != '\0'; i++){
printf("%c", arry_dosheader_e_magic[i]);
}
printf("\ne_lfanew(NT頭位置): %X\n", pDosHeader->e_lfanew);
pNtHeader = (PIMAGE_NT_HEADERS)((DWORD)pbFile + pDosHeader->e_lfanew);
// NT頭
puts("\n=================NT_HEADER=======================");
printf("Signature(PE標誌): %X ", pNtHeader->Signature);
char arry_nt_Signature[sizeof(pNtHeader->Signature)];
memcpy(arry_nt_Signature, &pNtHeader->Signature, sizeof(pNtHeader->Signature));
for (int i = 0; i < sizeof(pNtHeader->Signature) && arry_nt_Signature[i] != '\0'; i++){
printf("%c", arry_nt_Signature[i]);
}
// 文件頭
puts("\n\n==========================NT_FILE_HEADER=========================");
printf("NumberOfSections(節區數): %X\n", pNtHeader->FileHeader.NumberOfSections);
printf("TimeDateStamp(文件編譯時間): %X\n", pNtHeader->FileHeader.TimeDateStamp);
printf("SizeOfOptionalHeader(可選頭大小): %X\n", pNtHeader->FileHeader.SizeOfOptionalHeader);
printf("Characteristics(文件類型特徵值): %X\n", pNtHeader->FileHeader.Characteristics);
// 可選頭
puts("\n====================NT_OPTIONAL_HEADER(RVA)======================");
printf("AddressOfEntryPoint(程序執行入口點): %X\n", pNtHeader->OptionalHeader.AddressOfEntryPoint);
printf("BaseOfCode(代碼節地址): %X\n", pNtHeader->OptionalHeader.BaseOfCode);
printf("BaseOfData(數據節地址): %X\n", pNtHeader->OptionalHeader.BaseOfData);
printf("ImageBase(文件在內存中的基址): %X\n", pNtHeader->OptionalHeader.ImageBase);
printf("SectionAlignment(文件在內存中的節區對齊大小): %X\n", pNtHeader->OptionalHeader.SectionAlignment);
printf("FileAlignment(文件在磁盤中的節區對齊大小): %X\n", pNtHeader->OptionalHeader.FileAlignment);
printf("SizeOfImage(文件加載到內存中的大小): %X\n", pNtHeader->OptionalHeader.SizeOfImage);
printf("SizeOfHeaders(DOS頭+NT頭+節區表): %X\n", pNtHeader->OptionalHeader.SizeOfHeaders);
printf("NumberOfRvaAndSizes(數據目錄表的個數-bug): %X\n", pNtHeader->OptionalHeader.NumberOfRvaAndSizes);
/*打印數據目錄表*/
puts("\n=================PE IMAGE_DATA_DIRECTORY HEADER==================");
pDataDirectory = pNtHeader->OptionalHeader.DataDirectory;
printf("Table Name\t\tVirtualAddress\t\tSize\n\n");
printf("Export Table\t\t%08X\t\t%08X\n", pDataDirectory[0].VirtualAddress, pDataDirectory[0].Size);
printf("Import Table\t\t%08X\t\t%08X\n", pDataDirectory[1].VirtualAddress, pDataDirectory[1].Size);
printf("Resources Table\t\t%08X\t\t%08X\n", pDataDirectory[2].VirtualAddress, pDataDirectory[2].Size);
printf("Exception Table\t\t%08X\t\t%08X\n", pDataDirectory[3].VirtualAddress, pDataDirectory[3].Size);
printf("Security Table\t\t%08X\t\t%08X\n", pDataDirectory[4].VirtualAddress, pDataDirectory[4].Size);
printf("Base relocation Table\t%08X\t\t%08X\n", pDataDirectory[5].VirtualAddress, pDataDirectory[5].Size);
printf("Debug Table\t\t%08X\t\t%08X\n", pDataDirectory[6].VirtualAddress, pDataDirectory[6].Size);
printf("Copyrught Table\t\t%08X\t\t%08X\n", pDataDirectory[7].VirtualAddress, pDataDirectory[7].Size);
printf("Global Ptr Table\t%08X\t\t%08X\n", pDataDirectory[8].VirtualAddress, pDataDirectory[8].Size);
printf("TLS Table\t\t%08X\t\t%08X\n", pDataDirectory[9].VirtualAddress, pDataDirectory[9].Size);
printf("Load config Table\t%08X\t\t%08X\n", pDataDirectory[10].VirtualAddress, pDataDirectory[10].Size);
printf("Bound Import Table\t%08X\t\t%08X\n", pDataDirectory[11].VirtualAddress, pDataDirectory[11].Size);
printf("IAT Table\t\t%08X\t\t%08X\n", pDataDirectory[12].VirtualAddress, pDataDirectory[12].Size);
printf("Delay Import Table\t%08X\t\t%08X\n", pDataDirectory[13].VirtualAddress, pDataDirectory[13].Size);
printf("COM descriptor Table\t%08X\t\t%08X\n", pDataDirectory[14].VirtualAddress, pDataDirectory[14].Size);
printf("Retention Table\t\t%08X\t\t%08X\n", pDataDirectory[15].VirtualAddress, pDataDirectory[15].Size);
/* 打印SECTION頭 */
PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)IMAGE_FIRST_SECTION(pNtHeader);
puts("\n=========================SECTION HEADER==========================");
for (int count = 0; count < pNtHeader->FileHeader.NumberOfSections; count++){
// 打印節區標誌
printf("\n----------------");
char arry_section_text[sizeof(pSectionHeader->Name)];
memcpy(arry_section_text, &pSectionHeader->Name, sizeof(pSectionHeader->Name));
for (int i = 0; i < sizeof(pSectionHeader->Name) && arry_section_text[i] != '\0'; i++){
printf("%c", arry_section_text[i]);
}
printf("----------------\n");
printf("Name\t\t\t");
for (int i = 0; i < sizeof(pSectionHeader->Name) && arry_section_text[i] != '\0'; i++){
printf("%c", arry_section_text[i]);
}
printf("\nVirtualSize\t\t%08X\n", pSectionHeader->Misc.VirtualSize);
printf("VirtualAddress\t\t%08X\n", pSectionHeader->VirtualAddress);
printf("SizeOfRawData\t\t%08X\n", pSectionHeader->SizeOfRawData);
printf("PointerToRawData\t%08X\n", pSectionHeader->PointerToRawData);
//printf("PointerToRelocation\t%08X\n", pSectionHeader->PointerToRelocations);
//printf("PointerToLinenumbers\t%08X\n", pSectionHeader->PointerToLinenumbers);
//printf("NumberOfRelocations\t%04X\n", pSectionHeader->NumberOfRelocations);
//printf("NumberOfLinenumbers\t%04X\n", pSectionHeader->NumberOfLinenumbers);
printf("Characteristics\t\t%08X\n", pSectionHeader->Characteristics);
pSectionHeader++;
}
system("pause");
}
版本二:
#include <stdio.h>
#include <Windows.h>
#include <tchar.h>
#pragma warning(disable : 4996)
extern void DirectoryString(DWORD dwIndex);
char path[MAX_PATH]; // 文件路徑
int _tmain(int argc, _TCHAR* argv[])
{
// 選擇Virus文件
OPENFILENAMEA ofn;
memset(path, 0, MAX_PATH);
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.lpstrFile = path; // path
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFilter = "*.exe\0*.exe\0";
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (!GetOpenFileName(&ofn)) { // 如果打開文件錯誤
MessageBox(NULL, "Open file failed!", NULL, MB_OK);
exit(0); // 退出所有進程
}
// 獲取文件句柄,映射到內存
HANDLE hFile = CreateFileA(path, GENERIC_ALL, 3u, NULL, OPEN_EXISTING, 0x80u, 0); // path,第一個3u表示共享讀寫
// 獲取文件大小
DWORD dwFileSize = GetFileSize(hFile, NULL);
CHAR *pFileBuf = new CHAR[dwFileSize];
// 將文件讀取到內存
DWORD ReadSize = 0;
ReadFile(hFile, pFileBuf, dwFileSize, &ReadSize, NULL);
// 判斷是否爲PE文件
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuf;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
// 不是PE
printf("不是PE文件\n");
system("pause");
return 0;
}
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(pFileBuf + pDosHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
{
// 不是PE文件
printf("不是PE文件\n");
system("pause");
return 0;
}
// 獲取基本PE頭信息
// 獲取信息所用到的兩個結構體指針 (這兩個結構體都屬於NT頭)
PIMAGE_FILE_HEADER pFileHeader = &(pNtHeader->FileHeader);
PIMAGE_OPTIONAL_HEADER pOptionalHeader = &(pNtHeader->OptionalHeader);
// 輸出PE頭信息
printf("================== 基 本 P E 頭 信 息 ==================\n\n");
printf("入 口 點:\t%08X\t", pOptionalHeader->AddressOfEntryPoint);
printf("子 系 統:\t%04X\n", pOptionalHeader->Subsystem);
printf("鏡像基址:\t%08X\t", pOptionalHeader->ImageBase);
printf("區段數目:\t%04X\n", pFileHeader->NumberOfSections);
printf("鏡像大小:\t%08X\t", pOptionalHeader->SizeOfImage);
printf("日期時間標誌:\t%08X\n", pFileHeader->TimeDateStamp);
printf("代碼基址:\t%08X\t", pOptionalHeader->BaseOfCode);
printf("部首大小:\t%08X\n", pOptionalHeader->SizeOfHeaders);
printf("數據基址:\t%08X\t", pOptionalHeader->BaseOfData);
printf("特 徵 值:\t%04X\n", pFileHeader->Characteristics);
printf("塊 對 齊:\t%08X\t", pOptionalHeader->SectionAlignment);
printf("校 驗 和:\t%08X\n", pOptionalHeader->CheckSum);
printf("文件塊對齊:\t%08X\t", pOptionalHeader->FileAlignment);
printf("可選頭部大小:\t%04X\n", pFileHeader->SizeOfOptionalHeader);
printf("標 志 字:\t%04X\t\t", pOptionalHeader->Magic);
printf("RVA數及大小:\t%08X\n\n", pOptionalHeader->NumberOfRvaAndSizes);
printf("======================= 目 錄 表 =======================\n");
// 獲取目錄表頭指針,數據目錄表個數宏定義默認爲16
PIMAGE_DATA_DIRECTORY pDataDirectory = pOptionalHeader->DataDirectory;
printf("\t\t RAV\t\t 大小\n");
for (DWORD i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++)
{
DirectoryString(i);
printf("%08X\t%08X\n",
pDataDirectory[i].VirtualAddress, pDataDirectory[i].Size);
}
printf("======================= 區 段 表 =======================\n");
// 獲取區段表頭指針
PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(pNtHeader);
printf("名稱 VOffset VSize ROffset RSize 標誌\n");
// 獲取區段個數
DWORD dwSectionNum = pFileHeader->NumberOfSections;
// 根據區段個數遍歷區段信息
for (DWORD i = 0; i < dwSectionNum; i++, pSectionHeader++)
{
for (DWORD j = 0; j < IMAGE_SIZEOF_SHORT_NAME; j++)
{
printf("%c", pSectionHeader->Name[j]);
}
printf(" %08X %08X %08X %08X %08X\n",
pSectionHeader->VirtualAddress,
pSectionHeader->Misc.VirtualSize,
pSectionHeader->PointerToRawData,
pSectionHeader->SizeOfRawData,
pSectionHeader->Characteristics);
}
printf("\n");
system("pause");
return 0;
}
void DirectoryString(DWORD dwIndex)
{
switch (dwIndex)
{
case 0:printf("輸出表:\t\t");
break;
case 1:printf("輸入表:\t\t");
break;
case 2:printf("資源:\t\t");
break;
case 3:printf("異常:\t\t");
break;
case 4:printf("安全:\t\t");
break;
case 5:printf("重定位:\t\t");
break;
case 6:printf("調試:\t\t");
break;
case 7:printf("版權:\t\t");
break;
case 8:printf("全局指針:\t");
break;
case 9:printf("TLS表:\t\t");
break;
case 10:printf("載入配置:\t");
break;
case 11:printf("輸入範圍:\t");
break;
case 12:printf("IAT:\t\t");
break;
case 13:printf("延遲輸入:\t");
break;
case 14:printf("COM:\t\t");
break;
case 15:printf("保留:\t\t");
break;
}
}
效果: