- #pragma comment( lib, "Imagehlp.lib" )
- #include<windows.h>
- #include<Imagehlp.h>
- #include<memory.h>
- #include<iostream>
- using namespace std;
- class AnalysisPE
- {
- //一些辅助宏的定义;
- #define NUMOFSECTION pNTHeader->FileHeader.NumberOfSections
- public:
- AnalysisPE(){}
- AnalysisPE(PTCHAR iname){
- setPEName(iname);
- }
- ~AnalysisPE(){
- _UnLoadFile();
- }
- VOID setPEName(PTCHAR iname){
- name = iname;
- hFile=NULL;
- hFileMapping=NULL;
- hMapView=NULL;
- if(!_LoadFile()){
- cout << "加载文件失败!/n";
- return;
- }
- _walkThroughPE();
- }
- BOOL isPEFile(){ return isPE; }
- VOID printSectionHeaders();
- VOID printNTHeaderInfo();
- VOID printImageFileHeaderInfo();
- VOID printImageOptionalHeaderInfo();
- VOID printImportInfo();
- private:
- BOOL _LoadFile(); //把要分析的文件加载到内存;
- VOID _UnLoadFile();
- VOID _walkThroughPE(); //粗略地遍历PE文件;
- DWORD _getRawAddress(DWORD pVirtualAddress, DWORD pPEHeader);
- private:
- PTCHAR name;
- HANDLE hFile;
- HANDLE hFileMapping;
- HANDLE hMapView;
- BOOL isPE;
- PIMAGE_DOS_HEADER pDOSHeader;
- PIMAGE_NT_HEADERS pNTHeader;
- PIMAGE_SECTION_HEADER pSectionHeader;
- };
- VOID AnalysisPE::printImportInfo()
- {
- cout << "========================================================/n【Import information!】/n";
- PIMAGE_OPTIONAL_HEADER pOpn_header = &pNTHeader->OptionalHeader;
- DWORD pFileHeader = (DWORD)&pNTHeader->FileHeader;
- DWORD pAddress = pOpn_header->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
- DWORD rawAddress = _getRawAddress(pAddress, (DWORD)pFileHeader);
- PIMAGE_IMPORT_DESCRIPTOR pImportDec = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pDOSHeader + rawAddress);
- while(1)
- {
- IMAGE_IMPORT_DESCRIPTOR cmp;
- memset(&cmp, 0, sizeof(IMAGE_IMPORT_DESCRIPTOR));
- if( 0 == memcmp(&cmp, pImportDec, sizeof(IMAGE_IMPORT_DESCRIPTOR)))
- break;
- DWORD* desp = (DWORD*)((DWORD)pDOSHeader + _getRawAddress(pImportDec->OriginalFirstThunk, (DWORD)pFileHeader));
- DWORD* addr = (DWORD*)((DWORD)pDOSHeader + _getRawAddress(pImportDec->FirstThunk, (DWORD)pFileHeader));
- if(*desp || *addr)
- {
- char* dllName = (char*)((DWORD)pDOSHeader + _getRawAddress(pImportDec->Name, (DWORD)pFileHeader));
- cout << "/n==========/n" << dllName << endl;
- while(*desp || *addr)
- {
- if(IMAGE_ORDINAL_FLAG&*desp) //序号导入
- cout << IMAGE_ORDINAL(*desp)<<"/t/t";
- else //名字导入
- {
- PIMAGE_IMPORT_BY_NAME pName = (PIMAGE_IMPORT_BY_NAME)((DWORD)pDOSHeader + _getRawAddress(*desp, (DWORD)pFileHeader));
- cout << pName->Hint << "/t" << (char*)(&pName->Name) << "/t";
- }
- cout << *addr << endl;
- desp = (DWORD*)((DWORD)desp + sizeof(DWORD));
- addr = (DWORD*)((DWORD)addr + sizeof(DWORD));
- }
- }
- pImportDec = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pImportDec + sizeof(IMAGE_IMPORT_DESCRIPTOR));
- }
- }
- //因为文件对齐(FileAlignment)和内存对齐(SectionAlignment)不一样(见以下IMAGE_OPTIONAL_HEADER中的分析),所以这个函数是有必要的!
- DWORD AnalysisPE::_getRawAddress(DWORD pVirtualAddress, DWORD pPEHeader)
- {
- DWORD rt=-1;
- int sectionNum = PIMAGE_FILE_HEADER(pPEHeader)->NumberOfSections;
- DWORD pSectionAddress = pPEHeader + sizeof(IMAGE_FILE_HEADER) + PIMAGE_FILE_HEADER(pPEHeader)->SizeOfOptionalHeader;
- for(int i=0; i<sectionNum; i++)
- {
- PIMAGE_SECTION_HEADER pSection = (PIMAGE_SECTION_HEADER)pSectionAddress;
- DWORD begin = pSection->VirtualAddress;
- DWORD end = pSection->VirtualAddress + pSection->Misc.VirtualSize;
- if(pVirtualAddress<end && pVirtualAddress>=begin)
- {
- rt = pSection->PointerToRawData + pVirtualAddress - begin;
- break;
- }
- pSectionAddress += sizeof(IMAGE_SECTION_HEADER);
- }
- return rt;
- }
- // 相关结构体如下(可以在WinNT.h中找到):
- //
- //typedef struct _IMAGE_OPTIONAL_HEADER {
- // //
- // // Standard fields.
- // //
- //
- // WORD Magic;
- // BYTE MajorLinkerVersion;
- // BYTE MinorLinkerVersion;
- // DWORD SizeOfCode;
- // DWORD SizeOfInitializedData;
- // DWORD SizeOfUninitializedData;
- // DWORD AddressOfEntryPoint;
- // DWORD BaseOfCode;
- // DWORD BaseOfData;
- //
- // //
- // // NT additional fields.
- // //
- //
- // DWORD ImageBase;
- // DWORD SectionAlignment;
- // DWORD FileAlignment;
- // WORD MajorOperatingSystemVersion;
- // WORD MinorOperatingSystemVersion;
- // WORD MajorImageVersion;
- // WORD MinorImageVersion;
- // WORD MajorSubsystemVersion;
- // WORD MinorSubsystemVersion;
- // DWORD Win32VersionValue;
- // DWORD SizeOfImage;
- // DWORD SizeOfHeaders;
- // DWORD CheckSum;
- // WORD Subsystem;
- // WORD DllCharacteristics;
- // DWORD SizeOfStackReserve;
- // DWORD SizeOfStackCommit;
- // DWORD SizeOfHeapReserve;
- // DWORD SizeOfHeapCommit;
- // DWORD LoaderFlags;
- // DWORD NumberOfRvaAndSizes;
- // IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
- //} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
- VOID AnalysisPE::printImageOptionalHeaderInfo()
- {
- if(isPE!=TRUE)
- return;
- cout << "/n----Information provided by IMAGE_OPTIONAL_HEADER as Follows:/n ";
- PIMAGE_OPTIONAL_HEADER pOpn_header = &pNTHeader->OptionalHeader;
- cout << "Standard fields./n";
- cout << "SizeOfInitializedData is : " << pOpn_header->SizeOfInitializedData << endl;
- cout << "SizeOfUninitializedData is : " << pOpn_header->SizeOfUninitializedData << endl;
- cout << "AddressOfEntryPoint is : " << pOpn_header->AddressOfEntryPoint << endl;
- cout << "NT additional fields./n";
- cout << "ImageBase is : " << pOpn_header->ImageBase << endl;
- cout << "SectionAlignment is : " << pOpn_header->SectionAlignment << endl;
- cout << "FileAlignment is : " << pOpn_header->FileAlignment << endl;
- cout << "MajorOperatingSystemVersion is : " << pOpn_header->MajorOperatingSystemVersion << endl;
- cout << "MinorOperatingSystemVersion is : " << pOpn_header->MinorOperatingSystemVersion << endl;
- cout << "SizeOfImage is : " << pOpn_header->SizeOfImage << endl;
- cout << "SizeOfHeaders is : " << pOpn_header->SizeOfHeaders << endl;
- if(IMAGE_SUBSYSTEM_WINDOWS_GUI==pOpn_header->Subsystem)
- cout << "Image runs in the Windows GUI subsystem./n";
- if(IMAGE_SUBSYSTEM_WINDOWS_CUI==pOpn_header->Subsystem)
- cout << "Image runs in the Windows character subsystem./n";
- }
- // 相关结构体如下(可以在WinNT.h中找到):
- //
- //typedef struct _IMAGE_FILE_HEADER {
- // WORD Machine;
- // WORD NumberOfSections;
- // DWORD TimeDateStamp;
- // DWORD PointerToSymbolTable;
- // DWORD NumberOfSymbols;
- // WORD SizeOfOptionalHeader;
- // WORD Characteristics;
- //} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
- //
- VOID AnalysisPE::printImageFileHeaderInfo()
- {
- if(isPE!=TRUE)
- return;
- cout << "/n----Information provided by IMAGE_FILE_HEADER as Follows:/n ";
- cout << "Machine is : " << pNTHeader->FileHeader.Machine << " ";
- if(IMAGE_FILE_MACHINE_I386 == pNTHeader->FileHeader.Machine)
- cout << ", that means Intel 386. /n";
- cout << "NumberOfSections is : " << pNTHeader->FileHeader.NumberOfSections << endl;
- cout << "TimeDateStamp is : " << pNTHeader->FileHeader.TimeDateStamp << endl;
- cout << "Characteristics is : " << pNTHeader->FileHeader.Characteristics << endl;
- //对Characteristics的一个研究
- if(IMAGE_FILE_EXECUTABLE_IMAGE&pNTHeader->FileHeader.Characteristics)
- cout << "File is executable/n";
- if(IMAGE_FILE_DLL&pNTHeader->FileHeader.Characteristics)
- cout << "File is a DLL./n";
- }
- VOID AnalysisPE::printNTHeaderInfo()
- {
- cout << "/n=======================================================/n"
- << "Analysis NT header: /n";
- printImageFileHeaderInfo();
- printImageOptionalHeaderInfo();
- }
- VOID AnalysisPE::printSectionHeaders()
- {
- if(isPE!=TRUE)
- return;
- cout << "/n=======================================================/n"
- << "PE Section headers:/n";
- cout << "There are " << NUMOFSECTION << " sections in this PE!/n";
- cout << "/nname/tsize/taddr/tread/twrite/texcute/n";
- PIMAGE_SECTION_HEADER pSH = pSectionHeader;
- for(int i=0; i<NUMOFSECTION; i++)
- {
- cout <<pSH->Name<< "/t"
- << pSH->SizeOfRawData << "/t"
- << pSH->VirtualAddress << "/t"
- << (pSH->Characteristics&IMAGE_SCN_MEM_READ? "true" : "false") << "/t"
- << (pSH->Characteristics&IMAGE_SCN_MEM_WRITE? "true" : "false") << "/t"
- << (pSH->Characteristics&IMAGE_SCN_MEM_EXECUTE? "true" : "false") << endl;
- pSH = (PIMAGE_SECTION_HEADER)((DWORD)pSH + sizeof(IMAGE_SECTION_HEADER));
- }
- }
- VOID AnalysisPE::_walkThroughPE()
- {
- //文件的装载起始位置就是DOS头;
- pDOSHeader = (PIMAGE_DOS_HEADER)hMapView;
- if(IMAGE_DOS_SIGNATURE != pDOSHeader->e_magic){ //判断DOS的标识是否正确
- cout << "not PE file because of the DOS Magic number is not right!/n";
- isPE = FALSE;
- return;
- }
- //DOS头中的e_lfanew就是NT头的相对虚拟地址RVA;
- pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)hMapView + pDOSHeader->e_lfanew);
- if(IMAGE_NT_SIGNATURE != pNTHeader->Signature){ //判断PE的标识是否正确
- cout << "not PE file because of the NT Signature is not right/n";
- isPE = FALSE;
- return;
- }
- isPE = TRUE; //是的,这是一个PE文件
- //得到节表(Section Table)的地址
- pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pNTHeader + sizeof(IMAGE_NT_HEADERS));
- }
- BOOL AnalysisPE::_LoadFile()
- {
- BOOL Flag = TRUE;
- __try{
- hFile = CreateFile(
- this->name,
- GENERIC_READ|GENERIC_EXECUTE ,
- 0,NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- hFileMapping = CreateFileMapping(
- hFile, NULL, PAGE_EXECUTE_READ,
- 0, 0, TEXT("testdll.dll"));
- hMapView = MapViewOfFile(
- hFileMapping ,
- FILE_MAP_EXECUTE|FILE_MAP_READ,
- 0, 0, 0);
- }
- __finally{
- if(INVALID_HANDLE_VALUE==hFile){
- Flag = FALSE;
- cout << "Error handle: create file fail!/n";
- }
- if(NULL == hFileMapping){
- Flag = FALSE;
- cout << "Error to create file mapping!/n";
- }
- if(NULL == hMapView){
- Flag = FALSE;
- cout << "Error to maping view of file!/n";
- }
- }
- return Flag;
- }
- VOID AnalysisPE::_UnLoadFile()
- {
- if(NULL!=hMapView)
- UnmapViewOfFile(hMapView);
- if(NULL!=hFileMapping)
- CloseHandle(hFileMapping);
- if( INVALID_HANDLE_VALUE!=hFile || NULL!=hFile )
- CloseHandle(hFile);
- }
- void main()
- {
- AnalysisPE test;
- test.setPEName(TEXT("c://aa.exe")); //这里是想要测试的PE文件
- cout << (test.isPEFile()==TRUE ? "yes, it's PE" : "Shit, not a PE at all!") << endl;
- test.printNTHeaderInfo();
- test.printSectionHeaders();
- test.printImportInfo();
- system("pause");
- }
一个PE文件的学习程序[原创]
最新推荐文章于 2019-04-30 22:36:22 发布