首页
社区
课程
招聘
[原创]自己写的PE分析工具(附源代码)
发表于: 2012-5-9 20:47 17125

[原创]自己写的PE分析工具(附源代码)

2012-5-9 20:47
17125

以前刚开始学逆向分析的时候,总是找不到一份比较全的代码解析PE格式,最近闲暇无事,写了一个分析工具,里面的代码我现在贴出来,分享一下,希望对想了解PE格式的童鞋有帮助。如果对大家有帮助,希望大家给点鼓励,哈哈

MyPE.cpp

#include "stdafx.h"
#include "ParsePE.h"

FILE *pFResult;
int _tmain(int argc, _TCHAR* argv[])
{
        fopen_s(&pFResult, "c://result.txt", "w");
        CParsePE parsePE(L"c:\\notepad.exe");
        parsePE.ParseDosHeader();
        parsePE.ParseNtHeader();
        parsePE.ParseImportTable();
        parsePE.ParseDelayImportTable();
        parsePE.ParseBoundImportTable();
        parsePE.ParseDebugTable();
        parsePE.ParseResouceTable();
        fclose(pFResult);
        return 0;
}


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 6
支持
分享
最新回复 (10)
雪    币: 149
活跃值: (150)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
2
ParsePE.cpp

#include "StdAfx.h"
#include "ParsePE.h"
#include <algorithm>
#include <delayimp.h>

typedef ImgDelayDescr IMAGE_DELAY_IMPORT_DESCRIPTOR;
extern FILE *pFResult;

//调试时才打印该信息,必要的时候也可以打印到文件中去
inline void DebugPrint(const char *vmf, ...)
{
#ifdef _DEBUG
        va_list ap;
        va_start(ap, vmf);
        vprintf(vmf, ap);
        vfprintf(pFResult, vmf, ap);
        va_end(ap);
#endif
}

//判断是否是PE文件格式,两个地方:1.DOS块标识e_magic;2.PE文件头标识signature
bool CParsePE::is_pe_file()
{
        WORD dosMagic; //DOS MZ Header的标识符
        DWORD peMagic; //PE文件头的标识符
        long peStaAddr;
        fseek(fp, 0, 0);
        fread_s(&dosMagic, sizeof(dosMagic), sizeof(WORD), 1, fp);
        fseek(fp, 60, 0);
        fread_s(&peStaAddr, sizeof(peStaAddr), sizeof(long), 1, fp);
        fseek(fp, peStaAddr, 0);
        fread_s(&peMagic, sizeof(peMagic), sizeof(DWORD), 1, fp);
        if (IMAGE_DOS_SIGNATURE != dosMagic || IMAGE_NT_SIGNATURE != peMagic)
        {
                return false;
        }
        return true;
}

//解析DOS MZ部首
void CParsePE::ParseDosHeader()
{
        LONG lfanew;
        fseek(fp, 0, 0);
        fread_s(&m_dosHeader, sizeof(m_dosHeader), sizeof(IMAGE_DOS_HEADER), 1, fp);
        fseek(fp, 60, 0);
        fread_s(&lfanew, sizeof(lfanew), sizeof(LONG), 1, fp);
        m_PeInfo.pNtHeader = m_PeInfo.imageBase + lfanew;
        m_PeInfo.dosRVA = m_PeInfo.imageBase;
        m_PeInfo.dosSize = m_PeInfo.pNtHeader - m_PeInfo.imageBase;
        //打印DOS MZ部首信息
        DebugPrint("\n——————————Dos Header Info——————————\n"\
                "dos RVA : 0x%08x\n"\
                "dos size : 0x%08x\n",
                m_PeInfo.dosRVA, m_PeInfo.dosSize);
}

//解析PE文件头
void CParsePE::ParseNtHeader()
{
        fseek(fp, m_PeInfo.pNtHeader, 0);
        fread_s(&m_ntHeader, sizeof(m_ntHeader), sizeof(IMAGE_NT_HEADERS), 1, fp);
        m_fileHeader = m_ntHeader.FileHeader;
        m_opHeader = m_ntHeader.OptionalHeader;
        //映象文件头
        m_PeInfo.bDLL = m_fileHeader.Characteristics & IMAGE_FILE_DLL != 0 ? true : false;
        m_PeInfo.numSections = m_fileHeader.NumberOfSections;
        //可选映象头
        m_PeInfo.sectionAlign = m_opHeader.SectionAlignment;
        m_PeInfo.fileAlign = m_opHeader.FileAlignment;
        m_PeInfo.entryPoint = m_opHeader.AddressOfEntryPoint;
        m_PeInfo.imageBase = m_opHeader.ImageBase;

        int curSecOffset = m_PeInfo.pNtHeader + sizeof(IMAGE_NT_HEADERS);
        IMAGE_SECTION_HEADER sectionHeader;

        DebugPrint("\n——————————sections Info——————————\n");
        for (int i = 0; i < m_PeInfo.numSections; i++)
        {
                fseek(fp, curSecOffset + i * sizeof(IMAGE_SECTION_HEADER), 0);
                fread_s(§ionHeader, sizeof(IMAGE_SECTION_HEADER), sizeof(IMAGE_SECTION_HEADER), 1, fp);
                m_vSectionVirtualAddress.push_back(sectionHeader.VirtualAddress);
                m_vSectionVirtualSize.push_back(sectionHeader.Misc.VirtualSize);//实际的大小

                //如果有空隙,加上空隙
                if (m_vSectionVirtualSize[i]%m_PeInfo.sectionAlign != 0)
                {
                        UINT interspace = m_PeInfo.sectionAlign - m_vSectionVirtualSize[i]%m_PeInfo.sectionAlign;
                        m_vSectionVirtualSize[i] += interspace;
                }
                m_vSectionRawAddress.push_back(sectionHeader.PointerToRawData);
                m_vSectionRawSize.push_back(sectionHeader.SizeOfRawData);

                DebugPrint("section name : %s\n"\
                        "VirtualAddress : 0x%08x\n"\
                        "VirtualSize : 0x%08x\n"\
                        "RawAddress : 0x%08x\n"\
                        "RwaSize : 0x%08x\n",
                        sectionHeader.Name, sectionHeader.VirtualAddress, m_vSectionVirtualSize[i], m_vSectionRawAddress[i], m_vSectionRawSize[i]);
        }
        DebugPrint("\n——————————Header Info——————————\n"\
                "imageBase : 0x%08x\n"\
                "entryPoint : 0x%08x\n"\
                "sectionAlignment : 0x%08x\n"\
                "fileAlignment : 0x%08x\n"\
                "numSections : 0x%08x\n",
                m_PeInfo.imageBase, m_PeInfo.entryPoint, m_PeInfo.sectionAlign, m_PeInfo.fileAlign, m_vSectionRawAddress.size());

        ParseExportTable();

}

