32位PE文件信息查看器(WIN32控制台)

这是一个用于查看32位PE文件格式的控制台程序,能够读取DOS头、NT头、节区头、导入表和导出表信息。代码仅供学习参考,不保证鲁棒性和安全性,未包含边界检查。作者提醒,程序仅适用于标准32位PE文件,不适用于其他类型文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近重新撸了一遍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>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值