首页
社区
课程
招聘
[原创]保护模式10-10-12页,在0号线性地址处挂载物理页
2022-12-20 20:49 7458

[原创]保护模式10-10-12页,在0号线性地址处挂载物理页

2022-12-20 20:49
7458

 初学保护模式,做实验中会碰到很多坑点,理论知识的理解不透彻,调试技术不全面等,都能导致一个小小的实验进行不下去,今天分享一下自己的心得。大神勿喷!!!感谢手下留情!!!

一、调试环境:win10物理机,虚拟机中安装的xp_sp3,已经实现串口通信

二、上菜!(源代码)

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
DWORD* getPDE(DWORD addr)
{
    DWORD PDI = addr>>22;                //右移22位留下前10位,则为PDE偏移
    DWORD PTI = (addr>>12) & 0x000003FF;      //右移12后,和3ff(10个1)与运算后,正是PTE的序号
    return (DWORD*)(0xC0300000 + PDI * 4);    //系统通过0xC0300000这个线性地址找到的物理页就是页目录表,这个物理页比较特殊
}
DWORD* getPTE(DWORD addr)
{
    DWORD PDI = addr>>22;
    DWORD PTI = (addr>>12)&0x000003FF;
    return (DWORD*)(0xC0000000 + PDI * 0x1000 + PTI * 4); //PDI * 0x1000  把PDI移动到第21-12位置上
}
DWORD iAddr;
DWORD str = 0;  //查看读取页的PDE
__declspec(naked) void test()
{
    __asm
    {
        int 3
        push ebp;
        mov ebp, esp;//开辟新栈
        sub esp,0x1000;//提升栈空间
        pushad;//保存寄存器
        pushfd;
        push fs;
    }
str = *((DWORD*)0xC0300000);
*getPDE(0) = *getPDE(iAddr);
*getPTE(0) = *getPTE(iAddr);
    __asm
    {
        //int 3;
        pop fs;
        popfd;
        popad;
        add esp,0x1000;
        mov esp,ebp;
        pop ebp;
        iretd;
    }
}
int main()
{
    iAddr = (DWORD)VirtualAlloc(NULL,0x1000,MEM_COMMIT,PAGE_READWRITE);
    memset((DWORD*)iAddr,0,0x1000);   //把地址空间置为0
    printf("virtualAlloc addr: %x\n", iAddr);
    printf("test addr: %x\n", test);
    __asm
    {
        int 3
        int 0x20   //构造eq 8003f500 0040ee00`0008100a //自己构造的中断点,int index是在IDT中的序号   
        int 3
    }
    // test r/w
    *(DWORD*)0 = 0x12345678;
    printf("%x\n", *(DWORD*)0);
    return 0;
}

三、开始调试分析,以下代码截图则是源代码执行过程

一、背景介绍,要挂载物理页,因为要操作页表,所以必须在R0权限执行,所以自行构造中断描述符,进入R0后,对0线性地址进行挂载自己virtualalloc申请的物理页。


      程序F5后,断在用户态的int 3 处,这个时候需要我们自己构造以下中断描述符:eq 8003f500 0040ee00`00081019。中断描述符在存在于IDT表中,我是放在了8003f500位置,所以对应的中断序号正是0x20,看到的代码就是 int 0x20。

0040ee00`00081019 这是我自己构造的中断描述符,加粗部分是我们从中断描述符中的BaseAddress,就是我们程序进入中断后,要执行代码处的地址。这个要根据我们自己程序动态调整。

上图控制台窗口中的专门打印进入R0后执行的代码段test函数的地址00401019。新申请

===============================================================================漂亮分割线

通过上图分析,大家应该很清楚看明白这个中断描述符的构造了吧。

当代码执行int 0x20的时候,cpu就是到IDT表中找到序号为0x20的这个中断描述符,cpu在对这个描述符分解分析。

1、判断p位是否为1,不为1直接pass,因为无效嘛。

2、判断DPL,当前程序的CPL是否大于等于DPL。咱们当前程序在R3,cpl肯定是3,所以这里构造的时候也是3.

3、判断s位,s=0说明是系统类型的type,s=1说明是用户类型的type。

4、判断type位,14对应32-bit interrupt gate


cpu执行完以上步骤后,断定是个中断门描述符,则拿段选择子的序号到GDT表中找对应的全局描述符。0008是一个系统常用的全局描述符,我们直接就借用,也可自行构造,但是太麻烦了所以效仿别人直接使用。



       二、在windbg中开启系统中断,执行eq 8003f500 0040ee00`00081019后,就是我们xp系统的IDT表中更新了一条中断描述符。记得windbg g回去,要不xp系统还是中断状态。

        进入xp程序中执行F5继续执行程序。这时候程序由R3已经进入了R0.断在了我们的代码中。下图

    这个时候,是在R0领空了,所以时windbg捕捉到断点。到windbg查看已经断下来了。

    windbg中使用u命令,反编译当前要执行的代码。

可以清楚的看到正是我们写的汇编代码,windbg也给我们展现出来了,说明我们当前段在这个int 3处。

我们单部执行可以详细查看寄存器的内容,以及执行过程中内存中的数据。单部执行命令p

上图,我们代码把申请空间3a0000线性地址处的PDE赋给0线性地址处的PDE。根据3a0000分解,实际上和0处的PED是同样的一个页目录。

得到3a0000线性地址的PTE,不知道为什么页属性(886)p位=0,所以手动在windbg中做修改为2187c867,一般也属性都是这样。如有大神请指点迷津。

上图是0线性地址的PTE,可以看出来,全为0,实际是没有给挂载物理页。后面代码就把2187c867替换给此处。

kd> dd c0300000

c0300000  21438067 21677067 00000000 00000000

c0300010  00000000 00000000 00000000 00000000

c0300020  00000000 00000000 00000000 00000000

c0300030  00000000 00000000 00000000 00000000

c0300040  00000000 00000000 00000000 00000000

c0300050  00000000 00000000 00000000 00000000

c0300060  00000000 00000000 00000000 00000000

c0300070  00000000 00000000 00000000 00000000

kd> !dd 21438000

#21438000 2187c886 00000000 00000000 00000000

#21438010 00000000 00000000 00000000 00000000

#21438020 00000000 00000000 00000000 00000000

#21438030 00000000 00000000 00000000 00000000

#21438040 210b9886 00000000 00000000 00000000

#21438050 00000000 00000000 00000000 00000000

#21438060 00000000 00000000 00000000 00000000

#21438070 00000000 00000000 00000000 00000000

kd> !ed 21438000 2187c867 

如果上述没有修改页的属性,可以追加上述代码,把页的属性修改867

当执行完iretd后,程序断点已经切换到了用户态。已经正常可以看到打印出0线性地址处的值了。






[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

最后于 2022-12-22 21:39 被xiaoheizi66编辑 ,原因: 补充图片
收藏
点赞2
打赏
分享
最新回复 (1)
雪    币: 131
活跃值: (278)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xiaoheizi66 2022-12-26 22:54
2
0
补充问题:关于页属性,我们通过CR3获取物理页后,再获取页的属性,发现是886,最后的p=0,这是因为这是的物理页处于缺页状态(页从TLB被倒出了),当cpu读取这个物理页对应的线性地址时候,cpu迅速再把需要的物理页导入到TLB。
游客
登录 | 注册 方可回帖
返回