//解析各个节
void CParsePE::ParseSections()
{
        IMAGE_SECTION_HEADER sectionHeader;
        for (int i = 0; i < m_PeInfo.numSections; i++)
        {
        }
}

//虚拟地址转换为物理地址
UINT CParsePE::VAToRawAddr( UINT virtualAddr )
{
        assert(virtualAddr);
        if (m_PeInfo.numSections > 0 && virtualAddr < m_vSectionVirtualAddress[0])
        {
                return virtualAddr;
        }

        for (int i = 0; i < m_PeInfo.numSections; i++)
        {
                if (virtualAddr >= m_vSectionVirtualAddress[i] && virtualAddr < m_vSectionVirtualAddress[i] + m_vSectionVirtualSize[i])
                {
                        return virtualAddr - (m_vSectionVirtualAddress[i] - m_vSectionRawAddress[i]);
                }
        }
        return -1;
}
//查找是否在m_vExportFunc中
bool CParsePE::findIsFunc(UINT rva, UINT ordinal)
{
        assert(ordinal >= 0);
        assert(rva >= 0);
        for (int i = 0; i < m_vExportFunc.size(); i++)
        {
                if (m_vExportFunc.at(i).ordinal == ordinal)
                {
                        m_vExportFunc.at(i).rva = rva;
                        return true;
                }
        }
        FUNCEXPINFO funcInfo = {0};
        funcInfo.rva = rva;
        funcInfo.ordinal = ordinal;
        m_vExportFunc.push_back(funcInfo);
        return true;
}

//打印输出表信息
void printExportTable(FUNCEXPINFO funcInfo)
{
        DebugPrint("0x%08x\t0x%08x\t%s\n", funcInfo.rva, funcInfo.ordinal, funcInfo.name.c_str());
}

//打印输入表信息
void printImportTable(FUNCIMPINFO funcImpInfo)
{
        DebugPrint("%s\t0x%08x\t%s\n", funcImpInfo.dllName.c_str(), funcImpInfo.ordinal, funcImpInfo.funcName.c_str());
}

//解析输出表
void CParsePE::ParseExportTable()
{
        IMAGE_DATA_DIRECTORY dataDir;
        dataDir = m_opHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
        if (dataDir.Size != 0)
        {
                UINT exportStartAddr = VAToRawAddr(dataDir.VirtualAddress);
                fseek(fp, exportStartAddr, 0);
                fread_s(&m_exportDir, sizeof(m_exportDir), sizeof(IMAGE_EXPORT_DIRECTORY), 1, fp);
                UINT nameStartAddr = VAToRawAddr(m_exportDir.AddressOfNames);
                for (int i = 0; i < m_exportDir.NumberOfNames; i++)
                {
                        FUNCEXPINFO funcInfo = {0};
                        char FuncName[40] = {0};
                        assert(m_exportDir.AddressOfNames != 0);
                        //ENT
                        UINT nameRVA = m_exportDir.AddressOfNames + i * sizeof(DWORD);
                        UINT nameFileAddr = VAToRawAddr(nameRVA);
                        UINT nameRVA2;
                        UINT nameFileAddr2;
                        fseek(fp, nameFileAddr, 0);
                        fread_s(&nameRVA2, sizeof(nameRVA2), sizeof(UINT), 1, fp);

                        nameFileAddr2 = VAToRawAddr(nameRVA2);
                        fseek(fp, nameFileAddr2, 0);
                        fread_s(&FuncName, sizeof(FuncName), 40, 1, fp);
                        funcInfo.name.assign(FuncName);

                        //ENT对应的序号表
                        UINT ordinalRVA = m_exportDir.AddressOfNameOrdinals + i * sizeof(WORD);
                        UINT ordinalFileAddr = VAToRawAddr(ordinalRVA);
                        short int ordinal;
                        fseek(fp, ordinalFileAddr, 0);
                        fread_s(&ordinal, sizeof(ordinal), sizeof(WORD), 1, fp);
                        funcInfo.ordinal = ordinal;

                        m_vExportFunc.push_back(funcInfo);

                }
                //查找EAT,并找出以序号输出的函数
                for (int i = 0; i < m_exportDir.NumberOfFunctions; i++)
                {
                        UINT funcAddr = m_exportDir.AddressOfFunctions + i*sizeof(DWORD);
                        UINT funcFileAddr = VAToRawAddr(funcAddr);
                        UINT rva;
                        UINT ordinal = m_exportDir.Base + i;//当前输出函数的序号
                        fseek(fp, funcFileAddr, 0);
                        fread_s(&rva, sizeof(rva), sizeof(DWORD), 1, fp);
                        //如果不是名称,那么它一定是以序号输出的
                        findIsFunc(rva, ordinal);
                }
                //打印输出表信息
                DebugPrint("\n\n\n——————————Export Table——————————\n");
                for_each(m_vExportFunc.begin(), m_vExportFunc.end(), printExportTable);
        }
}

