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

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

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);
    }
};

PEFile pe;
FILE* outfile;

///对应-q
void ExitProgram()
{
    if(outfile)
        fclose(outfile);
    exit(0);
}

///对应-l
void LoadPEFile(const char*filename)
{
    if(!pe.LoadPEFile(filename))
        printf("文件不存在或无法读取\n");
    else
        printf("读取成功\n");
}
///对应-f filename
void PrintInFile(const char*filename)
{
    outfile=fopen(filename,"w");
}
void PrintMsg(char*str)
{

    if(outfile)
        fprintf(outfile,"%s",str);
    printf("%s",str);
}
///对应于-m dos [main]
void MsgOfDos(bool isMain)
{
    IMAGE_DOS_HEADER dosHeader=pe.GetDosHeader();
    char str[10000];
    strcpy(str,"\n----------------------------DOS头信息--------------------------------\n\n");
    PrintMsg(str);
    sprintf(str,"%-55s:0x%04x\n","DOS文件标记(Magic DOS signature)",dosHeader.e_magic);
    PrintMsg(str);
    sprintf(str,"%-55s:0x%04x\n","重定位表的文件地址(File Address of relocation table)",dosHeader.e_lfarlc);
    PrintMsg(str);
    sprintf(str,"%-55s:0x%08x\n","NT头地址(Offset to start of PE header)",dosHeader.e_lfanew);
    PrintMsg(str);
    if(!isMain)
    {
        sprintf(str,"%-55s:0x%04x\n","最后一页大小(Bytes on last page of file)",dosHeader.e_cblp);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x (%d)\n","文件页数(Pages in file)",dosHeader.e_cp,dosHeader.e_cp);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x\n","文件迁移(Relocations)",dosHeader.e_crlc);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x\n","头的段大小(Size of header in paragraphs)",dosHeader.e_cparhdr);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x\n","最小额外段需求(Minimun extra paragraphs needs)",dosHeader.e_minalloc);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x\n","最大额外段需求(Maximun extra paragraphs needs)",dosHeader.e_maxalloc);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x\n","DOS代码的初始化堆栈SS(intial(relative)SS value)",dosHeader.e_ss);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x\n","DOS代码的初始化堆栈指针SP(intial SP value)",dosHeader.e_sp);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x\n","校验和(Checksum)",dosHeader.e_csum);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x\n","DOS代码的初始化指令入口[指针IP](intial IP value)",dosHeader.e_ip);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x\n","DOS代码的初始堆栈入口(intial(relative)CS value)",dosHeader.e_cs);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x\n","Overlay number",dosHeader.e_ovno);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x\n","OEM identifier(for e_oeminfo)",dosHeader.e_oemid);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x\n","OEM information;e_oemid specific",dosHeader.e_oeminfo);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x 0x%04x 0x%04x 0x%04x\n","保留字(Reserved words,[e_res])",
                dosHeader.e_res[0],
                dosHeader.e_res[1],
                dosHeader.e_res[2],
                dosHeader.e_res[3]);
        PrintMsg(str);
        sprintf(str,"%-55s:\n0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x\n","保留字2(Reserved words,[e_res2])",
                dosHeader.e_res2[0],
                dosHeader.e_res2[1],
                dosHeader.e_res2[2],
                dosHeader.e_res2[3],
                dosHeader.e_res2[4],
                dosHeader.e_res2[5],
                dosHeader.e_res2[6],
                dosHeader.e_res2[7],
                dosHeader.e_res2[8],
                dosHeader.e_res2[9]);
        PrintMsg(str);
    }

    strcpy(str,"\n--------------------------DOS头信息-结束-------------------------------\n\n");
    PrintMsg(str);
}

