首页
社区
课程
招聘
[原创]Pe解析总结
发表于: 2013-12-2 20:34 4196

[原创]Pe解析总结

2013-12-2 20:34
4196

前言   

    一个操作系统的可执行文件格式在很多方面是这个系统的一面镜子。虽然学习一个可执行文件格式通常不是一个程序员的首要任务,但是你可以从这其中学到大量的知识。在可预知的未来,包括, PE文件格式在 MicroSoft 的操作系统中扮演一个重要的角色。如果你在使用 Win32 或 Winnt ,那么你已经在使用 PE 文件了。甚至你只是在 Windows3.1 下使用 Visual C++编程,你使用的仍然是 PE 文件(Visual C++ 的 32 位扩展组件用这个格式)。简而言之,PE 格式已经普遍应用,并且在不短的将来仍是不可避免的。PE结构如此重要,我们可以通过写一个PE_EDIT 工具来理解pe文件,这是本文的目的(15pb项目)
                                                          总体设计

      以简洁,直观的设计理念。我以树控件为主要控件,如下图:   


当然,树控件总体展现能力强,具体数据展示能力比较弱。为了弥补这一缺陷,我加了右键菜单功能。鼠标点击树控件哪一项,来展示具体数据。

为了数据和界面分离,可以写个数据类,这里是CPeTool。所有的数据组织都在这个类里面,当然这个pe工具所有的逻辑都在这个类里面

class PeTool
{
private:
        MAP_FILE_STRUCT m_filestruct;
public:
        vector<LPVOID>  m_importVector;
        vector<DOSHEADER*> m_DosHeaderVector;
        vector<DOSHEADER*> m_FileHeaderVector;
        vector<DOSHEADER*> m_OptionHeaderVector;
        vector<SECTION*>        m_SectionVector;
        vector<EXPORT_FUNC_DESCRIPTOR> m_ExportFucDecVector;
 
        vector<IMPORT_TABLE> m_ImportTableVector;
        IMAGE_IMPORT_DESCRIPTOR m_Image_Import;
        IMAGE_EXPORT_DIRECTORY m_Image_Export;
        DWORD m_exportOffset;
        bool m_isHasExport;
        bool m_isHaxImport;
         
public:
   PeTool();
        ~PeTool();
        TREENODE* m_pHeadNode;
        TREENODE* m_pResourceHeadNode;
        bool LoadFile(LPSTR lpFileName);
        //是否为PE
        bool IsPe();
        //我用的是树形框,构造树,初始化后,此数据初始化树形框
        void CreateTree();
        //创建资源数
        void CreateResourceTree();
        void AddNodeToResourceTree(TREENODE*,PIMAGE_RESOURCE_DIRECTORY,int depath);
        void PreAddNode(TREENODE*,int&);
        //释放空间
        void DeleteTree(TREENODE*);
        //分析dosheader
        void DosHeaderAnalysis();
        //分析Fileheader
        void FileHeaderAnalysis();
        //分析Optionheader
        void OptionHeaderAnalysis();
        //分析Section
        void SectionAnalysis();
        //分析EXport_Table
        void ExportTableAnalysis();
        //分析Import_table
        void ImportTableAnalysis();
        //得到资源指针
        DWORD GetResourceOffset();
        PIMAGE_DOS_HEADER GetDosHeaderPt();
        //地址转换
        DWORD RSAtoOffset(DWORD);
        //得到NT指针
        PIMAGE_NT_HEADERS GetNTheaderPt();
        //得到数据目录地址  根据INDEX
        PIMAGE_DATA_DIRECTORY GetDataDirectoryEnty(int index);
        //得到第一个节的指针
        PIMAGE_SECTION_HEADER GetFirstSectionHeader();
        //地址转换
        LPVOID RvaToOffet(LPVOID Rva);
        //得到可选头指针
        PIMAGE_OPTIONAL_HEADER32 GetOptionHeader();
        //得到文件头指针
        PIMAGE_FILE_HEADER GetFileHeader();
};
/*********************************************************************/
 
