C++ 读取PE文件信息(读取PE导入表等)
今天突然想自己实现一个PEID小工具,无奈颈椎不好啊,写好了核心代码只好匆匆结束了,不敢独享,拿出来与诸位朋友共勉了。// ReadPEInfo.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <Dbghelp.h>
void ReadNTPEInfo(PIMAGE_NT_HEADERS pImageNtPE);
ULONG RvaToOffset(IMAGE_NT_HEADERS * pNtHeader,ULONG Rva);
#define pNtHeaders pImageNtHeaders
int _tmain(int argc, _TCHAR* argv[])
{
char file[]="win32.exe";
//DOS头
PIMAGE_DOS_HEADER pImageDosHeader;
//NT头(包括PE标识+Image_File_Header+OptionHeader)
PIMAGE_NT_HEADERS pImageNtHeaders;
//标准PE头、
PIMAGE_FILE_HEADER pImageFileHeader;
//扩展PE头
IMAGE_OPTIONAL_HEADER32 pImageOptionHeaders;
HANDLE hFile;
HANDLE hMapObject;
//DOS头
PUCHAR uFileMap;
hFile= CreateFile(file,GENERIC_READ,0,NULL,OPEN_EXISTING,0,0);
if(hFile==NULL)
{
printf("打开文件失败\n");
system("pause");
return 0;
}
hMapObject=CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
if(hMapObject==NULL)
{
printf("创建文件映射内核对对象失败\n");
system("pause");
return 0;
}
//PE基址
uFileMap=(PUCHAR)MapViewOfFile(hMapObject,FILE_MAP_READ,0,0,0);
if(uFileMap==NULL)
{
printf("映射到进程地址空间失败\n");
system("pause");
return 0;
}
pImageDosHeader=(PIMAGE_DOS_HEADER)uFileMap;
if(pImageDosHeader->e_magic!=IMAGE_DOS_SIGNATURE)
{
printf("不是PE结构\n");
system("pause");
return 0;
}
//定位到NT PE头
pImageNtHeaders=(PIMAGE_NT_HEADERS)((PUCHAR)uFileMap+pImageDosHeader->e_lfanew);
//导入表的相对虚拟地址(RVA)
ULONG rva_ofimporttable=pImageNtHeaders->OptionalHeader.DataDirectory.VirtualAddress;
//根据相对虚拟(rva)地址计算偏移地址(offset)
ULONG offset_importtable=RvaToOffset(pImageNtHeaders,rva_ofimporttable);
if(!offset_importtable)
{
printf("获取导入表偏移地址失败\n");
system("pause");
return 0;
}
PIMAGE_THUNK_DATA s;
//取得导入表的地址
IMAGE_IMPORT_DESCRIPTOR *pImportTable=(IMAGE_IMPORT_DESCRIPTOR *)((char*)uFileMap+offset_importtable);
IMAGE_IMPORT_DESCRIPTOR null_iid;
IMAGE_THUNK_DATA null_thunk;
memset(&null_iid, 0, sizeof(null_iid));
memset(&null_thunk, 0, sizeof(null_thunk));
//每个元素代表了一个引入的DLL。
for(int i=0; memcmp(pImportTable + i, &null_iid, sizeof(null_iid))!=0; i++)
{
char *dllName= (char*)(uFileMap+RvaToOffset(pImageNtHeaders,pImportTable.Name));
//拿到了DLL的名字
printf("模块[%d]: %s\n", i, (char*)dllName);
PIMAGE_THUNK_DATA32 pThunk=(PIMAGE_THUNK_DATA32)(uFileMap+RvaToOffset(pImageNtHeaders,pImportTable.FirstThunk));
while(pThunk->u1.Ordinal!=NULL)
{
PIMAGE_IMPORT_BY_NAME pname=(PIMAGE_IMPORT_BY_NAME)(uFileMap+RvaToOffset(pImageNtHeaders,pThunk->u1.AddressOfData));
printf("函数编号: %d 名称: %s\n",pname->Hint,pname->Name);
pThunk++;
}
}
system("pause");
return 0;
}
void ReadNTPEInfo(PIMAGE_NT_HEADERS pImageNtPE)
{
printf("运行平台: 0x%04X\n",pImageNtPE->FileHeader.Machine);
printf("节数量: %d\n",pImageNtPE->FileHeader.NumberOfSections);
printf("PE属性: 0x%04X\n",pImageNtPE->FileHeader.Characteristics);
}
//计算Offset
ULONG RvaToOffset(IMAGE_NT_HEADERS * pNtHeader,ULONG Rva)
{
//PE节
IMAGE_SECTION_HEADER *p_section_header;
ULONG sNum,i;
//取得节表项数目
sNum=pNtHeader->FileHeader.NumberOfSections;
//取得第一个节表项
p_section_header=(IMAGE_SECTION_HEADER *)
((BYTE *)pNtHeader+sizeof(IMAGE_NT_HEADERS));
for(i=0;i<sNum;i++)
{
//printf("PE 节名称: %s\n",p_section_header->Name);
if((p_section_header->VirtualAddress<=Rva)&&Rva<(p_section_header->VirtualAddress+p_section_header->SizeOfRawData))
{
return Rva-p_section_header->VirtualAddress+p_section_header->PointerToRawData;
}
p_section_header++;
}
return 0;
}
支持共享精神.... 支持楼主 看上去不错的样子 支持 一下楼主 {:301_1003:} 后排支持下楼主、 前排举爪支持,。
看上去不错的样子 支持 一下楼主{:17_1073:}
页:
[1]