///对应于-m ntfh [main]
void MsgOfNtfh(bool isMain)
{
    IMAGE_FILE_HEADER ntfh=pe.GetNTFileHeader();
    char str[10000];
    strcpy(str,"\n----------------------------NT文件头信息--------------------------------\n\n");
    PrintMsg(str);
    sprintf(str,"%-55s:0x%04x\n","CPU机器码(Machine)",ntfh.Machine);
    PrintMsg(str);
    sprintf(str,"%-55s:0x%04x(%d)\n","节区数量(NumberOfSections)",ntfh.NumberOfSections,ntfh.NumberOfSections);
    PrintMsg(str);
    sprintf(str,"%-55s:0x%04x\n","属性(Characteristics)",ntfh.Characteristics);
    PrintMsg(str);
    if(!isMain)
    {
        sprintf(str,"%-55s:0x%08x\n","时间戳(TimeDateStamp)",ntfh.TimeDateStamp);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%08x\n","符号表指针(PointerToSymbolTable)",ntfh.PointerToSymbolTable);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%08x\n","符号表大小(NumberOfSymbols)",ntfh.NumberOfSymbols);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x\n","可选头大小(SizeOfOptionalHeader)",ntfh.SizeOfOptionalHeader);
        PrintMsg(str);

    }
    strcpy(str,"\n--------------------------DNT文件头信息-结束-------------------------------\n\n");
    PrintMsg(str);
}

///对应于-m ntoh [main] [d]
void MsgOfNtoh(bool isMain,bool isD)
{
    IMAGE_OPTIONAL_HEADER32 ntoh=pe.GetNTOptionalHeader();
    char str[10000];
    strcpy(str,"\n----------------------------NT可选头信息--------------------------------\n\n");
    PrintMsg(str);
    sprintf(str,"%-55s:0x%04x(%d位)\n","可选头类型(Magic)",ntoh.Magic,ntoh.Magic==0x10b?32:64);
    PrintMsg(str);
    sprintf(str,"%-55s:0x%08x\n","EP地址[RVA](AddressOfEntryPoint)",ntoh.AddressOfEntryPoint);
    PrintMsg(str);
    sprintf(str,"%-55s:0x%08x\n","映象基址(ImageBase)",ntoh.ImageBase);
    PrintMsg(str);
    sprintf(str,"%-55s:0x%08x\n","节对齐(SectionAlignment)",ntoh.SectionAlignment);
    PrintMsg(str);
    sprintf(str,"%-55s:0x%08x\n","文件节对齐(FileAlignment)",ntoh.FileAlignment);
    PrintMsg(str);
    sprintf(str,"%-55s:0x%08x\n","映象大小(SizeOfImage)",ntoh.SizeOfImage);
    PrintMsg(str);
    sprintf(str,"%-55s:0x%08x\n","PE头大小(SizeOfHeaders)",ntoh.SizeOfHeaders);
    PrintMsg(str);
    sprintf(str,"%-55s:0x%04x(%s)\n","子系统(Subsystem)",ntoh.Subsystem,ntoh.Subsystem==1?"系统驱动":
            ntoh.Subsystem==2?"窗口应用程序":"控制台应用程序");
    PrintMsg(str);
    sprintf(str,"%-55s:0x%08x\n","数据目录项数(NumberOfRvaAndSizes)",ntoh.NumberOfRvaAndSizes);
    PrintMsg(str);

    if(!isMain)
    {
        sprintf(str,"%-55s:0x%02x\n","连接器版本号(MajorLinkerVersion)",ntoh.MajorLinkerVersion);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%02x\n","连接器版本号(MinorLinkerVersion)",ntoh.MinorLinkerVersion);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%08x\n","代码段长度(SizeOfCode)",ntoh.SizeOfCode);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%08x\n","初始化数据长度(SizeOfInitializedData)",ntoh.SizeOfInitializedData);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%08x\n","未初始化的数据长度(SizeOfUninitializedData)",ntoh.SizeOfUninitializedData);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%08x\n","代码段起始地址的RVA(BaseOfCode)",ntoh.BaseOfCode);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%08x\n","数据段起始地址的RVA(BaseOfData)",ntoh.BaseOfData);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x\n","操作系统版本号(MajorOperatingSystemVersion)",ntoh.MajorOperatingSystemVersion);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x\n","操作系统版本号(MinorOperatingSystemVersion)",ntoh.MinorOperatingSystemVersion);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x\n","映象的版本号(MajorImageVersion)",ntoh.MajorImageVersion);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x\n","映象的版本号(MinorImageVersion)",ntoh.MinorImageVersion);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x\n","所需子系统版本号(MajorSubsystemVersion)",ntoh.MajorSubsystemVersion);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x\n","所需子系统版本号(MinorSubsystemVersion)",ntoh.MinorSubsystemVersion);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%08x\n","WIN32版本值(Win32VersionValue)",ntoh.Win32VersionValue);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%08x\n","映象文件校验和(CheckSum)",ntoh.CheckSum);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%04x\n","DLL的文件属性(DllCharacteristics)",ntoh.DllCharacteristics);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%08x\n","栈保留内存(SizeOfStackReserve)",ntoh.SizeOfStackReserve);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%08x\n","栈初始占用内存(SizeOfStackCommit)",ntoh.SizeOfStackCommit);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%08x\n","堆保留内存(SizeOfHeapReserve)",ntoh.SizeOfHeapReserve);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%08x\n","堆初始占用内存(SizeOfHeapReserve)",ntoh.SizeOfHeapCommit);
        PrintMsg(str);
        sprintf(str,"%-55s:0x%08x\n","LoaderFlags",ntoh.LoaderFlags);
        PrintMsg(str);
    }

    if(isD)
    {
        strcpy(str,"\n---------------------数据目录---------------------\n\n");
        PrintMsg(str);
        char* DataDirectory[50]=
            {"Export Directory"
            ,"Import Directory"
            ,"Resource Directory"
            ,"Exception Directory"
            ,"Security Directory"
            ,"Base Relocation Table"
            ,"Debug Directory"
            ,"COPYRIGHT/Architecture Specific Data"
            ,"RVA of GLOBALPTR"
            ,"TLS Directory"
            ,"Load Configuration Directory"
            ,"Bound Import Directory in headers"
            ,"Import Address Table"
            ,"Delay Load Import Descriptors"
            ,"COM Runtime descriptor"
            ,"Reserved Directory"
            };
        sprintf(str,"%-50s%-8s%7s%-8s\n","名称","地址","","大小");
        PrintMsg(str);
        for(DWORD i=0;i<ntoh.NumberOfRvaAndSizes;i++)
        {
            IMAGE_DATA_DIRECTORY cur=pe.GetDataDirectory(i);
            sprintf(str,"%-50s0x%08x%5s0x%08x\n",DataDirectory[i],cur.VirtualAddress,"",cur.Size);
            PrintMsg(str);
        }
        strcpy(str,"\n-------------------数据目录-结束------------------\n\n");
        PrintMsg(str);
    }
    strcpy(str,"\n-------------------------NT可选头信息-结束------------------------------\n\n");
    PrintMsg(str);
}