//解析输入表
void CParsePE::ParseImportTable()
{
        IMAGE_THUNK_DATA32 thunkData;
        IMAGE_DATA_DIRECTORY dataDir;
        IMAGE_IMPORT_DESCRIPTOR importTable;
        char dllName[56] = {'0'};
        dataDir = m_opHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
        if (dataDir.VirtualAddress)
        {
                UINT curFileAddr = VAToRawAddr(dataDir.VirtualAddress);
                fseek(fp, curFileAddr, 0);
                fread_s(&importTable, sizeof(importTable), sizeof(IMAGE_IMPORT_DESCRIPTOR), 1, fp);
                m_NumImportDll = 0;
                while(importTable.FirstThunk)
                {
                        m_NumImportDll++;
                        //获取导入库的名称
                        UINT dllNameFileAddr = VAToRawAddr(importTable.Name);
                        fseek(fp, dllNameFileAddr, 0);
                        fread_s(&dllName, sizeof(dllName), sizeof(dllName), 1, fp);

                        UINT originalRawAddr = VAToRawAddr(importTable.OriginalFirstThunk);
                        fseek(fp, originalRawAddr, 0);
                        fread_s(&thunkData, sizeof(thunkData), sizeof(IMAGE_THUNK_DATA), 1, fp);

                        unsigned int k = 0;
                        while(thunkData.u1.AddressOfData)
                        {
                                FUNCIMPINFO funcImpInfo;
                                funcImpInfo.dllName.assign(dllName);
                                if (thunkData.u1.Ordinal & 0x80000000) //如果最高位为1,那么函数是以序号导入的
                                {
                                        funcImpInfo.ordinal = thunkData.u1.Ordinal & 0x7fffffff;
                                }
                                else //如果是名字输出,那么该地址是指向IMAGE_IMPORT_BY_NAME的RVA
                                {
                                        IMAGE_IMPORT_BY_NAME importByName;
                                        char funcName[50] = {'0'};
                                        UINT nameFuncAddr = VAToRawAddr(thunkData.u1.AddressOfData);
                                        fseek(fp, nameFuncAddr, 0);
                                        fread_s(&importByName, sizeof(importByName), sizeof(IMAGE_IMPORT_BY_NAME), 1, fp);
                                        funcImpInfo.ordinal = importByName.Hint;
                                        fseek(fp, nameFuncAddr + 2, 0);
                                        fread_s(funcName, sizeof(funcName), sizeof(funcName), 1, fp);
                                        funcImpInfo.funcName.assign(funcName);
                                }
                                m_vImportFunc.push_back(funcImpInfo);

                                fseek(fp, originalRawAddr + (++k) * sizeof(IMAGE_THUNK_DATA), 0);
                                fread_s(&thunkData, sizeof(thunkData), sizeof(IMAGE_THUNK_DATA), 1, fp);
                        }

                        fseek(fp, curFileAddr + m_NumImportDll * sizeof(IMAGE_IMPORT_DESCRIPTOR), 0);
                        fread_s(&importTable, sizeof(importTable), sizeof(IMAGE_IMPORT_DESCRIPTOR), 1, fp);
                }
                //打印输入表信息
                DebugPrint("\n\n\n——————————Import Table——————————\n");
                for_each(m_vImportFunc.begin(), m_vImportFunc.end(), printImportTable);

        }
}

