首页
社区
课程
招聘
[讨论]正在研究PE结构,欢迎大家讨论。
发表于: 2007-10-20 08:49 9496

[讨论]正在研究PE结构,欢迎大家讨论。

2007-10-20 08:49
9496


本想跟在那个贴后面的,也许,我想没人会理了。就新开了一个贴!如果有什么不当的地方,就别在意了。。。。。。。。


正好我也在研究PE结构,我把我的看发贴出来,顺便请把你的问题再解释的清楚点。

我专门找了点专业点的:
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;

这个结构就是MS的定义,它的意思是文件头,MS在NT头是分了三部分的。
下面是属性头,根据MS的结构来看我们知道的不很清楚了,我想kmyc朋友是NumberOfRvaAndSizes
对这个的怀疑??我记得,从我研究PE结构开始它的值好象一直为0x10字节。如果这个可再大点,我就不知道了,再小点我想是不可能的了。看我后面的解释!
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;

根据MS的结构定义很难看出来PE头和文件的联系:

//-----------------------------------------------------------------------------------------

//下面是我自己写的PE头结构,我就不明白了,我这个结构是F8字节,后面紧跟的就是区段列表了.
//实际我以前的读PE头很简单,三次ReadFile就能搞定了,我知道的PE结构内部里,这些项目都是基本具备的
//如果真要说那个一项没有也可以,我就郁闷了,也许我学的还不好要继续修行了.
//也许楼主说的不明白我也看了好几遍没能觉得楼主说的是什么???
//我们可以肯定的是,NT头大小是F8字节,如果有朋友想知道为什么?那就可以算,DWORD是4字节,WORD是2字节,BYTE是1个字节
//而我也可以肯定的说,从_38NumberOfRvaAndSizes这个之后确实是0x80字节.至少,我的程序都是这样的,感觉MS的结构不清楚,
//所以,自己写了个.但是我这样写也没出什么错误.

struct _DLLHEADINFO_PESIG{

