挂物理&&修改页属性(Windbg)

admin 2024年2月17日00:19:08评论4 views字数 2417阅读8分3秒阅读模式

在学页的属性之前,我们只知道在程序运行时有虚拟的4GB空间,程序内部的静态常量是不可修改的,诸如0地址这样的特殊地址是不可访问不可读不可写的。但是在了解物理页之后,我们才知道,没有什么不可能的事情。

10-10-12分页

CR3寄存器

在说分页方式之前,我们先提一个概念:保护模式和实模式的区别,实模式与保护模式最大的区别在于:实模式访问的地址都是真实的地址,而保护模式都是虚假的地址。  

在这里,我们先介绍10-10-12分页方式。

我们以指令:JMP dword ptr ds:[0x123456]为例。

我们都知道,当我们需要JMP 0x123456时,他其实真正跳的地址是:ds.Base+0x123456,其中,我们可以叫0x123456为有效地址,ds.Base+0x123456为线性地址。但是这些地址全部都是虚拟的,并不是真正的物理地址。

(在这里我要补充一下,在我的笔记中,物理地址,其实也并不是真正的磁盘上的地址,这里不需要过多了解)

而,我们的操作系统和CPU是如何找到真正的物理地址的呢?

我们每一个进程都有一个自己的CR3寄存器,准确的说,应该是都有一个CR3寄存器的值,而CR3寄存器,是所有寄存器中,唯一存放物理地址的寄存器。CPU会通过CR3的值找到一个物理页,该物理页大小为4096个字节,每4个字节为其中一个值,因此能存放1024个值;而这些值都指向下一个物理页,这个第二个物理页与第一个物理页一样。第二个物理页里面的值会指向最后一个物理页,该物理页中存放的就是我们的数据了。如下图:

挂物理&&修改页属性(Windbg)

设置分页方式

挂物理&&修改页属性(Windbg)

将noexecute 改成 execute

PDT、PDE与PTT、PTE

先放图:

挂物理&&修改页属性(Windbg)

在上面我们已经介绍了如果要查找到真正的物理页,会经过多次的查找,这种就类似于一个数据,我找到第一级数据,在通过第一级数据,找第二级数据,最后找到第三级数据。

那么每一级叫什么呢?

第一级我们叫他PDE,页目录表,该表大小为4096个字节,表中存放的是PDE,也可以叫做页目录表项,每一项大小4字节,所以总共有1024个项,因此,这也就是10-10-12的第一个10的由来(2的10次方)。

第二级我们叫他PTE,页表,该表与PDE一样。

第三级,就是我们真正存储数据的物理页了。该页大小也是4096个字节,4KB。4096个字节= 2的12次方。

了解了每一级的含义,我们还需要在对他们进行一些知识的概括:

  • PTE可以指向物理页,也可以不指向物理页,不指向物理页时,就类似于0地址(下文会解释)。不可访问

  • 多个PTE可以指向同一个物理页,但是一个PTE只能指向一个物理页

而这个时候,我们会思考,这个与前面说的”想干嘛就干嘛“有啥关系?

这时,我们在介绍一下他们的属性:

属性

物理页的属性与我们是否可以访问,是否可以读写相关。

因此,在这之前,我们先了解:
物理页的属性 = PDE属性 & PTE属性

PDE属性:

挂物理&&修改页属性(Windbg)

PTE属性:

挂物理&&修改页属性(Windbg)

前面说到,PTE与PDE都是大小位4字节(32位)的,但是他们的前12位代表的是他们的属性,后20位才是真正指向的值。

这里简单介绍一下他们的一些的属性含义:

  • P位:为0,不可访问,为1,可访问

  • R/W位:0,代表只读,1代表可写可写

  • U/S位:0,代表特权用户才可以访问;1代表普通用户可以访问

  • A位:是否被访问过,0,代表未访问过,1代表访问过,既是只访问一个字节,也会导致PDE PTE置1

  • D位:脏位,0,代表没有被写过,1代表被写过

  • PS位:只对PDE有意义,PS = PageSize的意思,当PS = 1时,PDE直接指向物理页,无PTE,低22位时页内偏移

  • 关于G位 PWT位 PCD位,需要学完控制寄存器和TLB才能讲

分页分析举例

在介绍他们的属性之后,我们再来简要分析一下。

如地址:0x0012FF7C

根据10-10-12的分页模式,可以分为:

0x

0

0

1

2

f

f

7

c

-

0000

0000

0001

0010

1111

f

7

c

根据上述表格:

我们可以分为:

0000 0000 00:10位

01 0010 1111:10位 = 12f  

f7c:我们可以不用分了,因为刚好是12位。

如果此时cr3 = 1942a000

那么我们只需要根据以下步骤,就能找到真实的地址:

  1. !dd 1942a000 + 0*4

    1. 复制上面的结果的第一行

    2. 挂物理&&修改页属性(Windbg)

  1. !dd 1e8a4000 + 4bc

    1. 将1e8a4067改为:1e8a4000,因为前面说了,前12位为属性

    2. 4bc = 12f*4。这里为啥要*4,那是因为PDE与PTE项都是4个字节的。

    3. 挂物理&&修改页属性(Windbg)

  1. !db 1e639000 + f7c

    1. 将1e639067改为:1e639000,同理。

    2. f7c不需要修改了,因为物理页大小就是4kb

    3. 挂物理&&修改页属性(Windbg)

在这里我们还要说明几点:

  • 物理页因为大小为4kb,所以,范围为:0-fff

  • 所以:当CR3一样时,给我们地址如:0x12345678,0x12345fff。我们可以直接判断,这两个地址指向的物理页是一样的。

修改地址0的值

#include "stdafx.h"

int main(int argc, char* argv[])
{
int x = 0x1234;
printf("%xn",&x);

*(int*)0 = 123;
printf("0 Address: %dn",*(int*)0);

return 0;
}

挂物理&&修改页属性(Windbg)挂物理&&修改页属性(Windbg)

通过!ed 将0地址挂页。

修改静态值


#include "stdafx.h"
#include <windows.h>

int main(int argc, char* argv[])
{
char* str = "Hello World!";
//str[1] = "X";
//getchar();
//str[1] = "X";
printf("Address:%xn",str);
printf("%sn",str);
DWORD dwVal = (DWORD)str;
*(char*)dwVal = 'X';
printf("%sn",str);
return 0;
}

直接修改报错:

挂物理&&修改页属性(Windbg)

修改页属性后:

挂物理&&修改页属性(Windbg)

原文始发于微信公众号(loochSec):挂物理&&修改页属性(Windbg)

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年2月17日00:19:08
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   挂物理&&修改页属性(Windbg)http://cn-sec.com/archives/2149650.html

发表评论

匿名网友 填写信息