//解析延迟输入表
void CParsePE::ParseDelayImportTable()
{
        IMAGE_THUNK_DATA32 thunkData;
        IMAGE_DATA_DIRECTORY dataDir;
        IMAGE_DELAY_IMPORT_DESCRIPTOR importTable;
        char dllName[56] = {'0'};
        dataDir = m_opHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT];
        if (dataDir.VirtualAddress > 0)
        {
                UINT curFileAddr = VAToRawAddr(dataDir.VirtualAddress);
                fseek(fp, curFileAddr, 0);
                fread_s(&importTable, sizeof(importTable), sizeof(IMAGE_DELAY_IMPORT_DESCRIPTOR), 1, fp);
                m_NumImportDll = 0;
                while(importTable.rvaIAT)
                {
                        m_NumImportDll++;
                        //获取导入库的名称
                        UINT dllNameFileAddr = VAToRawAddr(importTable.rvaDLLName);
                        fseek(fp, dllNameFileAddr, 0);
                        fread_s(&dllName, sizeof(dllName), sizeof(dllName), 1, fp);

                        UINT originalRawAddr = VAToRawAddr(importTable.rvaINT);
                        fseek(fp, originalRawAddr, 0);
                        fread_s(&thunkData, sizeof(thunkData), sizeof(IMAGE_THUNK_DATA), 1, fp);

                        unsigned int k = 0;
                        while(thunkData.u1.AddressOfData)
                        {
                                FUNCIMPINFO funcImpInfo;
                                funcImpInfo.dllName.assign(dllName);
                                if (thunkData.u1.Ordinal & 0x80000000) //如果最高位为1,那么函数是以序号导入的
                                {
                                        funcImpInfo.ordinal = thunkData.u1.Ordinal & 0x7fffffff;
                                }
                                else //如果是名字输出,那么该地址是指向IMAGE_IMPORT_BY_NAME的RVA
                                {
                                        IMAGE_IMPORT_BY_NAME importByName;
                                        char funcName[50] = {'0'};
                                        UINT nameFuncAddr = VAToRawAddr(thunkData.u1.AddressOfData);
                                        fseek(fp, nameFuncAddr, 0);
                                        fread_s(&importByName, sizeof(importByName), sizeof(IMAGE_IMPORT_BY_NAME), 1, fp);
                                        funcImpInfo.ordinal = importByName.Hint;
                                        fseek(fp, nameFuncAddr + 2, 0);
                                        fread_s(funcName, sizeof(funcName), sizeof(funcName), 1, fp);
                                        funcImpInfo.funcName.assign(funcName);
                                }
                                m_vDelayImportFunc.push_back(funcImpInfo);

                                fseek(fp, originalRawAddr + (++k) * sizeof(IMAGE_THUNK_DATA), 0);
                                fread_s(&thunkData, sizeof(thunkData), sizeof(IMAGE_THUNK_DATA), 1, fp);
                        }

                        fseek(fp, curFileAddr + m_NumImportDll * sizeof(IMAGE_DELAY_IMPORT_DESCRIPTOR), 0);
                        fread_s(&importTable, sizeof(importTable), sizeof(IMAGE_DELAY_IMPORT_DESCRIPTOR), 1, fp);
                }
                //打印输入表信息
                DebugPrint("\n\n\n——————————Delay Import Table——————————\n");
                for_each(m_vDelayImportFunc.begin(), m_vDelayImportFunc.end(), printImportTable);
        }
}
//解析绑定输入表
void CParsePE::ParseBoundImportTable()
{
        IMAGE_DATA_DIRECTORY dataDir;
        IMAGE_BOUND_IMPORT_DESCRIPTOR boundImportTable;
        IMAGE_BOUND_FORWARDER_REF boundForRef;
        char dllName[56] = {'0'};
        dataDir = m_opHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT];
        if (dataDir.VirtualAddress)
        {
                DebugPrint("\n\n\n——————————BOUND IMPORT TABLE——————————\n");
                UINT curFileAddr = VAToRawAddr(dataDir.VirtualAddress);
                fseek(fp, curFileAddr, 0);
                fread_s(&boundImportTable, sizeof(boundImportTable), sizeof(IMAGE_BOUND_IMPORT_DESCRIPTOR), 1, fp);
                UINT k = 0;
                while(boundImportTable.OffsetModuleName)
                {
                        fseek(fp, curFileAddr + boundImportTable.OffsetModuleName, 0);
                        fread_s(&dllName, sizeof(dllName), 56, 1, fp);
                        DebugPrint("%s\t", dllName);
                        for (int i = 0; i < boundImportTable.NumberOfModuleForwarderRefs; i++)
                        {
                                fseek(fp, curFileAddr + (++k) * sizeof(IMAGE_BOUND_IMPORT_DESCRIPTOR), 0);
                                fread_s(&boundImportTable, sizeof(boundImportTable), sizeof(IMAGE_BOUND_IMPORT_DESCRIPTOR), 1, fp);
                                fseek(fp, curFileAddr + boundImportTable.OffsetModuleName, 0);
                                fread_s(&dllName, sizeof(dllName), 56, 1, fp);
                                DebugPrint("%s\t", dllName);
                        }

                        fseek(fp, curFileAddr + (++k) * sizeof(IMAGE_BOUND_IMPORT_DESCRIPTOR), 0);
                        fread_s(&boundImportTable, sizeof(boundImportTable), sizeof(IMAGE_BOUND_IMPORT_DESCRIPTOR), 1, fp);
                }
        }
        //boundImportTable.OffsetModuleName

}
//解析DEBUG目录表
void CParsePE::ParseDebugTable()
{
        IMAGE_DATA_DIRECTORY debugDir;
        IMAGE_DEBUG_DIRECTORY debugTable;
        char pdbName[128];
        debugDir = m_opHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
        if (debugDir.VirtualAddress)
        {
                UINT curFileAddr = VAToRawAddr(debugDir.VirtualAddress);
                fseek(fp, curFileAddr, 0);
                fread_s(&debugTable, sizeof(debugTable), sizeof(IMAGE_DEBUG_DIRECTORY), 1, fp);
                if (IMAGE_DEBUG_TYPE_CODEVIEW == debugTable.Type)
                {
                        fseek(fp, debugTable.PointerToRawData + 6, 0);
                        fread_s(&pdbName, sizeof(pdbName), 128, 1, fp);
                        DebugPrint("\n\n\n——————————Debug Table——————————\n"\
                                "The path of PDB : %s", pdbName);
                }
        }

}