///对应-i [i][j]
void MsgOfImport(int i,int j,bool isSingle=1)
{
    char str[10000];
    if(isSingle)
    {
        sprintf(str,"%s.%s( address/ordinal= 0x%08x)\n",
            pe.RVAtoRAW(pe.GetImportDescriptor(i).Name)+pe.p_buffer,
            pe.GetImprotFunctionName(i,j),
            pe.GetImprotFunctionAddress(i,j)
            );
    }
    else
    {
        sprintf(str,"%s.%s",
                pe.RVAtoRAW(pe.GetImportDescriptor(i).Name)+pe.p_buffer,
                pe.GetImprotFunctionName(i,j)
                );
        for(int i=0;str[i];i++)
            if(str[i]<0)
            {
                strcpy(str,"未知的函数名,请通过序号/地址识别函数");
                break;
            }
        sprintf(str,"%-50s0x%08x\n",
            str,
            pe.GetImprotFunctionAddress(i,j)
            );
    }

    PrintMsg(str);
}
void MsgOfImport(int i)
{
    char str[10000];
    IMAGE_IMPORT_DESCRIPTOR cur=pe.GetImportDescriptor(i);
    sprintf(str,"库名:%-50s\n", pe.RVAtoRAW(cur.Name)+pe.p_buffer);
    PrintMsg(str);
    size_t l_int=pe.GetINTLength(i),l_iat=pe.GetIATLength(i);
    sprintf(str,"INT长度:0x%08x(%d),IAT长度:0x%08x(%d)\n\n",l_int,l_int,l_iat,l_iat);
    PrintMsg(str);
    sprintf(str,"%-50s%-08s\n","函数名","地址/编号");
    PrintMsg(str);
    for(int j=0;j<l_int;j++)
        MsgOfImport(i,j,0);
}
void MsgOfImport()
{
    int sz=pe.GetImportDescriptorNums();
    for(int i=0;i<sz;i++)
    {
        MsgOfImport(i);
        PrintMsg("\n\n");
    }
}

