最近重新撸了一遍PE文件的文件格式,这个程序算是复习的产物吧。
说明与警告:
1.只适用于32位PE文件,可以读取符合标准的32位PE文件的DOS头、NT头、节区头、导入表、导出表信息,想要其他功能请在PEFile类中找,没有请留言
2.因为是边复习功能边写的,所以不要纠结程序架构、编码风格、鲁棒性等各种问题,我会再改的
3.翻译可能是不准的,仅供参考
4.所有计数从0开始,程序不对是否越界进行检查
5.转载请注明出处,本人不对引用此源码后程序产生的任何问题负责
单独的PEFile类
class PEFile
{
//转载请注明出处,本人不对引用此源码后程序产生的任何问题负责
public:
BYTE* p_buffer;///内容储存区
size_t size;///文件大小
DWORD headerOffset;///NT文件头地址
size_t GetFileSize(const char*filename)
{
HANDLE handle = CreateFile(filename, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (handle != INVALID_HANDLE_VALUE)
{
size_t size = ::GetFileSize(handle, NULL);
CloseHandle(handle);
return size;
}
return -1;
}
public:
BYTE GetBYTE(DWORD address)
{
return *((BYTE*)(p_buffer+address));
}
WORD GetWORD(DWORD address)
{
return *((WORD*)(p_buffer+address));
}
DWORD GetDWORD(DWORD address)
{
return *((DWORD*)(p_buffer+address));
}
PEFile()
{
p_buffer=nullptr;
size=0;
headerOffset=-1;
}
PEFile(const char*filename)
{
FILE* file=fopen(filename,"rb");
if(!file)
{
printf("读取失败");
exit(-1);
}
size=GetFileSize(filename);
p_buffer=new BYTE[size+1];
fread((void*)p_buffer,size+1,1,file);
fclose(file);
headerOffset=GetDWORD(0x3c);
}
PEFile(const PEFile& t)
{
p_buffer=new BYTE[t.size+1];
headerOffset=t.headerOffset;
memcpy(p_buffer,t.p_buffer,size+1);
}
PEFile& operator = (const PEFile& t)
{
if(p_buffer)
delete[] p_buffer;
p_buffer=new BYTE[t.size+1];
headerOffset=t.headerOffset;
memcpy(p_buffer,t.p_buffer,size+1);
}
bool LoadPEFile(const char* filename)
{
if(p_buffer)
delete[] p_buffer;
FILE* file=fopen(filename,"rb");
if(!file)return 0;
size=GetFileSize(filename);
p_buffer=new BYTE[size+1];
fread((void*)p_buffer,size+1,1,file);
fclose(file);
headerOffset=GetDWORD(0x3c);
return 1;
}
~PEFile()
{
delete[] p_buffer;
}
///导入表地址
IMAGE_DATA_DIRECTORY ImportDirectory()
{
return *(IMAGE_DATA_DIRECTORY*)(p_buffer+0x80+headerOffset);
}
///导出表地址
IMAGE_DATA_DIRECTORY ExportDirectory()
{
return *(IMAGE_DATA_DIRECTORY*)(p_buffer+0x78+headerOffset);
}
///获取第i个数据目录
IMAGE_DATA_DIRECTORY GetDataDirectory(WORD i)
{
return *(IMAGE_DATA_DIRECTORY*)(p_buffer+0x78+headerOffset+sizeof(IMAGE_DATA_DIRECTORY)*i);
}
///节区数量
WORD NumberOfSections()
{
return GetWORD(0x06+headerOffset);
}
///获取第i个节区头(从0开始计数)
IMAGE_SECTION_HEADER GetGetSectionHeader(WORD i)
{
return *(IMAGE_SECTION_HEADER*)(p_buffer+i*sizeof(IMAGE_SECTION_HEADER)+sizeof(IMAGE_NT_HEADERS32)+headerOffset);
}
///RVA转换为RAW
DWORD RVAtoRAW(DWORD RVA)
{
WORD sz=NumberOfSections();
DWORD ret=RVA;
for(WORD i=0;i<sz;i++)
{
IMAGE_SECTION_HEADER cur=GetGetSectionHeader(i);
if(cur.VirtualAddress<=RVA)
{
DWORD t=RVA-cur.VirtualAddress+cur.PointerToRawData;
if(t<ret)
ret=t;
}
}
return ret;
}
///获取导入描述表的数量
size_t GetImportDescriptorNums()
{
return ImportDirectory().Size/sizeof(IMAGE_IMPORT_DESCRIPTOR);
}
///获取第i张导入描述表
IMAGE_IMPORT_DESCRIPTOR GetImportDescriptor(int i)
{
return *(IMAGE_IMPORT_DESCRIPTOR*)(p_buffer+RVAtoRAW(ImportDirectory().VirtualAddress+i*sizeof(IMAGE_IMPORT_DESCRIPTOR)));
}
///获取第i张导入描述表的INT长度
size_t GetINTLength(WORD i)
{
IMAGE_IMPORT_DESCRIPTOR cur=GetImportDescriptor(i);
DWORD pINT=RVAtoRAW(cur.OriginalFirstThunk);
size_t ret=0;
while(GetDWORD(pINT+ret*sizeof(DWORD)))
++ret;
return ret;
}
///获取第i张导入描述表的第j个函数的函数名
BYTE* GetImprotFunctionName(int i,int j)
{
IMAGE_IMPORT_DESCRIPTOR cur=GetImportDescriptor(i);
DWORD pINT=RVAtoRAW(cur.OriginalFirstThunk)+j*sizeof(DWORD);
DWORD p_func=RVAtoRAW(GetWORD(pINT));
return p_buffer+p_func+sizeof(WORD);
}
///获取第i张导入描述表的IAT长度
size_t GetIATLength(WORD i)
{
IMAGE_IMPORT_DESCRIPTOR cur=GetImportDescriptor(i);
DWORD pINT=RVAtoRAW(cur.FirstThunk);
size_t ret=0;
while(GetDWORD(pINT+ret*sizeof(DWORD)))
++ret;
return ret;
}
///获取第i张导入描述表的第j个函数的地址
DWORD GetImprotFunctionAddress(int i,int j)
{
IMAGE_IMPORT_DESCRIPTOR cur=GetImportDescriptor(i);
DWORD pIAT=RVAtoRAW(cur.FirstThunk)+j*sizeof(DWORD);
return GetDWORD(pIAT);
}
///获取导出表
IMAGE_EXPORT_DIRECTORY GetExportDirectory()
{
if(ExportDirectory().VirtualAddress!=NULL)
return *(IMAGE_EXPORT_DIRECTORY*)(p_buffer+RVAtoRAW(ExportDirectory().VirtualAddress));
else
{
IMAGE_EXPORT_DIRECTORY ret;
memset(&ret,0,sizeof(ret));
return ret;
}
}
///导出函数的个数
size_t GetExprotFunctionNums()
{
IMAGE_EXPORT_DIRECTORY cur=GetExportDirectory();
return cur.NumberOfFunctions;
}
///导出函数的具名函数个数
size_t GetExprotFunctionNameNums()
{
return GetExportDirectory().NumberOfNames;
}
///给出第i个导出函数的信息
char* GetExportMsg(WORD i,DWORD& address,DWORD& ordinal)
{
IMAGE_EXPORT_DIRECTORY cur=GetExportDirectory();
if(cur.AddressOfFunctions!=0)
address=GetDWORD(RVAtoRAW(cur.AddressOfFunctions)+i*sizeof(DWORD));
else
address=0;
if(cur.AddressOfNameOrdinals!=0)
ordinal=GetWORD(RVAtoRAW(cur.AddressOfNameOrdinals)+i*sizeof(WORD));
else
ordinal=0;
if(cur.Name!=0)
{
DWORD p_name=GetDWORD(RVAtoRAW(cur.AddressOfNames)+i*sizeof(DWORD));
return (char*)(p_buffer+RVAtoRAW(p_name));
}
else
return nullptr;
}
///获取DOS头
IMAGE_DOS_HEADER GetDosHeader()
{
return *(IMAGE_DOS_HEADER*)p_buffer;
}
///获取NT文件头
IMAGE_FILE_HEADER GetNTFileHeader()
{
return *(IMAGE_FILE_HEADER*)(p_buffer+headerOffset+sizeof(DWORD));
}
IMAGE_OPTIONAL_HEADER32 GetNTOptionalHeader()
{
return *(IMAGE_OPTIONAL_HEADER32*)(p_buffer+headerOffset+0x18);
}
};
完整代码
#include <cstdio>
#include <windows.h>