//解析RESOURSE目录表
void CParsePE::ParseResouceTable()
{
        IMAGE_DATA_DIRECTORY resDir;
        IMAGE_RESOURCE_DIRECTORY resTable;
        IMAGE_RESOURCE_DIRECTORY_ENTRY resEntryTable;
        resDir = m_opHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
        if (resDir.VirtualAddress)
        {
                DebugPrint("\n\n\n——————————RESOURCE TABLE——————————\n");
                UINT curFileAddr = VAToRawAddr(resDir.VirtualAddress);
                fseek(fp, curFileAddr, 0);
                fread_s(&resTable, sizeof(resTable), sizeof(IMAGE_RESOURCE_DIRECTORY), 1, fp);
                UINT numEntry = resTable.NumberOfIdEntries + resTable.NumberOfNamedEntries;
                DebugPrint("numEntry1:%d\n", numEntry);
                //第一层目录
                //定义的是资源类型
                for (int i = 0; i < numEntry; i++)
                {
                        fseek(fp, curFileAddr + sizeof(IMAGE_RESOURCE_DIRECTORY) + i * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY), 0);
                        fread_s(&resEntryTable, sizeof(resEntryTable), sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY), 1, fp);
                        //资源类型的ID
                        //01 Cursor                                        08 Font(字体)                                 
                        //02 Bitmap                                        09 Accelerators(加速键)       
                        //03 Icon                                        0A Unformatted(未格式资源)                       
                        //04 Menu                                        0B MessageTable(消息表)
                        //05 Dialog                                        0C Group Cursor(光标组)
                        //06 String                                        0E Group Icon(图标组)
                        //07 Font Directory                        10 Versoin Information(版本信息)
                        DebugPrint("\nresType%d : 0x%x\n", i, resEntryTable.Id);
                        //是否低位数据指向下一层目录块的起始地址
                        if (resEntryTable.DataIsDirectory)
                        {
                                IMAGE_RESOURCE_DIRECTORY resTable2;
                                fseek(fp, curFileAddr + resEntryTable.OffsetToDirectory, 0);
                                fread_s(&resTable2, sizeof(resTable2), sizeof(IMAGE_RESOURCE_DIRECTORY), 1, fp);
                                UINT numEntry2 = resTable2.NumberOfIdEntries + resTable2.NumberOfNamedEntries;
                                DebugPrint("numEntry2:%d\n", numEntry2);
                                //第二层目录
                                //定义的是资源的名称
                                for (int j = 0; j < numEntry2; j++)
                                {
                                        IMAGE_RESOURCE_DIRECTORY_ENTRY resEntryTable2;
                                        fseek(fp, curFileAddr + resEntryTable.OffsetToDirectory
                                                + sizeof(IMAGE_RESOURCE_DIRECTORY) + j * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY), 0);
                                        fread_s(&resEntryTable2, sizeof(resEntryTable2), sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY), 1, fp);
                                        //第二层的NAME字段是目录项的名称字符串指针,否则用ID号表示
                                        if (resEntryTable2.NameIsString)
                                        {
                                                IMAGE_RESOURCE_DIR_STRING_U dirStr;
                                                fseek(fp, curFileAddr + resEntryTable2.NameOffset, 0);
                                                fread_s(&dirStr, sizeof(resDir), sizeof(IMAGE_RESOURCE_DIR_STRING_U), 1, fp);
                                                DebugPrint("Name:%s\n", dirStr.NameString);

                                        }
                                        else
                                        {
                                                DebugPrint("ID:%d\n", resEntryTable2.NameOffset);
                                        }
                                        //最高位为1时,指向下一层目录块的起始地址,否则指针指向IMAGE_RESOURCE_DATA_ENTRY
                                        if (resEntryTable2.DataIsDirectory)
                                        {
                                                IMAGE_RESOURCE_DIRECTORY resTable3;
                                                fseek(fp, curFileAddr + resEntryTable2.OffsetToDirectory, 0);
                                                fread_s(&resTable3, sizeof(resTable3), sizeof(IMAGE_RESOURCE_DIRECTORY), 1, fp);
                                                UINT numEntry3 = resTable3.NumberOfIdEntries + resTable3.NumberOfNamedEntries;
                                                DebugPrint("numEntry3:%d\n", numEntry3);
                                                //第三层
                                                //定义的是代码页编号
                                                for (int k = 0; k < numEntry3; k++)
                                                {
                                                        IMAGE_RESOURCE_DIRECTORY_ENTRY resEntryTable3;
                                                        fseek(fp, curFileAddr + resEntryTable2.OffsetToDirectory
                                                                + sizeof(IMAGE_RESOURCE_DIRECTORY) + k * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY), 0);
                                                        fread_s(&resEntryTable3, sizeof(resEntryTable3), sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY), 1, fp);
                                                        if (!resEntryTable3.DataIsDirectory)
                                                        {
                                                                IMAGE_RESOURCE_DATA_ENTRY resDirEntry;
                                                                fseek(fp, curFileAddr + resEntryTable3.OffsetToDirectory, 0);
                                                                fread_s(&resDirEntry, sizeof(resDirEntry), sizeof(IMAGE_RESOURCE_DATA_ENTRY), 1, fp);
                                                                DebugPrint("Rva:0x%x\t", resDirEntry.OffsetToData + m_PeInfo.imageBase);
                                                                DebugPrint("size:%d\n", resDirEntry.Size);
                                                        }
                                                        else
                                                        {
                                                                _asm int 3
                                                        }
                                                }

                                        }
                                        else
                                        {
                                                IMAGE_RESOURCE_DATA_ENTRY resDirEntry;
                                                fseek(fp, curFileAddr + resEntryTable2.OffsetToDirectory, 0);
                                                fread_s(&resDirEntry, sizeof(resDirEntry), sizeof(IMAGE_RESOURCE_DATA_ENTRY), 1, fp);
                                                DebugPrint("Rva:0x%x\t", resDirEntry.OffsetToData + m_PeInfo.imageBase);
                                                DebugPrint("size:%d\n", resDirEntry.Size);
                                        }
                                }
                        }
                }
        }

}
void CParsePE::DisplayPEInfo()
{

}
2012-5-9 20:48
0
雪    币: 149
活跃值: (150)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
3
ParsePE.h

#pragma once
#include <Windows.h>
#include <assert.h>
#include <iostream>
#include <vector>
using namespace std;

//导出表函数
typedef struct _FUNCEXPINFO
{
        UINT rva; //相对虚拟地址
        UINT ordinal; //序号
        string name; //名称
}FUNCEXPINFO;

//导入表函数
typedef struct _FUNCIMPINFO
{
        string dllName; //DLL名称
        UINT ordinal; //在对应的DLL输出表的序号
        string funcName; //导入函数名称
}FUNCIMPINFO;

typedef struct _PEINFO
{
        bool bDLL;
        long imageBase;
        long entryPoint;
        long dosRVA;
        long dosSize;
        long pNtHeader;
        long numSections;
        long sectionAlign;
        long fileAlign;
}PEINFO;