///对应-e [i]
void MsgOfExport(int i,bool isSingle=1)
{
    char str[10000];
    DWORD address,ordinal;
    char* name=pe.GetExportMsg(i,address,ordinal);
    if(isSingle)
    {
        sprintf(str,"%s( address = 0x%08x , ordinal = 0x%08x (%d) )\n",name?name:"无法识别的函数名/函数不存在",address,ordinal,ordinal);
        PrintMsg(str);
    }
    else
    {
        sprintf(str,"%-50s0x%08x%10s0x%08x (%d)\n",name?name:"无法识别的函数名/函数不存在",address,"",ordinal,ordinal);
        PrintMsg(str);
    }
}
void MsgOfExport()
{
    size_t sz=pe.GetExprotFunctionNums();
    if(sz==0)
        PrintMsg("该PE文件不存在EAT!\n");
    else
    {
        for(int i=0;i<sz;i++)
            MsgOfExport(i,0);
    }
}

///对应-s [i]
void MsgOfSection(int i)
{
    IMAGE_SECTION_HEADER cur=pe.GetGetSectionHeader(i);
    char str[10000];
    PrintMsg("\n\n");
    sprintf(str,"%-50s: %s\n","节区名(Name)",cur.Name);
    PrintMsg(str);
    sprintf(str,"%-50s: 0x%08x\n","节区大小(VirtualSize)/物理地址(PhysicalAddress)",cur.Misc.VirtualSize);
    PrintMsg(str);
    sprintf(str,"%-50s: 0x%08x\n","节区RVA(VirtualAddress)",cur.VirtualAddress);
    PrintMsg(str);
    sprintf(str,"%-50s: 0x%08x\n","文件对齐尺寸(SizeOfRawData)",cur.SizeOfRawData);
    PrintMsg(str);
    sprintf(str,"%-50s: 0x%08x\n","文件偏移(PointerToRawData)",cur.PointerToRawData);
    PrintMsg(str);
    sprintf(str,"%-50s: 0x%08x\n","重定位偏移(PointerToRelocations)",cur.PointerToRelocations);
    PrintMsg(str);
    sprintf(str,"%-50s: 0x%08x\n","行号表偏移(PointerToLinenumbers)",cur.PointerToLinenumbers);
    PrintMsg(str);
    sprintf(str,"%-50s: 0x%04x\n","重定位数目(NumberOfRelocations)",cur.NumberOfRelocations);
    PrintMsg(str);
    sprintf(str,"%-50s: 0x%04x\n","行号表数目(NumberOfLinenumbers)",cur.NumberOfLinenumbers);
    PrintMsg(str);
    sprintf(str,"%-50s: 0x%08x\n","属性(Characteristics)",cur.Characteristics);
    PrintMsg(str);
    PrintMsg("\n\n");
}
void MsgOfSection()
{
    int sz=pe.NumberOfSections();
    printf("节区数量:%d\n\n",sz);
    for(int i=0;i<sz;i++)
        MsgOfSection(i);
}

///对应-h/-?
void PrintHelp()
{
    puts("---------------------------------------------------------------------");
    puts("-h/-?                         查看帮助");
    puts("-q                            退出程序");
    puts("-l filenname                  打开名为filename的PE文件");
    puts("-f filename                   从当前操作起把输出写在文件中(原文件(如果存在)内容会被覆盖)");
    puts("-m dos/ntfh/ntoh  [main] [d]  显示DOS头/NT文件头/NT可选头信息,main参数:只显示主要信息.d:显示NT可选头的地址数据目录");
    puts("-i [i][j]                     第i个导入库的第j个导入函数信息,不填写则显示全部");
    puts("-e [i]                        第i个导出函数信息,不填写则显示全部");
    puts("-s [i]                        显示第i个节区信息,不填写则显示全部");
    puts("-cls                          清屏");
    puts("---------------------------------------------------------------------");
}

#include <string>
#include <queue>
using namespace std;

struct OpQueue:public queue<string>
{
    string front()
    {
        if(empty())
            return string("");
        return queue<string>::front();
    }
};

