【2021.03.26】分页:10-10-12

要点回顾

前文主要讲解段的机制,其实段的机制还有很多细节,需要在实验的过程中详细总结。

从本文开始,开始进入页的机制的学习。

4GB内存空间

每个进程都有自己的4GB的内存空间,如果开启两个进程那么就是2x4=8GB。

那么当前计算机的内存条是多少呢?可能是4GB,或者更少。那么这样就会有一个问题,内存不够,明显是不正常的。

也就是说,每个进程都有4GB的内存空间的时候,进程的4GB空间是不是真实存在的?

每个进程的4GB进程空间是假的,并不存在的。操作系统为每个进程分配了4GB的虚假内存

当使用某一块空间的时候,经过转换以后把数据储存到物理内存中。

那么物理内存是不是就是内存条呢?不是。

物理地址

有效地址线性地址物理地址

如指令:MOV EAX, DWORD PTR DS:[0x12345678]

有效地址:0x12345678

线性地址:DS.BASE + 0x1234578

大多数情况下,DS.BASE是0。也就是说,在大多数情况下有效地址和线性地址是一样的。但也有特殊情况,比如FS段寄存器就不是一样的。

每个进程的所谓4GB进程空间是假的,这就意味着拿着0x12345678去寻找是没有办法直接找到数据的,因为这个地址本身就是假的,是不存在的。

CPU会将线性地址转换为物理地址,然后通过物理地址找到数据。

每个EXE中都会用到一些系统层面的DLL,这些DLL存放在物理内存中,但是给每份EXE都映射了一份线性地址。

这意味着如果想知道程序B做了什么事情,通常情况下要进入到程序B的进程空间中进行HOOK。

其实没有必要这么复杂,因为在我们自己的程序如程序A的进程空间中HOOK系统相关的DLL,就可以知道程序B做了什么事情。

但如果看到这里就去做实验,那么会是失败的,因为需要页的知识,不了解内部实现细节。如果HOOK了会发现对其他程序没有影响。

CPU会将线性地址转换为物理地址,转换的过程就是接下来要了解的。

它转换的方式在x8632位CPU中有两种转换形式,一种是10-10-12的形式,另一种是2-9-9-12的形式。

如果CPU是64位的情况,它还有一种形式,且相对复杂。

如果了解了32位转换,那么再去了解64位的转换就会简单很多。

10-10-12分页

10-10-12形式,加起来会发现是32。说的就是将线性地址拆分为3份,第一份10位,第二份10位,第三份12位。

设置分页方式

boot.ini

[boot loader]

timeout=30

default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS

[operating systems]

multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional [VirtualKD]" /DEBUG /DEBUGPORT=bazis /fastdetect /noexecute=optin

multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin fastdetect

默认情况下是2-9-9-12分页形式,将 noexecute 修改为 execute,即可切换为10-10-12分页形式,保存后重启即可。

使用线性地址寻找物理地址

物理内存在哪里

每个进程都有一个CR3的值,CR3本身是个寄存器,一个核心,只有一套寄存器。CR3是唯一一个储存物理地址的寄存器。

CR3指向一个物理页,一共4096字节,如下图:

CPU拿到线性地址的时候,它要做的事情就是把线性地址拆分成3份,去找物理地址。所以CPU找的过程要拆,那么我们也要拆。

拆完了以后到哪里去找呢?它先找一个寄存器,CR3寄存器。它是唯一一个存储物理地址的寄存器。

CR3中储存了一个值,这个值指向了一个页,这个页有4KB(4096字节)。

4096字节中每个成员是4个字节,4个字节是一个地址。每个成员4个字节,意味着4096个字节可以储存1024个地址。每个地址又指向一个具体的页。

就像翻书先翻目录,只不过这本书厚一些,它有两层目录。

通过第一层目录找到第二层目录,通过第二层目录找到物理页。

10-10-12形式,加起来会发现是32。说的就是将线性地址拆分为3份,第一份10位,第二份10位,第三份12位。

第一份10,就是看在第一级的页哪个位置,并找到地址。

然后通过找到的地址指向一个页,第二份10就是找到在第二个页里面哪个位置。

第三份12,就是要找的地址在物理页的什么位置。

寻找物理地址

打开记事本,并随便写点东西。

记事本本身就是一个进程,它有自己的4GB进程空间,输入的内容一定是存在它的进程空间里的。

下面先来找到 Hello world 的线性地址,然后通过10-10-12的形式找到它的物理地址。

搜索出5个结果,通过修改记事本中的内容可以发现第一个地址的值改变了。

0x000AA8A0,该线性地址就是我们需要用的。

接下来通过这个线性地址找到物理地址。

先来计算一下,10-10-12,加起来刚好是32位。它说的就是线性地址,把线性地址分成3份,第一份10位,第二份10位,第三份12位。

线性地址:0x000AA8A0

转二进制:0000 0000 0000 1010 1010 8A0,前面刚好是20位,后面的先不管它。
第一份:0000 0000 00,第二份:00 1010 1010,第三份:8A0。

寻找CR3

!process 0 0

寻找物理地址之前需要先找到CR3,找哪个进程的物理地址,就找哪个进程的CR3。

CR3:0x146A0000

查看物理地址

CR3:0x146A0000
第一份:0000 0000 00  (0*4)、第二份:00 1010 1010  (AA*4)、第三份:8A0

以前使用dd 0x12345678,查看某个地址的内存,但是现在不能这样了,因为要查的是物理内存。

现在需要在前面加上一个感叹号,如:!dd 0x12345678 + 第一份*4,也就是:!dd 0x146A0000 + 0*4

为什么要乘以4?因为每个成员是4字节。

  • 寻找第一级

!dd 146a0000 + 第一份(0*4)

需要注意的是,后面选中的三位(067)是属性,在使用的时候将其改为0即可。

  • 寻找第二级

!dd 14dc0000 + 第二份(AA*4),也就是!dd 14dc0000 + 2A8

同样的,后三位在使用的时候修改为0。

  • 寻找第三级

!dd 13fdd067 + 第三份,这个时候不需要再乘以4了。!dd 13fdd067 + 8A0

寻找第三级,并以字节的形式查看。

现在,通过一个线性地址,找到了物理地址。

也就是通过hello world的线性地址,找到了它的物理地址。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值