class CParsePE
{
public:
        CParsePE(const wchar_t *pFileName)
        {
                assert(0 != pFileName);
                m_PeInfo.imageBase = 0;
                errno_t err;
                if ((err = _wfopen_s(&fp, pFileName, L"r")) != 0)
                {
                        cout<<"The file '"<<pFileName<<"'"<<"was not opened!"<<endl;
                }
                if (!is_pe_file())
                {
                        cout<<"is not pe file!"<<endl;
                }

        }
        ~CParsePE(void)
        {
                if (fp != 0)
                {
                        fclose(fp);
                }
        }

public:
        bool is_pe_file();
        bool findIsFunc(UINT rva, UINT ordinal);
        void ParseSections();
        void ParseDosHeader();
        void ParseNtHeader();
        void ParseExportTable();
        void ParseImportTable();
        void ParseBoundImportTable();
        void ParseDelayImportTable();
        void ParseDebugTable();
        void ParseResouceTable();
        UINT VAToRawAddr(UINT virtualAddr);
        void DisplayPEInfo();
public:
        //void printExportTable(FUNCINFO funcInfo);
private:
        PEINFO m_PeInfo;
        FILE *fp;
        IMAGE_DOS_HEADER m_dosHeader;
        IMAGE_NT_HEADERS m_ntHeader;
        IMAGE_FILE_HEADER m_fileHeader;
        IMAGE_OPTIONAL_HEADER m_opHeader;
        IMAGE_SECTION_HEADER m_secHeader;
        IMAGE_DATA_DIRECTORY m_dataDir;
        IMAGE_IMPORT_DESCRIPTOR m_importDir;
        IMAGE_EXPORT_DIRECTORY m_exportDir;
        IMAGE_RESOURCE_DIRECTORY m_resourceDir;
        IMAGE_TLS_DIRECTORY m_tlsDir;
private:
        vector<UINT> m_vSectionVirtualAddress;        //块的起始地址VA
        vector<UINT> m_vSectionVirtualSize;        //块的大小(包含块的间隙)
        vector<UINT> m_vSectionRawAddress;        //块的其实地址(在物理文件中)
        vector<UINT> m_vSectionRawSize;        //块的大小(物理文件中)
private:
        vector<FUNCEXPINFO> m_vExportFunc;
        vector<FUNCIMPINFO> m_vImportFunc;
        vector<FUNCIMPINFO> m_vDelayImportFunc;
        int m_NumImportDll;
};
2012-5-9 20:49
0
雪    币: 149
活跃值: (150)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
4
分析NOTEPAD.EXE结果如下

——————————Dos Header Info——————————
dos RVA : 0x00000000
dos size : 0x000000e0

——————————sections Info——————————
section name : .text
VirtualAddress : 0x00001000
VirtualSize : 0x00008000
RawAddress : 0x00000400
RwaSize : 0x00007800
section name : .data
VirtualAddress : 0x00009000
VirtualSize : 0x00002000
RawAddress : 0x00007c00
RwaSize : 0x00000800
section name : .rsrc
VirtualAddress : 0x0000b000
VirtualSize : 0x00008000
RawAddress : 0x00008400
RwaSize : 0x00008000

——————————Header Info——————————
imageBase : 0x01000000
entryPoint : 0x0000739d
sectionAlignment : 0x00001000
fileAlignment : 0x00000200
numSections : 0x00000003

