PE文件格式详解(4)

来源:互联网 发布:scratch创意编程 pdf 编辑:程序博客网 时间:2024/06/06 11:48
1.RVA to RAW
    PE文件加载到内存时,每个节区都要准确完成内存地址与文件偏移的映射。这种映射便称为RVA to RAW,实现这个过程需要经过以下的步骤。
        1.查找RVA所在节区。
        2.使用公式计算出文件偏移。
        根据IMAGE_SECTION_HEADER结构体,换算公式如下。
        RAW - PoniterToRawData = RVA - VirtualAddress
                                           RAW  = RVA - VirtualAddress + PointerToRawData
 2.IAT(Import Address Table,导入地址表)
   IAT保存的内容与Windows操作系统的核心进、内存、DLL结构等有关。(即掌握了IAT便掌握了Windows操作系统的根基)。

    1.DLL(Dynamic Linked Library)
        加载DLL的方式有两种:一种是“显式链接”(Explicit Linking),程序使用DLL时加载,使用完毕后释放内存。另一种是“隐式链接”(Implicit Linking),程序开始时遍一同加载DLL,程序终止时,再释放占用的内存。IAT提供的机制便与隐式链接有关。
    DLL重定位,DLL文件的ImageBase一般为10000000.比如某个程序使用a.dll和b.dll,OE装载器先把a.dll装载到内存的10000000(ImageBase)处,然后尝试把b.dll也装载到该处。但是由于该地址处已经装载了a.dll,所以PE装载器需要查找其他空白的内存空间(ex:3E000000),然后将b.dll装载进去。这就是DLL文件的重定位。
    2.IMAGE_IMPOT_DESCRIPTOR
        IMAGE_IMPORT_DESCRIPTOR结构体中记录着PE文件要导入哪些库文件。IMAGE_OPTIONAL_HEADER32.DataDirectory[1].VirtualAddress的值即是IMAGE_IMPORT_DESCRIPTOR结构体数组的起始地址(RVA值)。(第一个4字节为虚拟地址,第二个4字节为Size成员。)
          注:Import:导入,向库提供服务(函数)。
                  Export:导出,从库向其他PE文件提供服务(函数)。
 
代码 IMAGE_IMPORT_DESCRIPTOR

typedef struct _IMAGE_IMPORT_DESCRIPTOR{
    union{
        DWORD    Characteristics;
        DWORD    OriginalFirstThunk;        //INT(Import Name Table) address (RVA)
    };
    DWORD    TimeDatastamp;
    DWORD    ForwarderChain;
    DWORD    Name;                                // library name string address (RVA)
    DWORD    FirstThunk;                         // IAT( Import Address Table) address (RVA)
    } IMAGE_IMPORT_DESCRIPTOR;

typedef struct _IMAGE_IMPORT_BY_NAME{
    WORD    Hint;                                     // ordinal
    BYTE       Name[1];                              // function name string
     } IMAGE_IMPORT_BY_NAME , *PIMAGE_IMPORT_BY_NAME;

   执行一个普通程序时往往需要导入多个库,导入多少库就存在多少个IMAGE_IMPORT_DESCRIPTOR结构体,这些结构体形成了数组,且结构体数组最后以NULL结构体结束。
  IMAGE_IMPORT_DESCRIPTOR的重要成员如下
                            项目                            含义
            OriginalFirstThunk        INT的地址(RVA)
                    Name                      库名称字符串的地址(RVA)
            FirstThunk                      IAT的地址(RVA)
注:INT与IAT是长整型(4个字节数据类型)数组,以NULL结束(未另外明确指出大小)。
        INT中各元素的值为IMAGE_IMPORT_BY_NAME结构体指针(有时IAT也有相同的值)。
        INT与IAT的大小应相同。
3.EAT
   Windows操作系统中,“库”是为了方便其他程序调用而集中包含相关函数的文件(DLL/SYS)。Win32 API是最具代表性的库,其中的kernel32.dll文件称为最核心的库文件。
    EAT是一种核心机制,它使不同的应用程序可以条用库文件中提供的函数(即只有通过EAT才能准确求得从相应库中导出函数的起始地址)。PE文件内部有且仅有一个用来说明库EAT的IMAGE_EXPORT_DIRECTORY结构体,并且保存着导出信息。 
    注:IAT的结构体以数组的形式存在,且拥有多个成员。即说明PE文件可以同时导入多个库。
    可以在PE文件的PE头中查找到IMAGE_EXPORT_DIRECTORY结构体的闻之。IMAGE_OPTIONAL_HEADER32.DataDirectory[0].VirtualAddress值即为结构身体数组的其实地址(RVA值)。(第一个4字节为虚拟地址,第二个4字节为Size成员。)
    
   代码  IMAGE_EXPORT_DIRECTORY结构体
    typedef struct _IMAGE_EXPORT_DIRECTORY {
        DWORD    Characteristics;
        DWORD    TimeDateStamp;            //creation time date stamp
        WORD      MajorVersion;
        WORD      MinorVersion;
        DWORD   Name;                            //address of library file neme
        DWORD   Base;                              //ordinal base
        DWORD   NumberOfFunctions;     //number of functions
        DWORD   NumberOfNames;        //number of names
        DWORD   AddressOfFunctions;    //address of function start address array
        DWORD   AddressOfName;          //address of function name string array
        DWORD   AddressOfNameOrdinals;   //address of ordinal array
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

其中结构体中的重要成员如下
               项目                                       含义        
NumberOfFunctions                实际Export函数的个数
NumberOfNames                     Export函数中具名的函数个数
AddressOfFunctions                Export函数地址数组(数组元素个数=NumberOfFunctions
AddressOfNames                     函数名称地址数组(数组元素个数=NumberOfNames
AddressOfNameOrdinals        Ordinal地址数组 (数组元素个数=NumberOfNames)
原创粉丝点击