/*
此函数最先调用 保存文件句柄,内存文件地址
*/
bool PeTool::LoadFile(LPSTR lpFileName)
{
         
        HANDLE hFile;
    HANDLE hMapping;
    LPVOID ImageBase;
 
        memset(&m_filestruct,0,sizeof(MAP_FILE_STRUCT));
 
    hFile=CreateFile(lpFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING, 
        FILE_ATTRIBUTE_NORMAL,0);
 
    if (!hFile)                                   
                return false;
 
    hMapping=CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
    if(!hMapping)
    {                                                                        
        CloseHandle(hFile);
        return FALSE;
    }
    ImageBase=MapViewOfFile(hMapping,FILE_MAP_READ,0,0,0);
    if(!ImageBase)
        {
                  CloseHandle(hFile);
                  CloseHandle(hMapping);
                  return false;
        }
        m_filestruct.hFile=hFile;
    m_filestruct.hMapping=hMapping;
    m_filestruct.ImageBase=ImageBase;
 
  }
/*********************************************************************/
 
/*
        把pe内存文件地址转换成dos  header pointer
*/
PIMAGE_DOS_HEADER PeTool::GetDosHeaderPt()
{
    PIMAGE_DOS_HEADER  pDosHeader;
        pDosHeader=(PIMAGE_DOS_HEADER)m_filestruct.ImageBase;
    return pDosHeader;
}
/*********************************************************************/
/*
  根据 dos header 中的e_lfanew字段 求出文件的NT headers 的指针
*/
PIMAGE_NT_HEADERS PeTool::GetNTheaderPt()
{
    PIMAGE_DOS_HEADER  pDosHeader=NULL;
        pDosHeader=GetDosHeaderPt();
    PIMAGE_NT_HEADERS  pNtHeader=NULL;
        pNtHeader=(PIMAGE_NT_HEADERS)(pDosHeader->e_lfanew+(DWORD)m_filestruct.ImageBase);
    return pNtHeader;
}
/*********************************************************************/
/*
        根据NT header FileHeader 字段得出PIMAGE_FILE_HEADER
*/
PIMAGE_FILE_HEADER PeTool::GetFileHeader()
{
    
    PIMAGE_NT_HEADERS pNTHeader;
    PIMAGE_FILE_HEADER pFileHeader;
    pNTHeader=GetNTheaderPt();
    pFileHeader=&(pNTHeader->FileHeader);
    return pFileHeader;
}
/*********************************************************************/
/*
         根据RVA 求出文件地址
*/
LPVOID PeTool::RvaToOffet(LPVOID Rva)
{
 
    PIMAGE_FILE_HEADER pFileHeader;
        // get file pointer of fileheader
    pFileHeader=GetFileHeader();
 
    int NumberOfSections=0;
    NumberOfSections=pFileHeader->NumberOfSections;
    PIMAGE_SECTION_HEADER pSectionHeader;
        // get the first section pointer
    pSectionHeader=GetFirstSectionHeader();
 
    for(int i=0;i<NumberOfSections;i++)
    {
        int virtualsize;
        DWORD VirtualAddress;
        virtualsize=pSectionHeader->Misc.VirtualSize;
        VirtualAddress=pSectionHeader->VirtualAddress;
        if((DWORD)Rva>=VirtualAddress&&(DWORD)Rva<(VirtualAddress+virtualsize))
        {
                        return LPVOID((DWORD)Rva-VirtualAddress+pSectionHeader->PointerToRawData+(DWORD)m_filestruct.ImageBase);
        }
        pSectionHeader++;
    }
    return 0;
}
/*********************************************************************/
/*
根据索引值求的相应数据的数据目录表
*/
PIMAGE_DATA_DIRECTORY PeTool::GetDataDirectoryEnty(int index)
{
    PIMAGE_OPTIONAL_HEADER pOptionHeader;
        pOptionHeader=GetOptionHeader();
    return &(pOptionHeader->DataDirectory[index]);
}
/*********************************************************************/
/*
 得到第一个节表的文件地址
*/
PIMAGE_SECTION_HEADER  PeTool::GetFirstSectionHeader()
{
    PIMAGE_NT_HEADERS     pNtH=NULL;
    PIMAGE_SECTION_HEADER pSH=NULL;
 
    pNtH=GetNTheaderPt();
    pSH=IMAGE_FIRST_SECTION(pNtH);
    return  pSH;
}
/*********************************************************************/
/*
        得到OptionHeader 的文件地址
*/
PIMAGE_OPTIONAL_HEADER32 PeTool::GetOptionHeader()
{
    
    PIMAGE_NT_HEADERS pNTHeader;
    PIMAGE_OPTIONAL_HEADER pOptionalHeader;
 
        pNTHeader=GetNTheaderPt();
    pOptionalHeader=&(pNTHeader->OptionalHeader);
    return pOptionalHeader;
}

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

上传的附件:
收藏
免费 5
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//