——————————Import Table——————————
comdlg32.dll        0x0000000f        PageSetupDlgW
comdlg32.dll        0x00000006        FindTextW
comdlg32.dll        0x00000012        PrintDlgExW
comdlg32.dll        0x00000003        ChooseFontW
comdlg32.dll        0x00000008        GetFileTitleW
comdlg32.dll        0x0000000a        GetOpenFileNameW
comdlg32.dll        0x00000015        ReplaceTextW
comdlg32.dll        0x00000004        CommDlgExtendedError
comdlg32.dll        0x0000000c        GetSaveFileNameW
SHELL32.dll        0x0000001f        DragFinish
SHELL32.dll        0x00000023        DragQueryFileW
SHELL32.dll        0x0000001e        DragAcceptFiles
SHELL32.dll        0x00000103        ShellAboutW
WINSPOOL.DRV        0x00000078        GetPrinterDriverW
WINSPOOL.DRV        0x0000001b        ClosePrinter
WINSPOOL.DRV        0x0000007e        OpenPrinterW
COMCTL32.dll        0x00000008        CreateStatusWindowW
msvcrt.dll        0x0000004e        _XcptFilter
msvcrt.dll        0x000000f6        _exit
msvcrt.dll        0x000000c5        _c_exit
msvcrt.dll        0x00000317        time
msvcrt.dll        0x000002d4        localtime
msvcrt.dll        0x000000c8        _cexit
msvcrt.dll        0x000002c6        iswctype
msvcrt.dll        0x000000ed        _except_handler3
msvcrt.dll        0x00000274        _wtol
msvcrt.dll        0x0000032f        wcsncmp
msvcrt.dll        0x000001e4        _snwprintf
msvcrt.dll        0x00000290        exit
msvcrt.dll        0x000000a8        _acmdln
msvcrt.dll        0x0000006d        __getmainargs
msvcrt.dll        0x0000013b        _initterm
msvcrt.dll        0x0000009a        __setusermatherr
msvcrt.dll        0x000000b6        _adjust_fdiv
msvcrt.dll        0x00000080        __p__commode
msvcrt.dll        0x00000085        __p__fmode
msvcrt.dll        0x00000098        __set_app_type
msvcrt.dll        0x000000d6        _controlfp
msvcrt.dll        0x00000330        wcsncpy
ADVAPI32.dll        0x000001ef        RegQueryValueExW
ADVAPI32.dll        0x000001ca        RegCloseKey
ADVAPI32.dll        0x000001d0        RegCreateKeyW
ADVAPI32.dll        0x00000139        IsTextUnicode
ADVAPI32.dll        0x000001ee        RegQueryValueExA
ADVAPI32.dll        0x000001e4        RegOpenKeyExA
ADVAPI32.dll        0x000001fc        RegSetValueExW
KERNEL32.dll        0x0000013e        GetCurrentThreadId
KERNEL32.dll        0x000001d4        GetTickCount
KERNEL32.dll        0x00000294        QueryPerformanceCounter
KERNEL32.dll        0x0000016a        GetLocalTime
KERNEL32.dll        0x000001d8        GetUserDefaultLCID
KERNEL32.dll        0x00000140        GetDateFormatW
KERNEL32.dll        0x000001d6        GetTimeFormatW
KERNEL32.dll        0x000001f8        GlobalLock
KERNEL32.dll        0x000001ff        GlobalUnlock
KERNEL32.dll        0x0000015a        GetFileInformationByHandle
KERNEL32.dll        0x00000051        CreateFileMappingW
KERNEL32.dll        0x000001c0        GetSystemTimeAsFileTime
KERNEL32.dll        0x0000034a        TerminateProcess
KERNEL32.dll        0x0000013b        GetCurrentProcess
KERNEL32.dll        0x00000336        SetUnhandledExceptionFilter
KERNEL32.dll        0x00000244        LoadLibraryA
KERNEL32.dll        0x00000176        GetModuleHandleA
KERNEL32.dll        0x000001ae        GetStartupInfoA
KERNEL32.dll        0x000001f4        GlobalFree
KERNEL32.dll        0x0000016c        GetLocaleInfoW
KERNEL32.dll        0x0000024e        LocalFree
KERNEL32.dll        0x0000024a        LocalAlloc
KERNEL32.dll        0x000003b8        lstrlenW
KERNEL32.dll        0x00000254        LocalUnlock
KERNEL32.dll        0x00000038        CompareStringW
KERNEL32.dll        0x00000250        LocalLock
KERNEL32.dll        0x000000ea        FoldStringW
KERNEL32.dll        0x00000031        CloseHandle
KERNEL32.dll        0x000003b2        lstrcpyW
KERNEL32.dll        0x000002a6        ReadFile
KERNEL32.dll        0x00000052        CreateFileW
KERNEL32.dll        0x000003af        lstrcmpiW
KERNEL32.dll        0x0000013c        GetCurrentProcessId
KERNEL32.dll        0x00000198        GetProcAddress
KERNEL32.dll        0x0000010a        GetCommandLineW
KERNEL32.dll        0x000003a9        lstrcatW
KERNEL32.dll        0x000000cc        FindClose
KERNEL32.dll        0x000000d3        FindFirstFileW
KERNEL32.dll        0x00000159        GetFileAttributesW
KERNEL32.dll        0x000003ac        lstrcmpW
KERNEL32.dll        0x00000266        MulDiv
KERNEL32.dll        0x000003b5        lstrcpynW
KERNEL32.dll        0x00000253        LocalSize
KERNEL32.dll        0x00000168        GetLastError
KERNEL32.dll        0x0000038f        WriteFile
KERNEL32.dll        0x00000316        SetLastError
KERNEL32.dll        0x00000382        WideCharToMultiByte
KERNEL32.dll        0x00000251        LocalReAlloc
KERNEL32.dll        0x000000ec        FormatMessageW
KERNEL32.dll        0x000001da        GetUserDefaultUILanguage
KERNEL32.dll        0x00000300        SetEndOfFile
KERNEL32.dll        0x00000082        DeleteFileW
KERNEL32.dll        0x000000f6        GetACP
KERNEL32.dll        0x0000035e        UnmapViewOfFile
KERNEL32.dll        0x00000267        MultiByteToWideChar
KERNEL32.dll        0x0000025a        MapViewOfFile
KERNEL32.dll        0x0000035b        UnhandledExceptionFilter
GDI32.dll        0x00000098        EndPage
GDI32.dll        0x00000000        AbortDoc
GDI32.dll        0x00000096        EndDoc
GDI32.dll        0x0000008c        DeleteDC
GDI32.dll        0x00000249        StartPage
GDI32.dll        0x000001b6        GetTextExtentPoint32W
GDI32.dll        0x0000002f        CreateDCW
GDI32.dll        0x00000211        SetAbortProc
GDI32.dll        0x000001bc        GetTextFaceW
GDI32.dll        0x00000250        TextOutW
GDI32.dll        0x00000247        StartDocW
GDI32.dll        0x000000ce        EnumFontsW
GDI32.dll        0x000001a6        GetStockObject
GDI32.dll        0x00000198        GetObjectW
GDI32.dll        0x0000016c        GetDeviceCaps
GDI32.dll        0x0000003d        CreateFontIndirectW
GDI32.dll        0x0000008f        DeleteObject
GDI32.dll        0x000001be        GetTextMetricsW
GDI32.dll        0x00000217        SetBkMode
GDI32.dll        0x000001cc        LPtoDP
GDI32.dll        0x00000243        SetWindowExtEx
GDI32.dll        0x0000023f        SetViewportExtEx
GDI32.dll        0x0000022c        SetMapMode
GDI32.dll        0x0000020f        SelectObject
USER32.dll        0x000000ff        GetClientRect
USER32.dll        0x0000024d        SetCursor
USER32.dll        0x0000022a        ReleaseDC
USER32.dll        0x0000010c        GetDC
USER32.dll        0x0000009f        DialogBoxParamW
USER32.dll        0x00000243        SetActiveWindow
USER32.dll        0x00000122        GetKeyboardLayout
USER32.dll        0x0000008f        DefWindowProcW
USER32.dll        0x00000099        DestroyWindow
USER32.dll        0x000001db        MessageBeep
USER32.dll        0x00000292        ShowWindow
USER32.dll        0x00000117        GetForegroundWindow
USER32.dll        0x000001a6        IsIconic
USER32.dll        0x00000173        GetWindowPlacement
USER32.dll        0x00000037        CharUpperW
USER32.dll        0x000001c9        LoadStringW
USER32.dll        0x000001b4        LoadAcceleratorsW
USER32.dll        0x0000015c        GetSystemMenu
USER32.dll        0x00000218        RegisterClassExW
USER32.dll        0x000001be        LoadImageW
USER32.dll        0x000001ba        LoadCursorW
USER32.dll        0x00000282        SetWindowPlacement
USER32.dll        0x00000061        CreateWindowExW
USER32.dll        0x0000010e        GetDesktopWindow
USER32.dll        0x00000116        GetFocus
USER32.dll        0x000001bc        LoadIconW
USER32.dll        0x00000287        SetWindowTextW
USER32.dll        0x00000201        PostQuitMessage
USER32.dll        0x00000228        RegisterWindowMessageW
USER32.dll        0x000002bb        UpdateWindow
USER32.dll        0x0000026f        SetScrollPos
USER32.dll        0x00000029        CharLowerW
USER32.dll        0x000001fe        PeekMessageW
USER32.dll        0x000000c4        EnableWindow
USER32.dll        0x000000be        DrawTextExW
USER32.dll        0x00000056        CreateDialogParamW
USER32.dll        0x0000017a        GetWindowTextW
USER32.dll        0x0000015d        GetSystemMetrics
USER32.dll        0x000001e9        MoveWindow
USER32.dll        0x00000193        InvalidateRect
USER32.dll        0x000002d3        WinHelpW
USER32.dll        0x00000110        GetDlgCtrlID
USER32.dll        0x0000003c        ChildWindowFromPoint
USER32.dll        0x00000231        ScreenToClient
USER32.dll        0x0000010b        GetCursorPos
USER32.dll        0x00000237        SendDlgItemMessageW
USER32.dll        0x00000240        SendMessageW
USER32.dll        0x0000002c        CharNextW
USER32.dll        0x00000039        CheckMenuItem
USER32.dll        0x00000042        CloseClipboard
USER32.dll        0x0000019f        IsClipboardFormatAvailable
USER32.dll        0x000001f3        OpenClipboard
USER32.dll        0x00000137        GetMenuState
USER32.dll        0x000000c2        EnableMenuItem
USER32.dll        0x00000159        GetSubMenu
USER32.dll        0x0000012c        GetMenu
USER32.dll        0x000001e3        MessageBoxW
USER32.dll        0x00000281        SetWindowLongW
USER32.dll        0x0000016f        GetWindowLongW
USER32.dll        0x00000111        GetDlgItem
USER32.dll        0x00000256        SetFocus
USER32.dll        0x00000254        SetDlgItemTextW
USER32.dll        0x000002d9        wsprintfW
USER32.dll        0x00000114        GetDlgItemTextW
USER32.dll        0x000000c6        EndDialog
USER32.dll        0x00000145        GetParent
USER32.dll        0x000002ac        UnhookWinEvent
USER32.dll        0x000000a2        DispatchMessageW
USER32.dll        0x000002aa        TranslateMessage
USER32.dll        0x000002a8        TranslateAcceleratorW
USER32.dll        0x000001a2        IsDialogMessageW
USER32.dll        0x00000200        PostMessageW
USER32.dll        0x0000013e        GetMessageW
USER32.dll        0x0000027e        SetWinEventHook

