登录  | 立即注册

游客您好!登录后享受更多精彩

查看: 41|回复: 0

逆向工程核心原理读书笔记 03

[复制链接]

40

主题

3

回帖

59

积分

版主

积分
59
发表于 2025-3-22 12:06:57 | 显示全部楼层 |阅读模式

这一部分主要是PE相关,过了好几遍了,这次一定搞完。主要是后面的一些表,前面的就不太写了

第13章

dos头,dos存根,nt头,节表

va = imagebase + rva

NT头包含文件头和可选头

NT文件头:

image-20211101232815516

NT可选头:

image-20211101232920919

AddressOfEntryPoint;//EP的RVA值
ImageBase;        //载入内存时优先装载的地址
SectionAlignment; //节区在内存中的最小单位
FileAlignment;    //节区在磁盘文件中的最小单位
SizeOfImage;   //指定了PE Image在虚拟内存中所占空间的大小,包含所有头
SizeOfHeaders; //整个PE头的大小

节表

image-20211101233236636

DWORD VirtualSize; //载入内存时此节区的大小
VirtualAddress;   //内存中节区起始地址(RVA)
SizeOfRawData;    //磁盘中节区所占大小
PointerToRawData; //磁盘中本节对于文件头的距离

接下里重要的IAT来了

FOA = RVA - VirtualAddress + PointerToRawData

vitualAddress 和 PointerToRawData都在节区表里

在NT头的可选NT头中的最后,找到导入表的RVA = 0x7604

所以,FOA = 0x6A04

重要的部分:

DWORD OriginalFirstThunk; // INT address(RVA),数组,指向IMAGE_IMPORT_BY_NAME结构体
DWORD Name;       //当前库名的地址(RVA)
DWORD FirstThunk; //IAT address(RVA),数组,指向IMAGE_IMPORT_BY_NAME结构体

首先是INT和IAT导入的步骤:

  1. IMAGE_IMPORT_DESCRIPTORName成员获取库名称的字符串(比如’kernel32.dll’)
  2. 装载相应的库,LoadLibrary(“kernel32.dll”)
  3. IMAGE_IMPORT_DESCRIPTOROriginalFirstThunk成员,获得INT表的地址
  4. 逐一获取INT数组的IMAGE_IMPORT_BY_NAME地址
  5. 使用IMAGE_IMPORT_BY_NAME的hint或者name项,获取相应函数的起始地址
  6. IMAGE_IMPORT_DESCRIPTORFirstThunk(IAT),获取IAT的地址
  7. 将上面获得的函数地址输入相应的IAT数组值
  8. 重复4~7

image-20211102115247033

image-20211102115310442

EAT

typedef struct _IMAGE_EXPORT_DIRECTORY
{
    DWORD Characteristics;
    DWORD TimeDateStamp;
    WORD MajorVersion;
    WORD MinorVersion;
    DWORD Name;                  //要导出的名字的地址
    DWORD Base;                  //oridinal base
    DWORD NumberOfFunctions;     //实际导出函数个数
    DWORD NumberOfNames;         //导出函数中有名字的个数
    DWORD AddressOfFunctions;    //导出函数的地址(数组,RVA,元素个数=NumberOfFunctions )
    DWORD AddressOfNames;        //导出函数的名称的地址(数组,RVA,元素个数=NumberOfNames)
    DWORD AddressOfNameOrdinals; //导出函数序号表的地址(数组,RVA,元素个数=NumberOfNames),函数序号表
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

这里写图片描述

获得函数地址的API为:GetProcAddress,原理:

  1. 利用adressofname转到函数名称的数组
  2. 上面的数组存着的是地址,通过strcmp,查到指定的函数名,这时索引记为name_index
  3. 用addressofnameordinals转到ordinal数组,
  4. 通过name_index查找相应index值
  5. 利用addressoffunction转到 函数地址数组
  6. 用ordinal找到需要函数的地址。

这里使用kernel32.dll来演示:

image-20211102120644783

AddressOfFunctions :   RVA = 0x2654  FOA = 0x1A54
AddressOfNames:        RVA = 0x3538  FOA = 0x2938
AddressOfNameOrdinals: RVA = 0x441C  FOA = 0x381C

AddressOfName,一个个的RVA,个数为953:

image-20211102121145140

RVA = 4B9B ==> FOA = 3F9B

image-20211102122000215

来找下AddConsoleAliasA函数,是第4个,索引为3,

查ordinal数组,foa = 0x381C

image-20211102122300407

也是3,接下来就可以查实际地址了,

找addressofFunction:

image-20211102124641184

image-20211102123235632

第4个是0x071cdf,kernel32.dll的imagebase是0x7c800000,加起来是'0x7c871cdf'

image-20211102123350999

没问题。

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|断点社区 |网站地图

GMT+8, 2025-4-4 14:25 , Processed in 0.347754 second(s), 24 queries , Yac On.

Powered by XiunoBBS

Copyright © 2001-2025, 断点社区.

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