/*
* 近日学习pe文件格式,写了一个简单的分析程序
* 个人网站:http://ggg82.126.com
* 电子邮件:ggg82@163.com
* QQ:358416653
*
* 本程序在win2000+vc6平台编译通过
* 学习参考:看学论坛
*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
void help()
{
printf("Usage:Pedir <exefile>\n");
printf("Press any key to exit this program.\n");
getch();
}
//IMAGE_DOS_SIGNATURE
int main(int argc,char *argv[])
{
IMAGE_DOS_HEADER *pDosHead;
IMAGE_NT_HEADERS *pPeHead;
IMAGE_SECTION_HEADER *pSectionHead;
HANDLE hFile,hMapping;
char *pBasePoint;
// char buffer[MAX_PATH];
int i;
if(argc<2)
{
help();
exit(1);
}
hFile=CreateFile(argv[1],GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,0); //Create the File handle
if (hFile==INVALID_HANDLE_VALUE)
{ //test File Handle
GetLastError();
return 0;
}
if (!(hMapping=CreateFileMapping(hFile,0,PAGE_READONLY|SEC_COMMIT,0,0,0)))
{ //Create the File Map and test
CloseHandle(hFile);
return 0;
}
if (!(pBasePoint=MapViewOfFile(hMapping,FILE_MAP_READ,0,0,0)))
{
CloseHandle(hFile);
CloseHandle(hMapping);
return 0;
} // GetShortPathName(argv[1],buffer,sizeof buffer);
//判断是否是pe文件
pDosHead=(IMAGE_DOS_HEADER *)pBasePoint;
if(IMAGE_DOS_SIGNATURE!=pDosHead->e_magic)
{
printf("DOS文件头出错!\n");
exit(1);
}
//通过Dos头找到pe头
pPeHead=(IMAGE_NT_HEADERS *)(pBasePoint+pDosHead->e_lfanew);
//判断pe头
if(IMAGE_NT_SIGNATURE!=pPeHead->Signature)
{
printf("PE文件头错误!\n");
exit(1);
}
//列出pe filehead的信息
printf("运行平台:\t");
if(IMAGE_FILE_MACHINE_I386==pPeHead->FileHeader.Machine)
printf("%s\n","X86CPU");
else
printf("未知(%X)\n",pPeHead->FileHeader.Machine);
printf("节数目:\t%d\n",pPeHead->FileHeader.NumberOfSections);
printf("创建时间:\t%X\n",pPeHead->FileHeader.TimeDateStamp);
printf("PointerToSymbolTable:\t%X\n",pPeHead->FileHeader.PointerToSymbolTable);
printf("NumberOfSymbols:\t%X\n",pPeHead->FileHeader.NumberOfSymbols);
printf("SizeOfOptionalHeader:\t%X\n",pPeHead->FileHeader.SizeOfOptionalHeader);
printf("Characteristics:\t%X\n",pPeHead->FileHeader.Characteristics);
//列出Optional Header信息
printf("进入点:\t%x\n",pPeHead->OptionalHeader.AddressOfEntryPoint);
printf("载入地址:\t%x\n",pPeHead->OptionalHeader.ImageBase);
printf("内存对齐:\t%x\n",pPeHead->OptionalHeader.SectionAlignment);
printf("文件对齐:\t%x\n",pPeHead->OptionalHeader.FileAlignment);
printf("MajorSubsystemVersion:\t%x\n",pPeHead->OptionalHeader.MajorSubsystemVersion);
printf("MinorSubsystemVersion:\t%x\n",pPeHead->OptionalHeader.MinorSubsystemVersion);
printf("映像大小:\t%x\n",pPeHead->OptionalHeader.SizeOfImage);
printf("头大小:\t%x\n",pPeHead->OptionalHeader.SizeOfHeaders);
printf("界面:\t%x\n",pPeHead->OptionalHeader.Subsystem);
//DataDirectory
//Section Table
//fseet应该不用定位了吧
for(i=0;i<pPeHead->FileHeader.NumberOfSections;i++)
{
int j;
pSectionHead=(IMAGE_SECTION_HEADER *)((char *)pPeHead+sizeof *pPeHead+i*sizeof *pSectionHead);
printf("\n节名称:\t");
for(j=0;j<sizeof pSectionHead->Name;j++)
{
if(0==pSectionHead->Name[j])
break;
putchar(pSectionHead->Name[j]);
}
printf("\n本节的RVA:\t%X\n",pSectionHead->VirtualAddress);
printf("映射尺寸:\t%X\n",pSectionHead->SizeOfRawData);
printf("文件数据偏移:\t%X\n",pSectionHead->PointerToRawData);
printf("节属性:\t%X\n",pSectionHead->Characteristics);
}
#define addr(rva) (void *)((char *)((char *)pBasePoint+pSectionHead->PointerToRawData)+((DWORD)(rva)-pSectionHead->VirtualAddress))
//导入表//遍历节表查找导入表的位置
for(i=0;i<pPeHead->FileHeader.NumberOfSections;i++)
{
IMAGE_DATA_DIRECTORY *pData=&pPeHead->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
pSectionHead=(IMAGE_SECTION_HEADER *)((char *)pPeHead+sizeof *pPeHead+i*sizeof *pSectionHead);
//查看导入表是否在该节内
if(pData->VirtualAddress>=pSectionHead->VirtualAddress
&&pData->VirtualAddress+pData->Size<=pSectionHead->VirtualAddress+pSectionHead->SizeOfRawData)
{
//定位地址
IMAGE_IMPORT_DESCRIPTOR *pImport=addr(pData->VirtualAddress);
while(pImport->Name)
{
IMAGE_THUNK_DATA *imThunk_data=addr(pImport->Characteristics);
//输出模块名称
printf("\n导入模块:%s\n\n",(char *)addr(pImport->Name));
//输出引入函数表
while(imThunk_data->u1 .Ordinal)
{
if(IMAGE_SNAP_BY_ORDINAL(imThunk_data->u1.Ordinal))
{
printf("\t导入ID:\t%d\n",IMAGE_ORDINAL(imThunk_data->u1 .Ordinal ));
}
else
{
IMAGE_IMPORT_BY_NAME *imImport_Name=(IMAGE_IMPORT_BY_NAME *) addr(imThunk_data->u1.AddressOfData);
printf("\t导入函数:\t%s\n",(char *)imImport_Name->Name);
}
imThunk_data++;
}//*/
pImport++;
}
break;
}
}
//导出表//和导入标实现方法类似
CloseHandle(hFile);
CloseHandle(hMapping);
return 0;
}?