void RunOpList(OpQueue& opList)
{
    opList.push(string(""));
    while(!opList.empty())
    {
        string cur=opList.front();
        opList.pop();
        if(cur=="-l")
        {
            cur=opList.front();
            opList.pop();
            LoadPEFile(cur.c_str());
        }
        if(cur=="-cls")
        {
            system("cls");
        }
        else if(cur=="-q")
        {
            ExitProgram();
        }
        else if(cur=="-h"||cur=="-?")
        {
            PrintHelp();
        }
        else if(cur=="-f")
        {
            cur=opList.front();
            opList.pop();
            PrintInFile(cur.c_str());
        }
        else if(cur=="-m")
        {
            cur=opList.front();
            opList.pop();
            if(cur=="dos")
            {
                cur=opList.front();
                if(cur=="main")
                {
                    opList.pop();
                    MsgOfDos(1);
                }
                else
                    MsgOfDos(0);
            }
            else if(cur=="ntfh")
            {
                cur=opList.front();
                if(cur=="main")
                {
                    opList.pop();
                    MsgOfNtfh(1);
                }
                else
                    MsgOfNtfh(0);
            }
            else if(cur=="ntoh")
            {
                cur=opList.front();
                bool isMain=0,isD=0;
                if(cur=="main")
                {
                    opList.pop();
                    isMain=1;
                }
                cur=opList.front();
                if(cur=="d")
                {
                    opList.pop();
                    isD=1;
                }
                MsgOfNtoh(isMain,isD);
            }
            else
            {
                puts("命令错误");
                return;
            }
        }
        else if(cur=="-i")
        {
            cur=opList.front();

            int i=-1,j=-1;
            if(cur[0]!=‘-‘&&cur!="")
            {
                opList.pop();
                sscanf(cur.c_str(),"%d",&i);
            }

            cur=opList.front();
            if(cur[0]!=‘-‘&&cur!="")
            {
                opList.pop();
                sscanf(cur.c_str(),"%d",&j);
            }

            if(i!=-1&&j!=-1)
                MsgOfImport(i,j);
            else if(i!=-1&&j==-1)
                MsgOfImport(i);
            else
                MsgOfImport();
        }
        else if(cur=="-e")
        {
            cur=opList.front();
            int i=-1;
            if(cur[0]!=‘-‘&&cur[0])
            {
                opList.pop();
                sscanf(cur.c_str(),"%d",&i);
            }
            if(i==-1)
                MsgOfExport();
            else
                MsgOfExport(i);
        }
        else if(cur=="-s")
        {
            cur=opList.front();
            int i=-1;
            if(cur[0]!=‘-‘&&cur[0])
            {
                opList.pop();
                sscanf(cur.c_str(),"%d",&i);
            }
            if(i==-1)
                MsgOfSection();
            else
                MsgOfSection(i);
        }
    }
}

void GetOpList(OpQueue& opList)
{
    opList=OpQueue();
    char str[10000];
    char *p=str;
    gets(str);
    for(int i=0;p[i];i++)
    {
        if(p[i]==‘\t‘||p[i]==‘\n‘||p[i]==‘\r‘||p[i]==‘ ‘)
        {
            p[i]=0;
            if(*p)
            {
                opList.push(string(p));
                p+=i+1;
            }
            i=0;
        }
    }
    if(*p)
    {
        opList.push(string(p));
    }
}

int main(int argc,char** argv)
{
    puts("                                                                      ");
    puts("----------------------PE解析器V1.0 by lc思念落叶----------------------");
    puts("                                                                      ");
    puts("                                                                      ");
    if(argc==1)
    {
        while(!pe.p_buffer)
        {
            OpQueue opList;
            printf("请使用-l filename指令读取PE文件\n");
            GetOpList(opList);
            RunOpList(opList);
        }
        PrintHelp();
    }
    else if(argc>1)
    {
        OpQueue opList;
        int loc=1;
        if(argv[1][0]!=‘-‘)
            LoadPEFile(argv[loc++]);
        for(int i=loc;i<argc;i++)
            opList.push(string(argv[i]));
        RunOpList(opList);
    }
    while(1)
    {
        OpQueue opList;
        GetOpList(opList);
        puts("---------------------------------------------------------------------");
        RunOpList(opList);
    }
}
时间: 2024-10-18 23:37:03

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

在32位PE文件中的任意一个节中添加代码

// SectionOp.cpp : 定义控制台应用程序的入口点. // /************************************************ *程序说明:在32位PE文件中的任意一个节中添加代码 *          第一个参数为PE文件 第二个参数为第N个节 * * 时间: 20170718 * Win10 VS2010 测试通过  ver 0.01 **************************************************/ #inc