        DWORD           _01PESignature;             // (PE)50450000
        WORD            _02Machine    ;             //= IMAGE_FILE_MACHINE_I386
        WORD            _03NumberOfSections;        // = 5
        DWORD           _04TimeDateStamp   ;        // = 46AD3FF8
        DWORD           _05PointerToSymbolTable;    // = 0
        DWORD           _06NumberOfSymbols ;        //= 0
        WORD            _07SizeOfOptionalHeader;    // = E0 (224.)
        WORD            _08Characteristics ;        //=

DLL|EXECUTABLE_IMAGE|32BIT_MACHINE|LINE_NUMS_STRIPPED|LOCAL_SYMS_STRIPPED
        WORD            _09MagicNumber     ;        //= PE32
        BYTE            _10MajorLinkerVersion;      //= 6
        BYTE            _11MinorLinkerVersion;      // = 0
        DWORD           _12SizeOfCode        ;      // = D000 (53248.)
        DWORD           _13SizeOfInitializedData  ; //= D000 (53248.)
        DWORD           _14SizeOfUninitializedData; // = 0
        DWORD           _15AddressOfEntryPoint    ; //= 54C1
        DWORD           _16BaseOfCode      ;        //= 1000
        DWORD           _17BaseOfData      ;        //= E000
        DWORD           _18ImageBase       ;        //= 10000000
        DWORD           _19SectionAlignment;        // = 1000
        DWORD           _20FileAlignment   ;        //= 1000
        WORD            _21MajorOSVersion  ;        //= 4
        WORD            _22MinorOSVersion  ;        //= 0
        WORD            _23MajorImageVersion;       // = 0
        WORD            _24MinorImageVersion;       // = 0
        WORD            _25MajorSubsystemVersion;   // = 4
        WORD            _26MinorSubsystemVersion;   // = 0
        DWORD           _27Reserved             ;
        DWORD           _28SizeOfImage   ;          //= 1B000 (110592.)
        DWORD           _29SizeOfHeaders ;          //= 1000 (4096.)
        DWORD           _30CheckSum      ;          // = 0
        WORD            _31Subsystem     ;          //= IMAGE_SUBSYSTEM_WINDOWS_GUI
        WORD            _32DLLCharacteristics;      // = 0
        DWORD           _33SizeOfStackReserve;      //= 100000 (1048576.)
        DWORD           _34SizeOfStackCommit ;      //= 1000 (4096.)
        DWORD           _35SizeOfHeapReserve ;      //= 100000 (1048576.)
        DWORD           _36SizeOfHeapCommit  ;      //= 1000 (4096.)
        DWORD           _37LoaderFlags       ;      //= 0
        DWORD           _38NumberOfRvaAndSizes;     // = 10 (16.)
        DWORD           _39ExportTableAddress ;     //= F800
        DWORD           _40ExportTableSize    ;     //= 67 (103.)
        DWORD           _41ImportTableAddress ;     //= EC38
        DWORD           _42ImportTableSize    ;     //= 8C (140.)
        DWORD           _43ResourceTableAddress;    // = 16000
        DWORD           _44ResourceTableSize   ;    // = 21E8 (8680.)
        DWORD           _45ExceptionTableAddress;   // = 0
        DWORD           _46ExceptionTableSize   ;   //= 0
        DWORD           _47CertificateFilePointer;  // = 0
        DWORD           _48CertificateTableSize  ;  // = 0
        DWORD           _49RelocationTableAddress;  // = 19000
        DWORD           _50RelocationTableSize   ;  //= B54 (2900.)
        DWORD           _51DebugDataAddress      ;  //= 0
        DWORD           _52DebugDataSize         ;  //= 0
        DWORD           _53ArchitectureDataAddress; // = 0
        DWORD           _54ArchitectureDataSize   ; //= 0
        DWORD           _55GlobalPtrAddress       ; //= 0
        DWORD           _56Mustbe                 ; //0
        DWORD           _57TLSTableAddress        ; // = 0
        DWORD           _58TLSTableSize           ; //= 0
        DWORD           _59LoadConfigTableAddress ; //= 0
        DWORD           _60LoadConfigTableSize    ; //= 0
        DWORD           _61BoundImportTableAddress; // = 0
        DWORD           _62BoundImportTableSize   ; // = 0
        DWORD           _63ImportAddressTableAddress ; //= E000
        DWORD           _64ImportAddressTableSize    ; //= 230 (560.)
        DWORD           _65DelayImportDescriptorAddress ; //= 0
        DWORD           _66DelayImportDescriptorSize    ; // = 0
        DWORD           _67COMRuntimeHeaderAddress     ; // = 0
        DWORD           _68ImportAddressTableSize       ; //= 0
        DWORD           _69Reserved                     ;
        DWORD           _70Reserved                     ;
};

