首页
论坛
课程
招聘
雪    币: 478
活跃值: 活跃值 (82)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝

[原创]小白误入看雪:详解pe文件中的地址转换

2020-6-29 22:59 1095

[原创]小白误入看雪:详解pe文件中的地址转换

2020-6-29 22:59
1095

本菜鸡初入逆向这条道路,技术菜得抠脚,今天学习了pe文件中的地址转换,特此分享给跟我一样初入逆向学习道路的朋友们(逆向大佬请移步)
首先用peview打开相应的notepad.exe,显示如下的各项内容:
peview各项内容描述
接下来查看节区(".text")部分的内容,

可以看出节区(".text")中的在内存中的RVA=00001000,Virtual Size=00007748,在原文件中的Pointer to Raw Data = 00000400,Size of Raw Data = 000007800,假设内存的ImageBase = 01000000,这里我们可以画出如下的图示:
文件地址到内存地址的转换图示
其他区域依次从peview中读取相应的内容,可以画出如下所示的内存转换图
内存转换图
1.RVA=5000时,File Offset = ?
RVA=5000时,由于内存的基址地址为01000000,所以对应的内存地址为01005000,仔细查看后可以发现位于右边内存区域的节区(".text")部位的区域,
此时运用公式RAW-PointerToRawData = RVA-VA(文件偏移-原始数据指针=相对偏移地址-偏移地址),RAW=RVA-VA+PointerToRawData=01005000-01001000+400=4400
2.RVA=13314时,File Offset = ?
同理运用公式RAW=RVA-VA+PointerToRawData=01013314-0100B000+8400=10714
接下来对于IAT(导入地址表)进行学习,查找notepad.exe中调用的IMAGE_IMPORT_DESCRIPTOR结构体,
首先我们在peview中查看IMAGE_OPTIONAL_HEADER结构体,找出相应的IMPORT Table的RVA和Size
IMPORT Table的RVA和Size
当RVA=7604时,将其转换成相应的RAW,转换方式与上面的方式相同,RAW=7604-1000+400=6A04,使用Hex editor(官网可下载)打开notepad.exe之后,找到地址为6A04处的内容
导入地址表的对应内容
该结构体数组为
结构体数组描述
1.OriginalFirstThunk-INT
INT为一个包含导入函数信息的结构体指针数组,只有获得了这些信息才能在加载到进程内存的库中准确求得相应函数的起始地址
将OriginalFirstThunk的RVA转换成对应的RAW(RVA:7990->RAW:6D90),查看对应地址的相应内容
IMAGE_IMPORT_BY_NAME
上图即对应的INT,由地址数组形式组成(数组尾部以NULL结束),每个地址值分别指向IMAGE_IMPORT_BY_NAME结构体,跟踪数组的第一个7A7A(RAW:6E7A),可以查找出数组第一个元素指向函数的名称
第一个元素指向的函数
2.找寻相应的dll库文件的名称
将Name对应的00007AAC转换为相应的00006D90,找到相应的地址之后即可找到对应的dll库文件的名称
dll库文件的名称
3.找寻相应的IAT
FirstThunk-IAT(Import Address Table)
IAT的RVA:12C4即为RAW:6C4,到对应的位置找寻对应的IAT
IAT的具体内容
黑框圈出的区域即为IAT数组区域,对应于comdlg32.dll库。它与INT类似,由结构体指针数组组成,且以NULL结尾。IAT的第一个元素值被硬编码为76324906,该值无实际意义,notepad.exe文件加载到内存时,准确的地址值会取代该值。
普通DLL文件的ImageBase为10000000,所以经常会发生DLL重定位。但是Windows系统DLL文件(kernel32/user32/gdi32等)拥有自身固有的ImageBase,不会出现DLL重定位。

 