Mp3tag(MP3文件信息修改器) V2.79a 多语绿色版

软件名称: Mp3tag(MP3文件信息修改器) 软件语言: 多国语言 授权方式: 免费软件 运行环境: Win 32位/64位 软件大小: 3.0MB 图片预览: 软件简介: Mp3Tag 是一款mp3文件id3-tag信息修改器.所谓id3-tag 信息,就是在mp3文件中加入曲名.演唱者.专集.年月.流派.注释等信息,便于您收集歌曲. mp3tag是一款体积小巧功能强大简单易用的音频文件标签(元数据)编辑软件.它支持ID3v1, ID3v2.3, ID3v2.4, iTunes MP4,

vbs-计算机硬件信息查看器-源码-.exe程序-可直接使用复制使用

vbs-计算机硬件信息查看器-源码-可直接使用复制使用 #----------------------------------------------------------------------------------------以下为源代码 msgbox "               正在加载本机配置信息,请按确认继续!       ", 40, "配置信息查询" On Error Resume Next   SerVerPath = "c:\硬件

64位系统下注册32位dll文件

64位系统下注册32位dll文件 在64位系统里注册32位软件所需的一些dll会提示不兼容,大概因为32 位进程不能加载64位Dll,64位进程也不可以加载32的导致. 若要支持的32 位和64 位COM 注册和程序共存状态,需要WOW64 子系统. 故可以把这些32的dll.ax从C:\Windows\system32\复制到C:\Windows\sysWOW64\下注册即可. 如:regsvr32 C:\Windows\sysWOW64\MakerCom.dll 原文地址:https://w

32位Linux文件限制大小

线上程序不断重新启动,查看log发现是进程由于SIGXFSZ信号退出.对过大的文件进行操作的时候会产生此信号,一般仅仅在32位机器上出现,文件限制大小为2G.用lsof查看进程打开的文件,果然有一个文件达到2G. 解决方式:编译时加上參数:-D_FILE_OFFSET_BITS=64:代码中调用lseek时參数为off_t(不要为int或long,否则在32位和64位中表现不同). 附上一个链接,linux大文件支持:http://users.suse.com/~aj/linux_lfs.htm

win7旗舰版 32位 esd文件 590.2M

win7旗舰版 32位 链接: http://pan.baidu.com/s/1nvjJ3vF 密码: 1svg

Windows 7/8 64位系统 不能注册32位dll 文件的解决方案

这几天碰到一个问题,运行一个易语言开发的软件出现以下错误.我的系统是 Windows7 64 位 专业版.在系统盘 windows/system32  下查找 dm.dll.但是没有这个文件.于是我到百度去查找相关答案,问的人有很多,答案却是相同的,我断定这些都是复制来粘贴去的,都没有一个好的答案,有些更是离谱的发疯了.到百度知道提问,也是复制粘贴到,牛头不对马嘴. 错误信息:不能载入OCX组件 "Dm1.0版1.0版",其组件或类型库文件名为"dm.dll",数字

pdf文件内容查看器 -- 采用wpf开发

前言 pdf是一种应用非常广的版式文档格式,已成为事实上的国际标准.关于pdf格式的文章汗牛充栋,本文也是关于pdf格式的文章,但是本文不是纸上谈兵:本人这几周一直研究pdf格式内容,不但对pfd格式的内容有所了解,同时也写了一款软件,可以方便查看pdf文件内容.使用该软件,同时结合pdf相关文章,可以很快掌握pdf格式内容. 软件截图:软件下载地址 点我下载 pdf文件内容简要介绍 这里对pdf文件格式做个粗略介绍,只有了解了这些内容,才能知道如何使用该软件. pdf文档总结构如下: 1)he

WinLister(进程窗口信息查看器)

软件简介: 此实用程序会显示在您的系统上打开的窗口的列表.对于每个窗口,显示一些有用的信息:标题.窗口的句柄.位置.大小.类名.进程.创建该窗口的程序的名称,以及更多...此外,你可以很容易地隐藏,显示或关闭选定的窗口,或保存窗口列表到文本文件或HTML文件. 图片预览: 下载地址:http://dickmoore.cn/Down/winlister.zip