//---------------------------下面是我自己的读PE头的代码------------------

        //DOS结构:
        BYTE dsbuf[0x1000]={0};   //初始化一个字节数组存放PE头
        m_pnFiles.ReadFiles(0x00,dsbuf,sizeof(_DLLHEADINFO_DOSSIG));  //读DOS头部分
        memset(&_hiDosSig,0,sizeof(_DLLHEADINFO_DOSSIG));             //原结构清空
        memcpy(&_hiDosSig,dsbuf,sizeof(_DLLHEADINFO_DOSSIG));         //将内容初始化结构
        for(int m=0,n=0;m<n_dsSig;m++,n=n+0x02)
        {
                _addrHeadInfo._01AddrDOSSIG[m]=n;
                _addrHeadInfo._01sAddrDOSSIG[m].Format("0x%08X",n);
        }

        //PE 偏移量:
        memset(dsbuf,0,0x1000);       //数组清空
        memset(&_hiOffsetSig,0,sizeof(_DLLHEADINFO_OFFSETSIG));
        m_pnFiles.ReadFiles(sizeof(_DLLHEADINFO_DOSSIG),dsbuf,sizeof(_DLLHEADINFO_OFFSETSIG)); //从DOS头大小的地方开始读
        memcpy(&_hiOffsetSig,dsbuf,sizeof(_DLLHEADINFO_OFFSETSIG));  //初始化结构
        for(int m=0,n=sizeof(_DLLHEADINFO_DOSSIG);m<n_OffsetSig;m++,n=n+0x04)
        {
                _addrHeadInfo._02AddrOFFSETSIG[m]=n;
                _addrHeadInfo._02sAddrOFFSESIG[m].Format("0x%08X",n);
        }

        //PE 结构:
        memset(dsbuf,0,0x1000);   //数组清空
        memset(&_hiPESig,0,sizeof(_DLLHEADINFO_PESIG));  //结构清空
        m_pnFiles.ReadFiles(_hiOffsetSig._8OffsetSignature,dsbuf,sizeof(_DLLHEADINFO_PESIG));  //从偏移量指定的地方读NT头
        memcpy(&_hiPESig,dsbuf,sizeof(_DLLHEADINFO_PESIG));
        //上面这里读的就是我前面贴出来的哪个结构.

        //区段信息:
            DWORD seek=_hiOffsetSig._8OffsetSignature+sizeof(_DLLHEADINFO_PESIG); //计算区段位置=偏移量+NT结构头长度(我自己的结构,MS那个不行!),
        for(int i=0;i<_hiPESig._03NumberOfSections;i++)
        {
                memset(dsbuf,0,0x1000);
                memset(&_hiSection[i],0,sizeof(_DLLHEADINFO_SECTIONS));
                m_pnFiles.ReadFiles(seek,dsbuf,sizeof(_DLLHEADINFO_SECTIONS));
                memcpy(&_hiSection[i],dsbuf,sizeof(_DLLHEADINFO_SECTIONS));
                seek=seek+sizeof(_DLLHEADINFO_SECTIONS);   //当前位置加区段头长度,为下个区段头位置;
        }

//看到上面的代码我真的觉得PE头是个死格式,但是,Kmyc朋友说的78和80是什么问题,能不能解释的清楚点!

//实在是搞不懂,到底你说的那有问题!!!!!!!!!!!!!

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (15)
雪    币: 235
活跃值: (17)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
2
其实我的意思很简单,有些钻牛角尖。就是关于NumberOfRvaAndSizes的

30)接着我们会发现32位的“NumberOfRvaAndSizes(Rva数和大小)”,它是紧随其后的目录的有效项的数目。我已发现此值不可靠;你也许希望用常量IMAGE_NUMBEROF_DIRECTORY_ENTRIES(映象文件目录项数目)来代替它,或者用它们中的较小者。

我想kmyc朋友是NumberOfRvaAndSizes
对这个的怀疑??我记得,从我研究PE结构开始它的值好象一直为0x10字节。如果这个可再大点,我就不知道了,再小点我想是不可能的了。看我后面的解释!


PE文件头格式里有很多在现在看来是被废掉的域,我很奇怪既然NumberOfRvaAndSizes总是10h,那为什么要给它保留空间,每个PE文件都为这些“废域”保留空间。有可能:
1,在设计之初,这个域是有用的,可是后来被废掉了。
2,现在这个域暂时是常量,以后可能就会变化,这是保留给以后用的。
PE文件头的定位很重要,NumberOfRvaAndSizes域后面那个数组到底应该算多少个?算10h个,现在看来不会出错的。算NumberOfRvaAndSizes个,从你的描述来看(它的值好象一直为0x10),也没有什么问题。不过《PE格式注释》好像意思是算NumberOfRvaAndSizes个会有问题“我已发现此值不可靠……或者用它们中的较小者”。

如果这个域像我想象的可能是保留给以后用的,比如Vista或者别的什么,那么直接用10h代替是否会出问题就要打一个问号了。

请原谅我废话了这么多,也许这本不该是个问题的,纯粹是我钻牛角尖。
2007-10-20 10:57
0
雪    币: 3758
活跃值: (3337)
能力值: ( LV15,RANK:500 )
在线值:
发帖
回帖
粉丝
3
可以不为$10,最小要保留导入表和导出表, 也就是2.

顺序便可以看出这是2个所谓平等目录中的不平等成员了.
查阅MS的文档,
Note that the number of directories is not fixed. Before looking for a specific directory, check the NumberOfRvaAndSizes field in the optional header.

请留意数据目录的数量不是固定的, 在你获取指定的目录前, 检查optional header中NumberOfRvaAndSizes字段的值.

