maikehong 发表于 2023-8-10 00:25:38

PE导入表起步实操

本帖最后由 maikehong 于 2023-8-10 13:15 编辑

USER32.dll:
                173a8= 74 78 01 00 AC 78 01 00        
                是00开头的
       
       
MFC42D.DLL:
                170ac= 76 0E 00 80 .... .... .... ....
                是80开头的

MSVCRTD.dll:
               17328=是00开头的

KERNEL32.dll:
         17078=是00开头的

MFCO42D.DLL:
                172f8= 是00开头的



1 data_DLL目录表:       

        IMAGE_DATA_DIRECTORY{
                        0x00 DWORD VirtualAddress-->地址中包含各种DLL 每个dll占20个字节 最后以20个字节0结尾
                        0x04 DWORD Size
        }

                                                                                                           A8 73 01 00       
                                0 00 00 00 00 00 00 00 0088 78 01 00 08 77 01 00

2 DLL结构:

                IMAGE_IMPORT_DESCRIPTOR STRUCT{                         20个字节
                        union{
                                Characteristics;                           DWORD 1
                                OriginalFirstThunk;              &&                DWORD//RVA指向 IMAGE_THUNK_DATA 结构数组【用这个】
                        };
                        TimeDateStamp;                                    DWORD 2 //时间戳
                        ForwarderChain;                              DWORD 3
                        Name;                           &&      DWORD 4 //RVA指向依赖的dll名字,该名字以0结尾
                        FirstThunk;                     &&      DWORD 5 //RVA指向 IMAGE_THUNK_DATA 结构数组

                }IMAGE_IMPORT_DESCRIPTOR;

                173a8                OriginalFirstThunk;              &&                DWORD//RVA指向 IMAGE_THUNK_DATA 结构数组【用这个】
                17888               DWORD 4         RVA指向依赖的dll名字,该名字以0结尾
                17708               DWORD 5         RVA指向 IMAGE_THUNK_DATA 结构数组               



3OriginalFirstThunk --->指向 INT表(这个表中存放[最高位不是0的话]是函数地址看得到ASCII码):

                        74 78 01 00 AC 78 01 00

                INT表_ 导入名称表
                IMAGE_THUNK_DATA                        4个字节
                IMAGE_THUNK_DATA                        4个字节
                00 01 78 74h                                4个字节
                00 01 78 AC                                        4个字节
                ......
                (以四个字节00结束)                                                                                       

                表里面每个成员的结构如下:
                INT表_每个成员结构: 4个字节
               
                        typedef struct_IMAGE_THUNK_DATA32 {
                                unon{
                                                PBYTE ForwarderString;
                                                PDWORD Function;               
                                                DWORD Ordinal;                        //序号
                                                PIMAGE_IMPORT_BY_NAME AddressOfData; //指向IMAGE_IMPORT_BY_NAME
                                       }u1;
                                }IMAGE_THUNK_DATA32;

        实操如下:
       
                17874         =         GetSystemMetrics
                178AC        =        MessageBoxA


                        Offset      01234567   89ABCDEF               

                        00017870                     47 6574 53 79 73 74 65 6D 4D         GetSystemM
                        00017880   65 74 72 69 63 73 00                               etrics

                        000178A0                                        BE 01 4D 65               ?Me
                        000178B0   73 73 61 67 65 42 6F 7841 00 00 00 00 00 00 00   ssageBoxA      
                                                                                                                                       

4 FirstThunk-->一样(user.dll一样其他没查过)


=============================我亲爱的甲鱼大神笔记之乾坤大挪移 =========================================


我们得到 IMAGE_THUNK_DATA 结构的定义如下:

IMAGE_THUNK_DATA STRUC
        union u1
                ForwarderString       DWORD?              ; 指向一个转向者字符串的RVA
                Function                      DWORD?               ; 被输入的函数的内存地址
                Ordinal                     DWORD?               ; 被输入的API 的序数值
                AddressOfData         DWORD?              ; 指向 IMAGE_IMPORT_BY_NAME
        ends
IMAGE_THUNK_DATA ENDS

我们可以看出由于是union结构,所以IMAGE_THUNK_DATA 事实上是一个双字大小。
该结构在不同时候赋予不同的意义(伟大神奇不得鸟……)。其实union这种数据结构很容易理解:
说白了就是当时穷,能省就省,再说白了,就是几兄弟姐妹轮流穿一条裤子去相亲!理解了吧?哈哈


那我们怎么来区分何时是何意义呢?
规定如下:
        当 IMAGE_THUNK_DATA 值的最高位为 1时,表示函数以序号方式输入,这时候低 31位被看作一个函数序号。
        当 IMAGE_THUNK_DATA 值的最高位为 0时,表示函数以字符串类型的函数名方式输入,这时双字的值是一个 RVA,
                                指向一个 IMAGE_IMPORT_BY_NAME 结构


IMAGE_IMPORT_BY_NAME 结构
        仅仅只有一个字型数据的大小,存有一个输入函数的相关信息结构。其结构如下:
        IMAGE_IMPORT_BY_NAME STRUCT
                Hint      WORD    ?                 Hint 字段也表示函数的序号,不过这个字段是可选的,有些编译器总是将它设置为 0
                Name      BYTE      ?                定义了导入函数的名称字符串,这是一个以 0 为结尾的字符串
        IMAGE_IMPORT_BY_NAME ENDS



输入地址表(IAT)

        为什么由两个并行的指针数组同时指向 IMAGE_IMPORT_BY_NAME 结构呢?

                第一个数组(由 OriginalFirstThunk 所指向)是单独的一项,而且不能被改写,我们前边称为 INT。
                第二个数组(由 FirstThunk 所指向)事实上是由 PE 装载器重写的


好了,那么 PE 装载器的核心操作时如何的呢?这里就给大家揭秘啦~

        PE 装载器首先搜索 OriginalFirstThunk ,找到之后加载程序迭代搜索数组中的每个指针,
        找到每个 IMAGE_IMPORT_BY_NAME 结构所指向的输入函数的地址,
        然后加载器用函数真正入口地址来替代由 FirstThunk 数组中的一个入口,因此我们称为输入地址表(IAT)。

        所以,当我们的 PE 文件装载内存后准备执行时,刚刚的图就会转化为下图
        通过加载器之后 IAT里面的 IMAGE_THUNK_DATA 就成了 IAT里面 函数n的真正地址了 被覆盖了
        也就是说 IAT 在加载器之前是个变量














涛4091 发表于 2023-8-10 11:26:47

{:5_106:}
页: [1]
查看完整版本: PE导入表起步实操