IAT的RVA为12C4,加上ImageBase中的01000000后会变成010012C4,查看ollydbg对应地址的内容
图片描述
可以看出comdlg.dll!PageSetupDlgW函数的IAT地址为010012C4,其值为76324906,它时API准确的起始地址值。
总结:找到IAT地址的关键在于首先分析出文件以及内存所占据的各个区域,接下来通过IMAGE_OPTIONAL_HEADER中的IMPORT Table找出相应的每一个函数对应的INT、dll库文件名称以及IAT,最后根据IAT对应的RVA运行程序,然后查看程序运行之后dll库名称所对应的API起始地址值
接下来介绍对于EAT库文件的查找,IAT使不同的应用程序可以调用库文件中提供的函数普通PE文件通过IAT表来正确调用库文件的函数,库文件通过EAT表将函数的正确入口告知普通PE文件。
IAT内地址的获得其实是通过INT提供的名称或者标号利用GetProcAddress()API从库文件中获得的,而GetProcAddress()API正是通过访问EAT表来获取的地址。
(在本例子之中,查看IAT需要运行源程序notepad.exe,查看EAT则需要运行相应的kernel32.dll库文件)
使用peview打开kernel32.dll库文件,分析kernel.dll的库文件偏移,画出相应的文件偏移以及在内存之中的虚拟地址
文件偏移以及在内存之中的虚拟地址
在kernel32.dll中的IMAGE_OPTIONAL_HEADER中找出EXPORT Table对应的RVA以及Size, EXPORT Table的RVA以及Size
得出EXPORT Table中的RVA=0000262C,利用公式RVA-VA=RAW-PointerToRawData,0000262C-00001000=RAW-400,RAW=00001A2C
1.函数名称数组
使用hex editor打开文件notepad.exe,查看00001A2C处的内容
查看地址为1A2C偏移处的内容
/883690_ZYV9ZYRFV9ZQ8SF.png)
Characteristics:00000000
TimeDatestamp:48025b1e
MajorVersion:0000
MinorVersion:0000
Name:00004b8e
Base:00000001
NumberOfFuctions:000003b9
NumberOfNames:000003b9
AddressOfFunctions:0002654
AddressOfNames:00003538
AddressOfNameOrdinals:0000441c
00003538对应的RAW=00002938,
2.函数名称对应地址
到内存00002938中找寻相应的函数地址
对应的函数地址
假设我们需要找寻的为第三个函数的对应名称,可以看出第三个函数对应的RVA=00004bb3,将其转换为相应的RAW=00003fb3,到00003fb3中去找寻相应的函数名称,发现函数名称为AddAtomW 函数名称对应图片,对应的数组索引为2
3.Ordinal数组进行转化
AddressOfNameOrdinals成员的值为RVA:0000441c->RAW:0000381C
到RAW=0000381C中去查看相应的索引值
对应的索引值
可以看出index=2的时候,对应的为Ordinal=2
5.找寻函数的实际函数地址
查找AddAtomW的实际函数地址,AddressOfFunctions成员的值为RVA:265A4->RVA:1A54,到hex editor里面查找对应的Export函数的地址
查阅Export函数的地址因为ordinal=2,所以其中的第三个地址即为Export函数的地址,查阅后发现Export函数的地址为000326d9(ordinal=2,RVA=000326d9)



[看雪官方培训]《安卓高级研修班(网课)》9月班开始招生!顶尖技术、挑战极限、工资翻倍!

最后于 6天前 被mb_eiksswhr编辑 ,原因:
上传的附件:
最新回复 (3)
雪    币: 4783
活跃值: 活跃值 (1042)
能力值: (RANK:40 )
在线值:
发帖
回帖
粉丝
Editor 活跃值 6天前
2
1
文章简单了些,但作为临时会员还是值得鼓励的,设置优秀,恭喜你转为正式会员!
雪    币: 478
活跃值: 活跃值 (82)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
mb_eiksswhr 活跃值 6天前
3
1
Editor 文章简单了些,但作为临时会员还是值得鼓励的,设置优秀,恭喜你转为正式会员!
感谢版主大大
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_xaqrnpgr 活跃值 4天前
4
0
打卡路过的
游客
登录 | 注册 方可回帖
返回