http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
2007-10-20 13:20
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
NumberOfRvaAndSizes 为1也是可以的哦,貌似有比较多人认为它最小是2,好象我看到过为1程序也呼呼的跑起来了

本应该它最大是16的,不过你让它大于16也是可以的,程序还是呼呼的跑,不过这个时候你用OD一加载,就会MessageBox下,至于它最大可以是多少,偶不知,希望知道的人冒个泡
2007-10-20 13:34
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
5
服了,不知道你们在钻什么,说得很清楚了就是用PEHeader+18h+SizeOfOptinalHeader定位SectionHeaders

钻吧,使劲钻。
2007-10-20 13:47
0
雪    币: 3758
活跃值: (3337)
能力值: ( LV15,RANK:500 )
在线值:
发帖
回帖
粉丝
6
为2就是为了要使用导入表
无导入表的程序要跑也只能穷那个Kernel32了.
试过了无导入表的程序, 这个可以减为0, 可以跑...

最大应该跟可载入PE文件大小有关, 假设其他区段大小都忽略, 应该是sizeofimage最大值mod数据目录的记录项大小, 每个记录大小为8, 则是$1F FF FF FF项, 再减去前面的必须的字段mod8的值.
2007-10-20 13:48
0
雪    币: 3758
活跃值: (3337)
能力值: ( LV15,RANK:500 )
在线值:
发帖
回帖
粉丝
7
SizeOfOptionalHeader的值不可与这个参与计算的结果矛盾, 不然会被和谐....

只是为了解决一些误解, PE结构如何取目录项不是试出来的, 反正有资料可以看, 么必要去猜测
2007-10-20 13:51
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
8
#OfRvas可以减少,就不注册,注册多了OS也不管你
2007-10-20 14:11
0
雪    币: 3758
活跃值: (3337)
能力值: ( LV15,RANK:500 )
在线值:
发帖
回帖
粉丝
9
例如你减少optional header的值, 并且挪好文件, 将datadirectionay的后面几项或者全部空间征做他用(在你确保这些项你不使用的前提下), 如果不保证numberofrvaandsize这个个数是相应减少的, 那么载入时候, 就会啾啾啾, 应用程序xxxxx初始化失败/应用程序xxxx不是有效的xxx(2k/2k3), 或者是宫, 与系统连接的一个或多个设备不能运转(9x).

反之呢, 如果一个程序size of ova and size和optional header都是正确的, 并且数量简直就是0, 那么有人利用楼主的类获取了各个目录后, 继续查询目录下面的入口项, 就会喵的, 自我和谐了.

写程序是一回事, 但是提供类给别人用, 就尽量使用文档化的方法, 而不是经验法则和归纳规律, 以上.
2007-10-20 14:26
0
雪    币: 1657
活跃值: (291)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
10
我还是希望标准点好,至于,楼上几位朋友说的我也试了一下!好象不要资源表不要导入表,也能正常运行,这个我想并不能说明什么吧!那个程序,还算是PE结构的程序,还是算DOS类程序。我看的资料上说从95开始,MS才把可执行文件规范化!很多程度上都是结合了APPLE或LINUX,才做的,至于具体的,还是要问微软了。也许很多相关的是由于借鉴的问题了。

不过,WINDOWS的异常处理会把许多问题代替处理掉,至于没有表项的程序,我想兼容一定是问题!

说的不好别笑话,个人看法!
2007-10-20 14:53
0
雪    币: 3758
活跃值: (3337)
能力值: ( LV15,RANK:500 )
在线值:
发帖
回帖
粉丝
11
怎么感觉你看的是一部野史....
2007-10-20 15:03
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
12
兰陵某某某写的,文档化得不好。
2007-10-20 15:22
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
我来学习
2007-10-20 18:37
0
雪    币: 230
活跃值: (149)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
一起学习,学习。
2007-12-7 15:20
0
雪    币: 233
活跃值: (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
收藏了,PE结构里的学问太多了。
2007-12-8 11:25
0
雪    币: 442
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
一点不懂
2007-12-8 13:06
0
游客
登录 | 注册 方可回帖
返回
//