最近重新撸了一遍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>
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);
}
};
PEFile pe;
FILE* outfile;
///对应-q
void ExitProgram()
{
if(outfile)
fclose(outfile);
exit(0);
}
///对应-l
void LoadPEFile(const char*filename)
{
if(!pe.LoadPEFile(filename))
printf("文件不存在或无法读取\n");
else
printf("读取成功\n");
}
///对应-f filename
void PrintInFile(const char*filename)
{
outfile=fopen(filename,"w");
}
void PrintMsg(char*str)
{
if(outfile)
fprintf(outfile,"%s",str);
printf("%s",str);
}
///对应于-m dos [main]
void MsgOfDos(bool isMain)
{
IMAGE_DOS_HEADER dosHeader=pe.GetDosHeader();
char str[10000];
strcpy(str,"\n----------------------------DOS头信息--------------------------------\n\n");
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","DOS文件标记(Magic DOS signature)",dosHeader.e_magic);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","重定位表的文件地址(File Address of relocation table)",dosHeader.e_lfarlc);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","NT头地址(Offset to start of PE header)",dosHeader.e_lfanew);
PrintMsg(str);
if(!isMain)
{
sprintf(str,"%-55s:0x%04x\n","最后一页大小(Bytes on last page of file)",dosHeader.e_cblp);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x (%d)\n","文件页数(Pages in file)",dosHeader.e_cp,dosHeader.e_cp);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","文件迁移(Relocations)",dosHeader.e_crlc);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","头的段大小(Size of header in paragraphs)",dosHeader.e_cparhdr);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","最小额外段需求(Minimun extra paragraphs needs)",dosHeader.e_minalloc);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","最大额外段需求(Maximun extra paragraphs needs)",dosHeader.e_maxalloc);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","DOS代码的初始化堆栈SS(intial(relative)SS value)",dosHeader.e_ss);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","DOS代码的初始化堆栈指针SP(intial SP value)",dosHeader.e_sp);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","校验和(Checksum)",dosHeader.e_csum);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","DOS代码的初始化指令入口[指针IP](intial IP value)",dosHeader.e_ip);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","DOS代码的初始堆栈入口(intial(relative)CS value)",dosHeader.e_cs);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","Overlay number",dosHeader.e_ovno);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","OEM identifier(for e_oeminfo)",dosHeader.e_oemid);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","OEM information;e_oemid specific",dosHeader.e_oeminfo);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x 0x%04x 0x%04x 0x%04x\n","保留字(Reserved words,[e_res])",
dosHeader.e_res[0],
dosHeader.e_res[1],
dosHeader.e_res[2],
dosHeader.e_res[3]);
PrintMsg(str);
sprintf(str,"%-55s:\n0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x\n","保留字2(Reserved words,[e_res2])",
dosHeader.e_res2[0],
dosHeader.e_res2[1],
dosHeader.e_res2[2],
dosHeader.e_res2[3],
dosHeader.e_res2[4],
dosHeader.e_res2[5],
dosHeader.e_res2[6],
dosHeader.e_res2[7],
dosHeader.e_res2[8],
dosHeader.e_res2[9]);
PrintMsg(str);
}
strcpy(str,"\n--------------------------DOS头信息-结束-------------------------------\n\n");
PrintMsg(str);
}
///对应于-m ntfh [main]
void MsgOfNtfh(bool isMain)
{
IMAGE_FILE_HEADER ntfh=pe.GetNTFileHeader();
char str[10000];
strcpy(str,"\n----------------------------NT文件头信息--------------------------------\n\n");
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","CPU机器码(Machine)",ntfh.Machine);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x(%d)\n","节区数量(NumberOfSections)",ntfh.NumberOfSections,ntfh.NumberOfSections);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","属性(Characteristics)",ntfh.Characteristics);
PrintMsg(str);
if(!isMain)
{
sprintf(str,"%-55s:0x%08x\n","时间戳(TimeDateStamp)",ntfh.TimeDateStamp);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","符号表指针(PointerToSymbolTable)",ntfh.PointerToSymbolTable);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","符号表大小(NumberOfSymbols)",ntfh.NumberOfSymbols);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","可选头大小(SizeOfOptionalHeader)",ntfh.SizeOfOptionalHeader);
PrintMsg(str);
}
strcpy(str,"\n--------------------------DNT文件头信息-结束-------------------------------\n\n");
PrintMsg(str);
}
///对应于-m ntoh [main] [d]
void MsgOfNtoh(bool isMain,bool isD)
{
IMAGE_OPTIONAL_HEADER32 ntoh=pe.GetNTOptionalHeader();
char str[10000];
strcpy(str,"\n----------------------------NT可选头信息--------------------------------\n\n");
PrintMsg(str);
sprintf(str,"%-55s:0x%04x(%d位)\n","可选头类型(Magic)",ntoh.Magic,ntoh.Magic==0x10b?32:64);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","EP地址[RVA](AddressOfEntryPoint)",ntoh.AddressOfEntryPoint);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","映象基址(ImageBase)",ntoh.ImageBase);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","节对齐(SectionAlignment)",ntoh.SectionAlignment);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","文件节对齐(FileAlignment)",ntoh.FileAlignment);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","映象大小(SizeOfImage)",ntoh.SizeOfImage);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","PE头大小(SizeOfHeaders)",ntoh.SizeOfHeaders);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x(%s)\n","子系统(Subsystem)",ntoh.Subsystem,ntoh.Subsystem==1?"系统驱动":
ntoh.Subsystem==2?"窗口应用程序":"控制台应用程序");
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","数据目录项数(NumberOfRvaAndSizes)",ntoh.NumberOfRvaAndSizes);
PrintMsg(str);
if(!isMain)
{
sprintf(str,"%-55s:0x%02x\n","连接器版本号(MajorLinkerVersion)",ntoh.MajorLinkerVersion);
PrintMsg(str);
sprintf(str,"%-55s:0x%02x\n","连接器版本号(MinorLinkerVersion)",ntoh.MinorLinkerVersion);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","代码段长度(SizeOfCode)",ntoh.SizeOfCode);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","初始化数据长度(SizeOfInitializedData)",ntoh.SizeOfInitializedData);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","未初始化的数据长度(SizeOfUninitializedData)",ntoh.SizeOfUninitializedData);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","代码段起始地址的RVA(BaseOfCode)",ntoh.BaseOfCode);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","数据段起始地址的RVA(BaseOfData)",ntoh.BaseOfData);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","操作系统版本号(MajorOperatingSystemVersion)",ntoh.MajorOperatingSystemVersion);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","操作系统版本号(MinorOperatingSystemVersion)",ntoh.MinorOperatingSystemVersion);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","映象的版本号(MajorImageVersion)",ntoh.MajorImageVersion);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","映象的版本号(MinorImageVersion)",ntoh.MinorImageVersion);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","所需子系统版本号(MajorSubsystemVersion)",ntoh.MajorSubsystemVersion);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","所需子系统版本号(MinorSubsystemVersion)",ntoh.MinorSubsystemVersion);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","WIN32版本值(Win32VersionValue)",ntoh.Win32VersionValue);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","映象文件校验和(CheckSum)",ntoh.CheckSum);
PrintMsg(str);
sprintf(str,"%-55s:0x%04x\n","DLL的文件属性(DllCharacteristics)",ntoh.DllCharacteristics);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","栈保留内存(SizeOfStackReserve)",ntoh.SizeOfStackReserve);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","栈初始占用内存(SizeOfStackCommit)",ntoh.SizeOfStackCommit);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","堆保留内存(SizeOfHeapReserve)",ntoh.SizeOfHeapReserve);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","堆初始占用内存(SizeOfHeapReserve)",ntoh.SizeOfHeapCommit);
PrintMsg(str);
sprintf(str,"%-55s:0x%08x\n","LoaderFlags",ntoh.LoaderFlags);
PrintMsg(str);
}
if(isD)
{
strcpy(str,"\n---------------------数据目录---------------------\n\n");
PrintMsg(str);
char* DataDirectory[50]=
{"Export Directory"
,"Import Directory"
,"Resource Directory"
,"Exception Directory"
,"Security Directory"
,"Base Relocation Table"
,"Debug Directory"
,"COPYRIGHT/Architecture Specific Data"
,"RVA of GLOBALPTR"
,"TLS Directory"
,"Load Configuration Directory"
,"Bound Import Directory in headers"
,"Import Address Table"
,"Delay Load Import Descriptors"
,"COM Runtime descriptor"
,"Reserved Directory"
};
sprintf(str,"%-50s%-8s%7s%-8s\n","名称","地址","","大小");
PrintMsg(str);
for(DWORD i=0;i<ntoh.NumberOfRvaAndSizes;i++)
{
IMAGE_DATA_DIRECTORY cur=pe.GetDataDirectory(i);
sprintf(str,"%-50s0x%08x%5s0x%08x\n",DataDirectory[i],cur.VirtualAddress,"",cur.Size);
PrintMsg(str);
}
strcpy(str,"\n-------------------数据目录-结束------------------\n\n");
PrintMsg(str);
}
strcpy(str,"\n-------------------------NT可选头信息-结束------------------------------\n\n");
PrintMsg(str);
}
///对应-i [i][j]
void MsgOfImport(int i,int j,bool isSingle=1)
{
char str[10000];
if(isSingle)
{
sprintf(str,"%s.%s( address/ordinal= 0x%08x)\n",
pe.RVAtoRAW(pe.GetImportDescriptor(i).Name)+pe.p_buffer,
pe.GetImprotFunctionName(i,j),
pe.GetImprotFunctionAddress(i,j)
);
}
else
{
sprintf(str,"%s.%s",
pe.RVAtoRAW(pe.GetImportDescriptor(i).Name)+pe.p_buffer,
pe.GetImprotFunctionName(i,j)
);
for(int i=0;str[i];i++)
if(str[i]<0)
{
strcpy(str,"未知的函数名,请通过序号/地址识别函数");
break;
}
sprintf(str,"%-50s0x%08x\n",
str,
pe.GetImprotFunctionAddress(i,j)
);
}
PrintMsg(str);
}
void MsgOfImport(int i)
{
char str[10000];
IMAGE_IMPORT_DESCRIPTOR cur=pe.GetImportDescriptor(i);
sprintf(str,"库名:%-50s\n", pe.RVAtoRAW(cur.Name)+pe.p_buffer);
PrintMsg(str);
size_t l_int=pe.GetINTLength(i),l_iat=pe.GetIATLength(i);
sprintf(str,"INT长度:0x%08x(%d),IAT长度:0x%08x(%d)\n\n",l_int,l_int,l_iat,l_iat);
PrintMsg(str);
sprintf(str,"%-50s%-08s\n","函数名","地址/编号");
PrintMsg(str);
for(int j=0;j<l_int;j++)
MsgOfImport(i,j,0);
}
void MsgOfImport()
{
int sz=pe.GetImportDescriptorNums();
for(int i=0;i<sz;i++)
{
MsgOfImport(i);
PrintMsg("\n\n");
}
}
///对应-e [i]
void MsgOfExport(int i,bool isSingle=1)
{
char str[10000];
DWORD address,ordinal;
char* name=pe.GetExportMsg(i,address,ordinal);
if(isSingle)
{
sprintf(str,"%s( address = 0x%08x , ordinal = 0x%08x (%d) )\n",name?name:"无法识别的函数名/函数不存在",address,ordinal,ordinal);
PrintMsg(str);
}
else
{
sprintf(str,"%-50s0x%08x%10s0x%08x (%d)\n",name?name:"无法识别的函数名/函数不存在",address,"",ordinal,ordinal);
PrintMsg(str);
}
}
void MsgOfExport()
{
size_t sz=pe.GetExprotFunctionNums();
if(sz==0)
PrintMsg("该PE文件不存在EAT!\n");
else
{
for(int i=0;i<sz;i++)
MsgOfExport(i,0);
}
}
///对应-s [i]
void MsgOfSection(int i)
{
IMAGE_SECTION_HEADER cur=pe.GetGetSectionHeader(i);
char str[10000];
PrintMsg("\n\n");
sprintf(str,"%-50s: %s\n","节区名(Name)",cur.Name);
PrintMsg(str);
sprintf(str,"%-50s: 0x%08x\n","节区大小(VirtualSize)/物理地址(PhysicalAddress)",cur.Misc.VirtualSize);
PrintMsg(str);
sprintf(str,"%-50s: 0x%08x\n","节区RVA(VirtualAddress)",cur.VirtualAddress);
PrintMsg(str);
sprintf(str,"%-50s: 0x%08x\n","文件对齐尺寸(SizeOfRawData)",cur.SizeOfRawData);
PrintMsg(str);
sprintf(str,"%-50s: 0x%08x\n","文件偏移(PointerToRawData)",cur.PointerToRawData);
PrintMsg(str);
sprintf(str,"%-50s: 0x%08x\n","重定位偏移(PointerToRelocations)",cur.PointerToRelocations);
PrintMsg(str);
sprintf(str,"%-50s: 0x%08x\n","行号表偏移(PointerToLinenumbers)",cur.PointerToLinenumbers);
PrintMsg(str);
sprintf(str,"%-50s: 0x%04x\n","重定位数目(NumberOfRelocations)",cur.NumberOfRelocations);
PrintMsg(str);
sprintf(str,"%-50s: 0x%04x\n","行号表数目(NumberOfLinenumbers)",cur.NumberOfLinenumbers);
PrintMsg(str);
sprintf(str,"%-50s: 0x%08x\n","属性(Characteristics)",cur.Characteristics);
PrintMsg(str);
PrintMsg("\n\n");
}
void MsgOfSection()
{
int sz=pe.NumberOfSections();
printf("节区数量:%d\n\n",sz);
for(int i=0;i<sz;i++)
MsgOfSection(i);
}
///对应-h/-?
void PrintHelp()
{
puts("---------------------------------------------------------------------");
puts("-h/-? 查看帮助");
puts("-q 退出程序");
puts("-l filenname 打开名为filename的PE文件");
puts("-f filename 从当前操作起把输出写在文件中(原文件(如果存在)内容会被覆盖)");
puts("-m dos/ntfh/ntoh [main] [d] 显示DOS头/NT文件头/NT可选头信息,main参数:只显示主要信息.d:显示NT可选头的地址数据目录");
puts("-i [i][j] 第i个导入库的第j个导入函数信息,不填写则显示全部");
puts("-e [i] 第i个导出函数信息,不填写则显示全部");
puts("-s [i] 显示第i个节区信息,不填写则显示全部");
puts("-cls 清屏");
puts("---------------------------------------------------------------------");
}
#include <string>
#include <queue>
using namespace std;
struct OpQueue:public queue<string>
{
string front()
{
if(empty())
return string("");
return queue<string>::front();
}
};
void RunOpList(OpQueue& opList)
{
opList.push(string(""));
while(!opList.empty())
{
string cur=opList.front();
opList.pop();
if(cur=="-l")
{
cur=opList.front();
opList.pop();
LoadPEFile(cur.c_str());
}
if(cur=="-cls")
{
system("cls");
}
else if(cur=="-q")
{
ExitProgram();
}
else if(cur=="-h"||cur=="-?")
{
PrintHelp();
}
else if(cur=="-f")
{
cur=opList.front();
opList.pop();
PrintInFile(cur.c_str());
}
else if(cur=="-m")
{
cur=opList.front();
opList.pop();
if(cur=="dos")
{
cur=opList.front();
if(cur=="main")
{
opList.pop();
MsgOfDos(1);
}
else
MsgOfDos(0);
}
else if(cur=="ntfh")
{
cur=opList.front();
if(cur=="main")
{
opList.pop();
MsgOfNtfh(1);
}
else
MsgOfNtfh(0);
}
else if(cur=="ntoh")
{
cur=opList.front();
bool isMain=0,isD=0;
if(cur=="main")
{
opList.pop();
isMain=1;
}
cur=opList.front();
if(cur=="d")
{
opList.pop();
isD=1;
}
MsgOfNtoh(isMain,isD);
}
else
{
puts("命令错误");
return;
}
}
else if(cur=="-i")
{
cur=opList.front();
int i=-1,j=-1;
if(cur[0]!=‘-‘&&cur!="")
{
opList.pop();
sscanf(cur.c_str(),"%d",&i);
}
cur=opList.front();
if(cur[0]!=‘-‘&&cur!="")
{
opList.pop();
sscanf(cur.c_str(),"%d",&j);
}
if(i!=-1&&j!=-1)
MsgOfImport(i,j);
else if(i!=-1&&j==-1)
MsgOfImport(i);
else
MsgOfImport();
}
else if(cur=="-e")
{
cur=opList.front();
int i=-1;
if(cur[0]!=‘-‘&&cur[0])
{
opList.pop();
sscanf(cur.c_str(),"%d",&i);
}
if(i==-1)
MsgOfExport();
else
MsgOfExport(i);
}
else if(cur=="-s")
{
cur=opList.front();
int i=-1;
if(cur[0]!=‘-‘&&cur[0])
{
opList.pop();
sscanf(cur.c_str(),"%d",&i);
}
if(i==-1)
MsgOfSection();
else
MsgOfSection(i);
}
}
}
void GetOpList(OpQueue& opList)
{
opList=OpQueue();
char str[10000];
char *p=str;
gets(str);
for(int i=0;p[i];i++)
{
if(p[i]==‘\t‘||p[i]==‘\n‘||p[i]==‘\r‘||p[i]==‘ ‘)
{
p[i]=0;
if(*p)
{
opList.push(string(p));
p+=i+1;
}
i=0;
}
}
if(*p)
{
opList.push(string(p));
}
}
int main(int argc,char** argv)
{
puts(" ");
puts("----------------------PE解析器V1.0 by lc思念落叶----------------------");
puts(" ");
puts(" ");
if(argc==1)
{
while(!pe.p_buffer)
{
OpQueue opList;
printf("请使用-l filename指令读取PE文件\n");
GetOpList(opList);
RunOpList(opList);
}
PrintHelp();
}
else if(argc>1)
{
OpQueue opList;
int loc=1;
if(argv[1][0]!=‘-‘)
LoadPEFile(argv[loc++]);
for(int i=loc;i<argc;i++)
opList.push(string(argv[i]));
RunOpList(opList);
}
while(1)
{
OpQueue opList;
GetOpList(opList);
puts("---------------------------------------------------------------------");
RunOpList(opList);
}
}
时间: 2024-10-18 23:37:03