DLL那些事儿(二)

Hello.dll里面有什么

我们使用文本查看工具进行查看, 显然这些乱码我们完全无法阅读。

在这里插入图片描述

所有DLL文件的结构都如下图所示, 由这几部分组成。

在这里插入图片描述

DOS Stub和PE Signature

其中的DOS Stub和PE Signature我们可以从上图看到,This program cannot be run in DOS modePE。我们也可以使用十六进制查看工具进行查看。其中DOS Stub部分的位置是固定的,而PE Signature部分的地址在3C处指明了。
在这里插入图片描述
在这里插入图片描述

COFF file header

DOS Stub和PE 标识由于是ASCII形式存储在文件中的,所以我们可以通过文本查看工具或者16进制查看工具看到,但是剩下的部分使用文本查看工具看起来就很费劲了,好在微软为我们提供了查看二进制可执行文件的工具——dumpbin.exe。

使用dumpbin /HEADERS Hello.dll命令就可以将hello.dll的头部信息格式化成我们人类可读的形式并输出到屏幕上了。
在这里插入图片描述
我们可以看到FILE HEADER VALUES部分就是我们的COFF file header了,

这部分告诉我们这个文件是x64架构的机器上的DLL(8665 machine(x64));

由两部分组成(2 number of sections),

然后是一个时间戳,默认标明了这个DLL创建的时间(59BDE631 time date stamp Sat Sep 16 20:04:17 2017这个实际上可以是任意值,它不一定必须是时间戳,你可以在构建的时候指定它的值);

可选头的大小是0xF0(F0 size of optional header);

这个文件有2022个字符(2022 characteristics);

这个文件包含可执行代码(Excutable,并不能表明这是一个EXE可执行程序,只是说明这是一个能被加载并执行的DLL);

这是一个64位的二进制文件,所以可以处理更大(大于2GB)的地址,32-bit的二进制文件则同(Application can handle large (>2GB) addresses);

这是一个DLL而不是EXE(DLL

可选头文件(Option Header)

可选头文件有两种类型,PE32和PE32+,分别标识32位二进制文件和64位二进制文件。

在这里插入图片描述

我们可以看到magic 前边有一个数字(魔数),用来确保链接器正确的解析数据类型;

我们可以在此处看到入口点为空,这就是我们希望看到的,因为我们在链接时使用了/NOENTRY选项指定它没有入口点;

这个image的首选基地址是0X70000000到0X70002FFF,还有一些对齐信息

image的大小是0x3000 比特(12Kb),头部大小是0x400比特(1Kb),DLL特征字0x160比特

除此之外还有一些其他的扩展信息

还有一些有额外的关于DLL里面有什么的元数据的目录,可以看到这些目录里都有RVA(Relative Virtual Address)和size,

Relative Virtual Address(RVA,虚拟地址):

相对于DLL被加载到内存中的初始地址的偏移量

运行时真实的内存地址 = DLL的基地址 + RVA(Address in Memory = DLL Base Address + RVA)

如果想要计算对应的RVA只需要用下面公式即可

RVA = Address in Memory - DLL Base Address

例如:

  • 函数GetGreeting() 在Hello.dll 中的RVA=0x2000,
  • Hello.dll 加载到初始地址为0x7000’0000的内存中
    可以得出函数GetGreeting()在地址为0x7000‘2000处(0x7000’0000 + 0x2000 = 0x7000‘2000)

Section Header

紧跟着Option Header的是一个接一个的Section Header,Section Header告诉我们如何在DLL中找到实际的数据。

如图所示是Hello.dll中的第一个Section——.text Section(包含代码的代码段),并且它需要映射到内存中以供执行和读取,

我们可以看到虚拟地址为0x1000,这就是上面说的RVA,表明了这部分在DLL被加载时在内存中的位置。virtual size表示这部分占用内存的大小,可以看到我们这个程序代码只占8比特(bytes),除此之外还包含了一些其他信息。

在这里插入图片描述

第二个Section——.rdata Section(只读数据段, 可以通过标志位(flags 0x40000040)看出,这个section具有只读权限,不是可执行程序,也不可写),它也需要被映射进内存页中。

在这里插入图片描述

数据段还包含了一些其他数据,从上边的option header中我们可以看到Export Directory(0x2040)和Debug Directory(0x2020)的RVA是被包含在.rdata section中的(0x2000到0x20D7)

在这里插入图片描述

小结

从Hello.dll的头部信息中我们知道,当Hello.dll加载到进程中时,它将在内存中占用0x3000 bytes(3页)的空间。

  • 一页包含头部信息(headers)
  • 一页包含 代码段(.text section)
  • 一页包好只读数据段(.rdata section)

(这些不是唯一可能的 section,我们可以在其他DLL中找到其他 几种 section)

Hello.dll在一对目录(directories)中有一些额外的元数据

  • 一个调试目录(debug Directory)
  • 一个导出目录 (export directory)

这些数据包含在 .rdata section 中
在这里插入图片描述

查看 Sections的具体内容

我们可以使用dumpbin.exe 方便的查看各个Section的具体内容

Section #1: .text (代码段)

我们使用dumpbin /rawdata /section:.text Hello.dll命令可以看到代码段以16进制的形式显示到屏幕上,

使用dumpbin /disasm:BYTES /section:.text Hello.dll命令可以同事查看代码段的反汇编和16进制形式

在这里插入图片描述

Section #2: .rdata (只读数据段)

使用dumpbin /rawdata /sectiion:.rdata Hello.dll命令可以显示16进制形式的只读数据段。

可以看到我们程序中的字符串常量在只读数据段中。我们之前讨论过的两个Directory也在只读数据段中,如图所示,我们用不同的颜色高亮标记了它们。但这也是不可读的,我们完全看不懂这些Directory中到底是什么。

在这里插入图片描述

使用命令dumpbin /exports Hello.dll可以看到DLL的导出表(Export Directory)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值