——————————BOUND IMPORT TABLE——————————
comdlg32.dll        SHELL32.dll        WINSPOOL.DRV        COMCTL32.dll        msvcrt.dll        ADVAPI32.dll        KERNEL32.dll        NTDLL.DLL        GDI32.dll        USER32.dll       

——————————Debug Table——————————
The path of PDB : oPテ;E彏踀痳蜎

——————————RESOURCE TABLE——————————
numEntry1:8

resType0 : 0x3
numEntry2:9
ID:1
numEntry3:1
Rva:0x100b568        size:1640
ID:2
numEntry3:1
Rva:0x100bbd0        size:744
ID:3
numEntry3:1
Rva:0x100beb8        size:296
ID:4
numEntry3:1
Rva:0x100bfe0        size:3752
ID:5
numEntry3:1
Rva:0x100ce88        size:2216
ID:6
numEntry3:1
Rva:0x100d730        size:1384
ID:7
numEntry3:1
Rva:0x100dc98        size:9640
ID:8
numEntry3:1
Rva:0x1010240        size:4264
ID:9
numEntry3:1
Rva:0x10112e8        size:1128

resType1 : 0x4
numEntry2:1
ID:1
numEntry3:1
Rva:0x1011750        size:816

resType2 : 0x5
numEntry2:4
Name:N
numEntry3:1
Rva:0x1011780        size:816
ID:11
numEntry3:1
Rva:0x10117fc        size:816
ID:12
numEntry3:1
Rva:0x1011bbc        size:1128
ID:14
numEntry3:1
Rva:0x1012024        size:208

resType3 : 0x6
numEntry2:4
ID:1
numEntry3:1
Rva:0x10120f4        size:668
ID:2
numEntry3:1
Rva:0x1012390        size:700
ID:3
numEntry3:1
Rva:0x101264c        size:232
ID:30
numEntry3:1
Rva:0x1012734        size:40

resType4 : 0x9
numEntry2:2
Name:M
numEntry3:1
Rva:0x101275c        size:136
Name:S
numEntry3:1
Rva:0x10127e4        size:168

resType5 : 0xe
numEntry2:1
ID:2
numEntry3:1
Rva:0x101288c        size:132

resType6 : 0x10
numEntry2:1
ID:1
numEntry3:1
Rva:0x1012910        size:880

resType7 : 0x18
numEntry2:1
ID:1
numEntry3:1
Rva:0x1012c80        size:670
2012-5-9 20:50
0
雪    币: 306
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
不错. 高手,可不可以弄个附件呢.
2012-11-3 17:43
0
雪    币: 55
活跃值: (519)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
6
我学PE只学到导出节,后面的资源节反而没看。
2012-11-3 18:27
0
雪    币: 214
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
很好,学习了,谢谢
2012-11-11 20:33
0
雪    币: 1358
活跃值: (17)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
建议用附件附近附上代码,这样更方便大家啊!
2012-11-17 13:40
0
雪    币: 2262
活跃值: (871)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
Debug Table 这里还不够详细,没考虑会存在多个IMAGE_DEBUG_DIRECTORY信息
2012-11-20 12:29
0
雪    币: 134
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
同意8楼……
2012-11-20 12:39
0
雪    币: 1552
活跃值: (1288)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
11
缺重定位表
2013-10-5 15:55
0
游客
登录 | 注册 方可回帖
返回
//