• PE文件格式详解(六)


    0x00 前言

      前面两篇讲到了输出表的内容以及涉及如何在hexWorkShop中找到输出表及输入DLL,感觉有几个地方还是没有理解好,比如由数据目录表DataDirectory[16]找到输出表表后以为找到输入DLL就完了,其实这一流程的最终功能是通过输入DLL找到输入DLL调用的函数,这一步骤是通过输出表结构中的OriginalFristThunk或者OriginalFristThunk所指向的INT或者IAT结构来找到的。这里要说明的是,虽然一般情况通过OriginalFristThunk也行,但是有些情况下它的值被设置为0了,这样就无法利用了,最委托的的方式是通过FristThunk所指向的IAT表来找寻。下面来通过实例实践这一过程。

    0x01 找寻输入DLL以及输入DLL调用的函数

       材料及工具:名为PE.exe的可执行文件,工具hexWrokshopLordPE

       思路:找到PE文件头——》找到数据目录表第二项——》通过地址转换找到输出表数组——》逐个读出输出表数组的OriginalFristThunkFristThunk值——》通过INT或者IAT逐个读出被调用函数的名字地址——》通过名字地址找到函数名。

    1)将目标文件拖入hexWrokShop,快捷键ctrl+g跳往载入地址的3ch处,这里即PE文件头地址,如下图:

     2)跳往40h处,该处即为文件头,如下图:

    3)跳往PE文件头+80h处,该处存储了输入数据表的地址如下图:

    4)RVA=2040h转化位FileOffset地址,这里我们利用lordpe协助转化,转化后值为440h。

    5)跳转至440h处,该处即为输出表IID数组的数据所在,每项为五对双字组成,结尾以五对双字0。我这个实例一共两组,如下图:

     将以上根据字段数据统计如下表(PS:由于hex中是由低位到高位的故统计时应该注意高低位的换位):

    OriginalFristThunk

    TimeStamp

    ForwardChain

    Name

    FristThunk

    0000208C

    00000000

    00000000

    00002174

    00002010

    0000207C

    00000000

    00000000

    000021B4

    00002000

    利用表中的Name字段我们可以直接推出输入DLL的名字,第一项NameRVA2174h,转化为FileOffset值为:574h,跳往574h,我们可以看到第一个DLLUSER32.DLL,如下图:

     第二项的Name值为RVA值为21B4h,转化位FileOffset值为5B4h,跳往574h,我们知道第二项DLLKERNEL32.DLL,如下图:

     

    6)知道了输入DLL不是我们目的终点,我们还要知道DLL所调用的所有函数名字地址,这里有两个字段可用,第一个是OriginalFristThunk,它所指向的是一个名为输入名称表(INT)的结构,这个结构是由多个IMAGE_THUNK_DATA结构所组成的数组。第二个是FristThunk,它所指向的是一个名称为输入地址表的(IAT)的结构,这个结构也是有多个IMAGE_THUNK_DATA结构所组成的数组。IMAGE_THUNK_DATA双字数组的每项指向另一个结构——IMAGE_IMPORT_BY_NAME。最终通过IMAGE_IMPORT_BY_NAME找到被DLL调用的函数。一般而言,这两个被指向的数组值是相等的。我们接下来分别用两个字段来查找。我们先用第一项的OriginalFristThunk来试试,将208C转化为FileOffset48ch。掉跳往48ch,的如下图结果,共十一项,以双字0结尾。

    我们用FristThunk来试试,将2010h转化为FileOffset410h,跳往410h,可得下图:

     它们的值都为:

    102100001C210000F4200000E0200000502100006421000002210000CE200000BC2000002E21000042210000,将数据按八个字节拆分与翻转的下表:

        第一项指向的IAMGE_THUNK_DATA数组

    00002110

    0000211C

    000020F4

    000020E0

    00002150

    00002164

    00002102

    000020CE

    000020BC

    0000212E

    00002142

    接下来进行地址转换,的下表:

    510

    51c

    4f4

    4e0

    550

    564

    502

    4ce

    4bc

    52e

    542

    7)由上表逐个查询出被调用函数名,如下图:

    重复以上操作的下表:

    RVA

    FileOffset

    Hint

    函数名

    00002110

    510

    019B

    LoadIconA

    0000211C

    51c

    01DD

    PostQuitMessage

    000020F4

    4f4

    0128

    GetMessageA

    000020E0

    4e0

    0094

    DispatchMessageA

    00002150

    550

    027D

    TranslateMessage

    00002164

    564

    028B

    UpdateWindow

    00002102

    502

    0197

    LoadCursorA

    000020CE

    4ce

    0083

    DefWindowProcA

    000020BC

    4bc

    0058

    CreateWindowExA

    0000212E

    52e

    01EF

    RegisterClassExA

    00002142

    542

    0265

    ShowWindow

    8)当然你可能会觉得这样找输入表实在太麻烦了,确实是,但是只有经过这样找你才能弄明白输出表到底是如何存放的转换的,从而对PE文件格式有更为透彻理解。接下来我们通过强大的lordPE来轻松查找到输入表和输入函数。如下图:

     0x02 总结

      这两天看加密与解密收获很大,对于对逆向破解的朋友我强烈建议读一读此书,有相同兴趣的朋友欢迎评论留言交流。

  • 相关阅读:
    点击图片显示原图
    SQL判断语句
    窗口淡入淡出效果
    判断两段时间之间的时间差
    软件行业发展趋势
    VSS客户端不能访问问题“unable to open user login file\\服务器项目管理目录\data\logedin\用户名.log ”
    鑫哥儿子顺利降生了!
    面向对象原则之单一职责原则实现
    PHP编码,乱码问题
    泛型中的default(T)
  • 原文地址:https://www.cnblogs.com/2f28/p/9824366.html
Copyright © 2020-2023  润新知