吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 7787|回复: 10
收起左侧

[调试逆向] PE文件格式详细解析(二)--IAT

  [复制链接]
yaoyao7 发表于 2020-3-8 12:53
本帖最后由 yaoyao7 于 2020-3-8 16:37 编辑

PE文件格式详细解析(二)--IAT

IAT,导入地址表(Import Address Table),保存了与windows操作系统核心进程、内存、DLL结构等相关的信息。只要了理解了IAT,就掌握了Windows操作系统的根基。IAT是一种表格,用来记录程序正在使用哪些库中的哪些函数。

一、DLL

DLL,动态链接库(Dynamic Linked Library)

1. 来源

在16位的DOS环境中,不存在DLL的概念,例如在C中使用printf函数时,编译器会先从C库中读取相应函数的二进制代码,然后插入到应用程序中。但是Windows支持多任务,采用这种包含库的方式会没有效率,因为如果每个程序在运行时都将Windows库中的函数加载进来,将造成严重的内存浪费,因此引入了DLL的概念。

2. 设计理念

  1. 不把函数库包含进应用程序中,单独组成DLL文件,在需要使用时再进行调用。
  2. 使用内存映射技术将加载后的DLL代码、资源在多个进程中实现共享。
  3. 在对函数库进行更新时,只更新DLL文件即可。

3. 加载方式

DLL加载方式有两种:显式链接(Explicit Linking)隐式链接(Implicit Linking)

  • 显示链接:程序在使用DLL时进行加载,使用完毕后释放内存
  • 隐式链接:程序在开始时即一同加载DLL,程序终止时再释放占用的内存

    IAT提供的机制与DLL的隐式链接有关。

二、DLL调用的简单理解

在OD中查看程序的反汇编代码如下所示:

iat

在调用ThunRTMain()函数时,并非是直接调用函数,而是通过获取0x00405164地址处的值-0x7400A1B0,该值是加载到待分析应用程序进程内存中的ThunRTMain()函数的地址。  

需要注意的是,此处之所以编译器不直接进行jmp 7400A1B0主要是因为以下两点:

  • DLL版本不同,由于操作系统的版本存在差异,DLL文件版本也会存在差异
  • DLL重定位,DLL文件的ImageBase一般为0x10000000,如果应用程序同时有两个DLL文件需要加载--a.dll和b.dll,在运行时a.dll首先加载进内存,占到了0x10000000,此时b.dll如果再加载到0x10000000,就会发生冲突,所以需要加载到其他的空白内存空间处。

三、IMAGE_IMPORT_DESCRIPTOR结构体

1. 结构介绍

该结构体中记录着PE文件要导入哪些库文件,因为在执行一个程序时需要导入多个库,所以导入了多少库,就会存在多少IMAGE_IMPORT_DESCRIPTOR结构体,这些结构体组成数组,数组最后以NULL结构体结束。部分重要成员如下所示:

成员 含义
OriginalThunk INT的地址(RVA),4字节长整型数组,NULL结束
Name 库名称字符串的地址(RVA)
FirstThunk IAT的地址(RVA),4字节长整型数组,NULL结束

下图描述了notepad.exe之kernel32.dll的IMAGE_IMPORT_DESCRIPTOR结构:

iat1

2. PE装载器把导入函数输入至IAT的顺序

  1. 读取IID的Name成员,获取库名称字符串(eg:kernel32.dll)

  2. 装载相应库:

    LoadLibrary("kernel32.dll")

  3. 读取IID的OriginalFirstThunk成员,获取INT地址

  4. 逐一读取INT中数组的值,获取相应IMAGE_IMPORT_BY_NAME地址(RVA)

  5. 使用IMAGE_IMPORT_BY_NAME的Hint(ordinal)或Name项,获取相应函数的起始地址:

    GetProcAddress("GetCurrentThreadld")

  6. 读取IID的FirstThunk(IAT)成员,获得IAT地址

  7. 将上面获得的函数地址输入相应IAT数组值

  8. 重复以上步骤4~7,知道INT结束(遇到NULL)

四、总结

IAT是在学习PE文件格式中重要的一部分,也是比较难的一部分,需要仔细学习,一定要熟练掌握。建议根据实际的PE文件结合前面的分析步骤,亲自动手多加分析,不断熟悉分析流程。

免费评分

参与人数 6吾爱币 +7 热心值 +4 收起 理由
Hmily + 5 + 1 鼓励转贴优秀软件安全工具和文档!
13185872266 + 1 谢谢@Thanks!
shiyangyanga + 1 我很赞同!
windtrace + 1 谢谢@Thanks!
cpj001 + 1 我很赞同!
白影33 + 1 排版不错

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| yaoyao7 发表于 2020-3-8 16:24
白影33 发表于 2020-3-8 13:57
GetProcAddress(

HMODULE hModule, // DLL模块句柄

图片放在图床上了,可能部分区域的网路需要科学一下。那个函数的用法那不是函数表达式,只是一个象征性的表达方式。你可以看下《逆向工程核心原理》这本书
白影33 发表于 2020-3-8 16:54
yaoyao7 发表于 2020-3-8 16:24
图片放在图床上了,可能部分区域的网路需要科学一下。那个函数的用法那不是函数表达式,只是一个象征性的 ...

确实,大部分和原文一模一样,建议留个参考书籍在结尾,要是能附上多少面就跟好了
白影33 发表于 2020-3-8 13:57
GetProcAddress(

HMODULE hModule, // DLL模块句柄

LPCSTR lpProcName // 函数名

);
你的这个函数用法好像错了吧,
图片好像也少了一些
Screenshot_2020-03-08-13-55-38.jpg
阿花丷 发表于 2020-3-8 14:22
这个pe格式倒是不难
xiayusammr 发表于 2020-3-8 23:42
这是一个好东西,很详细
carrot2017 发表于 2020-3-9 07:38
感谢分享
pantherTL 发表于 2020-3-16 08:00
看这个可以复习计算机知识,很好很好!
cuist3 发表于 2020-3-16 08:20
感谢楼主分享,先收藏了
嗜梦终空 发表于 2020-3-29 19:01
感谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-27 08:46

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表