12558网页游戏私服论坛

 找回密码
 立即注册
游戏开服表 申请开服
游戏名称 游戏描述 开服状态 游戏福利 运营商 游戏链接
攻城掠地-仿官 全新玩法,觉醒武将,觉醒技能 每周新区 经典复古版本,长久稳定 进入游戏
巅峰新版攻 攻城掠地公益服 攻城掠地SF 新兵种、新武将(兵种) 进入游戏
攻城掠地公 散人玩家的天堂 新开 进入游戏
改版攻城掠 上线即可国战PK 稳定新区 全新改版,功能强大 进入游戏
少年江山 高福利高爆率 刚开一秒 江湖水落潜蛟龙 进入游戏
太古封魔录 开服送10亿钻石 福利多多 不用充钱也可升级 进入游戏
神魔之道 签到送元宝 稳定开新区 送豪华签到奖励 进入游戏
神奇三国 统帅三军,招揽名将 免费玩新区 激情国战,征战四方 进入游戏
龙符 三日豪礼领到爽 天天开新区 助你征战无双 进入游戏
王者之师 免费领豪华奖励 免费玩新区 6元送6888元宝 进入游戏
查看: 184|回复: 0

12.2-9-9-12分页(Win7 x86)

[复制链接]

303

主题

303

帖子

616

积分

实习版主

Rank: 7Rank: 7Rank: 7

积分
616
发表于 2022-1-28 20:36:17 | 显示全部楼层 |阅读模式
章节介绍

  • Win7 x86 设置2-9-9-12分页.
  • windows与Intel管理物理页规则,以及Windows内存分区.
  • 2-9-9-12分页规则及其由来.
  • 通过线性地址查找对应物理地址.
  • 共享内存实现原理.
  • 0地址访问错误缘故起因,常量区无法修改缘故起因,高2G内存R3访问失败起因于物理页属性限制.
  • PDPTE,PDE,PTE属性探测,基址探测(MmIsAddressValid).
  • 代码示例0线性地址挂物理页,0线性地址实现SHELLCODE,R3通过门读取任意线性地址...
0.Win7 x86设置2-9-9-12分页

CMD:关闭指令(开启10-10-12分页)                         bcdedit /set pae ForceDisable  bcdedit /set nx AlwaysOff      开启指令(开启2-9-9-12分页)bcdedit /set pae forceEnablebcdedit /set nx OptIn 分页内核文件目录: C:\Windows\System32

x86下每个进程都有虚拟4GB内存空间(x86下线性地址宽度为32位4字节,2^32为4GB(线性地址有4G但未必都能访问 高2G内存为全部进程共享)),x86下虚拟地址划分为:
内存区范围空指针赋值区0x00000000 - 0x0000FFFF用户模式区 0x00010000 - 0x7FFEFFFF64KB禁入区0x7FFF0000 - 0x7FFFFFFF内核0x80000000 - 0xFFFFFFFFintel amd规定一个最小物理页为4KB(一个物理页4096byte遍历每一个字节2^12这也就是分页最后12由来)
Windows规定一个最小物理页为64KB.
1.2-9-9-12分页规则


x86下每个进程有4GB线性地址空间,但是有些地址无法访问,这是由于线性地址对应物理地址为空大概对应物理页属性限制.物理地址MOV EAX, DWORD PTR DS:[0x12345678]有效地址: 0x12345678线性地址: DS.BASE + 0x12345678物理地址: 2-9-9-12分页 通过高31-30位定位PDPTE,通过29-21位定位PDE,通过20-12位定位PTE,通过PTE指向基址 + 11-00位定位页内偏移每个进程都有一个CR3(CR3是一个寄存器,每个核心一个) CR3指向一个物理页(4KB),2-9-9-12分页模式下CR3指向PDPT分页规则物理页: 4KB(4096BYTE)09: PDE(8BYTE),物理页(4KB),一张物理页可以存储 4096 / 8 (512),要遍历每一个PDE 2^909: PTE(8BYTE),物理页(4KB),一张物理页可以存储 4096 / 8 (512),要遍历每一个PTE 2^912: 物理页(4KB),要遍历每一个字节 2^1202: PDPTE(8BYTE)32位剩余2位 2^2(4)一共4个PDPTE2-9-9-12线性地址上限: 4 * 512 * 512 * 4096 4GB2-9-9-12物理地址上限: 2^36(物理地址宽度)    64GB同一进程内相同物理页 MOV EAX, DWORD PTR DS:[0x12345FFF] MOV EAX, DWORD PTR DS:[0x12345EEE] 线性地址前20位(PDPTE PDE PTE)决定在哪张物理页,后12位(OFFSET)决定页内偏移 PTE规则PTE可以没有物理页,且只能对应一个物理页.多个PTE也可以指向同一个物理页.  1.1 通过线性地址查找对应物理地址

#include #include int main(){        DWORD num = 0x64;        printf("numaddr -> 0x%08x numdata -> 0x%08x \r\n",&num, num);        system("pause");        printf("numaddr -> 0x%08x numdata -> 0x%08x \r\n",&num, num);        system("pause");        return 0;}
有效地址为: 0x0012ff44
线性地址为: 0x0012ff44 + SS.Base(0)
线性地址转换为二进制: 0000 0000 0001 0010 1111 1111 0100 0100
2: 00 0h PDPTE
9: 0 0000 0000 000h PDE
9: 1 0010 1111 12fh PTE
12: 1111 0100 0100 f44h OFFSET
通过Windbg手动查看:
1).通过!process 0 0查找进程CR3

DirBase = Cr3 = PDPT.Base = 0x7ea04440
*2).查找PDPTE(巨细8字节)(PDPT(页目录指针表基址) + PDPTI(页目录指针项索引) 8)**
!dq(8Byte方式)查看物理地址

*3).查找PDE(巨细8字节)(PDT(页目录表基址) + PDI(页目录项索引) 8)**
查找需要将PDPTE后12位抹除(为PDPTE属性)

*4).查找PTE(巨细8字节)(PTT(页表基址) + PTI(页表项索引) 8)**
查找需要将PDE后12位抹除(为PDE属性)

5).查找线性地址对应物理地址(Physical Page + offset)
查找需要将PTE后12位抹除(为PTE属性)

6).修改物理页数据(!ed指令)


1.2 申请内存挂物理页过程

#include #include int main(){        PVOID lp = VirtualAlloc(NULL,0x64,MEM_COMMIT,PAGE_EXECUTE_READWRITE);        if (!lp)        {                printf("VirtualAlloc Fail \r\n");                getchar();        }        printf("mem addr -> 0x%08x \r\n",lp);        system("pause");        memset(lp,0xFF,4);        system("pause");        return 0;}
有效地址为: 0x00150000
线性地址为: 0x00150000 + SS.Base(0)
线性地址转换为二进制: 0000 0000 0001 0101 0000 0000 0000 0000
2: 00 0h PDPTE
9: 0 0000 0000 000h PDE
9: 1 0101 0000 150h PTE
12: 0000 0000 0000 000h OFFSET
通过Windbg手动查看:
1).通过!process 0 0 查找进程CR3

DirBase = Cr3 = PDPT.Base = 0x7ea04440
*2).查找PDPTE(巨细8字节)(PDPT(页目录指针表基址) + PDPTI(页目录指针项索引) 8)**
!dq(8Byte方式)查看物理地址

*3).查找PDE(巨细8字节)(PDT(页目录表基址) + PDI(页目录项索引) 8)**
查找需要将PDPTE后12位抹除(为PDPTE属性)

*4).查找PTE(巨细8字节)(PTT(页表基址) + PTI(页表项索引) 8)**
查找需要将PDE后12位抹除(为PDE属性)

5).实行初始化内存代码

*6).查找PTE(巨细8字节)(PTT(页表基址) + PTI(页表项索引) 8)**
查找需要将PDE后12位抹除(为PDE属性)

7).查找线性地址对应物理地址(Physical Page + offset)
查找需要将PTE后12位抹除(为PTE属性)

使用virtualalloc函数在申请内存成功情况下如果不初始化将不会被挂有效物理页
1.3 什么是共享内存?(多个线性地址共用一个或多个物理页)

进程A代码
#include #include int main(){        int num = 1;        printf("numaddr -> 0x%08x numdata -> 0x%08x \r\n",&num , num);        system("pause");        printf("numaddr -> 0x%08x numdata -> 0x%08x \r\n",&num , num);        system("pause");        return 0;}进程B代码
#include #include int main(){        system("pause");        printf("0data -> 0x%08x \r\n",*(LPDWORD)(0 + 0xf44));        *(LPDWORD)(0 + 0xf44) = 0xffffffff;        system("pause");        return 0;}1).打开进程A查看变量所对应物理地址


2).打开进程B给0线性地址挂物理页

3).实行进程B剩余代码

4).实行进程A剩余代码
进程B代码实行后将会同时修改进程A变量数据,由于此时指向同一张物理页且页内偏移相同

数据被成功修改
2.2-9-9-12分页PDE PTE属性探测

测试代码使用内核函数MmIsAddressValid实现原理后文将分析
如果代码实行后不生效TLB(后需章节介绍)没有刷新,切换进程或打开新进程后在运行

2.1 P位

P = 1 有效的物理页
P = 0 无效的物理页
#include #include DWORD g_Data = 0x12345678;DWORD g_offs = (DWORD)&g_Data & 0xFFF;DWORD g_PDE = 0;DWORD g_PTE = 0;_declspec(naked) VOID ChangePTEAttribute(){  __asm  {    //获取线性地址    lea ecx, g_Data    //获取PDE    mov eax, ecx    shr eax, 0x12    and eax, 0x3FF8    sub eax, 0x3FA00000    mov eax, [eax]    mov g_PDE, eax    //PDE->P    test al, 1    jz END    //获取PTE    mov eax, ecx    shr eax, 0x9    and eax, 0x7FFFF8    sub eax, 0x40000000    mov eax, [eax]    mov g_PTE, eax    //PTE->P    test al, 1    jz END    //获取线性地址    mov ecx, 0    //PTE    mov eax, ecx    shr eax, 0x9    and eax, 0x7FFFF8    sub eax, 0x40000000    mov edx, g_PTE    mov [eax], edxEND:    iretd  }}int main(){  printf("INTERRUPT ADDR [0x%08x]  \n",ChangePTEAttribute);  printf("ADDR [0x%08x]  DATA [0x%08x] OFFS [0x%03x]  \n",&g_Data, g_Data, g_offs);    system("Pause");  __asm  {          //通过停止门给0线性地址挂物理页          //eq 80b99500 0040ee00`00081005          INT 0x20  }  *(LPDWORD)(0 + g_offs) = 0xFFFFFFFF;   printf("ADDR [0x%08x]  DATA [0x%08x] OFFS [0x%03x]  \n",&g_Data, g_Data, g_offs);  system("Pause");  return 0;}
变量地址为:0x00412030 转换为二进制 0000 0000 0100 0001 0010 0000 0011 0000
按照2-9-9-12分页格式转换:
2: 00 0h PDPTE
9: 0 0000 0010 002h PDE
9: 0 0001 0010 012h PTE
12: 0000 0011 0000 030h OFFSET
通过Windbg手动查看:
1).通过!process 0 0查看进程CR3

DirBase = Cr3 = PDPT.Base = 0x7eb54460
*2).查找PDPTE(巨细8字节)(PDPT(页目录指针表基址) + PDPTI(页目录指针项索引) 8)**
!dq(8Byte方式)查看物理地址

*3).查找PDE(巨细8字节)(PDT(页目录表基址) + PDI(页目录项索引) 8)**
查找需要将PDPTE后12位抹除(为PDPTE属性)

*4).查找PTE(巨细8字节)(PTT(页表基址) + PTI(页表项索引) 8)**
查找需要将PDE后12位抹除(为PDE属性)

5).查找线性地址对应物理地址(Physical Page + offset)
查找需要将PTE后12位抹除(为PTE属性)

变量线性地址0x00412030对应物理地址为:#055491030
0线性地址默认不可访问是由于没有挂有效物理地址

上述代码实行完毕后将0线性地址对应物理地址改为变量所对应物理地址,即0线性地址此时存在有效物理页
2.2 R/W位

R/W = 0 只读
R/W = 1 可读可写
#include #include CHAR* Data = "HHHHHH";DWORD g_PDE = 0;DWORD g_PTE = 0;_declspec(naked) VOID ChangePTEAttribute(){  __asm  {  //获取线性地址  mov ecx, Data  //获取PDE  mov eax, ecx  shr eax, 0x12  and eax, 0x3FF8  sub eax, 0x3FA00000  mov eax, [eax]  mov g_PDE, eax  //PDE->P  test al, 1  jz END  //获取PTE  mov eax, ecx  shr eax, 0x9  and eax, 0x7FFFF8  sub eax, 0x40000000  mov edx, [eax]  mov g_PTE, edx  //PTE->P  test dl, 1  jz END  //修改R/W位  or dl, 2  mov [eax], edx  mov g_PTE, edxEND:  iretd  }}int main(){        printf("INTERRUPT ADDR [0x%08x]  \n",ChangePTEAttribute);        printf("DATA [%s] %08x\n",Data,&Data[0]);          system("Pause");        __asm        {                //通过停止门修改页属性                //eq 80b99500 0040ee00`00081005                INT 0x20        }        Data[0] = 'A';        printf("DATA [%s] PDE [0x%08x]  PTE [0x%08x]  \n",Data, g_PDE,g_PTE);        system("Pause");        return 0;}
变量地址为:0x0041010C 转换为二进制 0000 0000 0100 0001 0000 0001 0000 1100
按照2-9-9-12分页格式转换:
2: 00 0h PDPTE
9: 0 0000 0010 002h PDE
9: 0 0001 0000 010h PTE
12: 0001 0000 1100 10Ch OFFSET
通过Windbg手动查看:
1).通过!process 0 0查看进程CR3

DirBase = Cr3 = PDPT.Base = 0x7eb54560
*2).查找PDPTE(巨细8字节)(PDPT(页目录指针表基址) + PDPTI(页目录指针项索引) 8)**
!dq(8Byte方式)查看物理地址

*3).查找PDE(巨细8字节)(PDT(页目录表基址) + PDI(页目录项索引) 8)**
查找需要将PDPTE后12位抹除(为PDPTE属性)

*4).查找PTE(巨细8字节)(PTT(页表基址) + PTI(页表项索引) 8)**
查找需要将PDE后12位抹除(为PDE属性)

5).查找线性地址对应物理地址(Physical Page + offset)
查找需要将PTE后12位抹除(为PTE属性)

变量线性地址0x0041010C对应物理地址为:#04c01310c

常量字符串不可以修改是由于物理页属性限制修改R/W位即可改写
2.3 U/S位

U/S = 0 特权用户
U/S = 1 平凡用户
2G以上是内核才能访问的缘故起因是U/S位的设置问题,如果将内核的某个页设置为1就可以在R3访问了.
0 1 2是系统环可以访问系统页和用户页0环是特权级环1, 2环固然不是特权级环 但是是系统环 3环是用户环 可以访问用户页.
#include #include DWORD g_PDE = 0;DWORD g_PTE = 0;_declspec(naked) VOID ChangePTEAttribute(){  __asm  {    //获取线性地址    mov ecx, 0x80b99008    //获取PDE    mov eax, ecx    shr eax, 0x12    and eax, 0x3FF8    sub eax, 0x3FA00000    mov edx, [eax]    test dl, 1    jz END    or dl, 4    mov [eax], edx    mov g_PDE, edx    //获取PTE    mov eax, ecx    shr eax, 0x9    and eax, 0x7FFFF8    sub eax, 0x40000000    mov edx, [eax]    test dl, 1    jz END    //全局页修改G位        and edx, 0xFFFFFEFF    //修改U/S位    or dl, 4    mov [eax], edx    mov g_PTE, edxEND:    iretd  }}int main(){  printf("INTERRUPT ADDR [0x%08x]  \n",ChangePTEAttribute);  system("Pause");  __asm  {    //通过停止门提权修改页属性    //eq 80b99500 0040ee00`00081005    INT 0x20  }  printf("PDE [0x%08x]  PTE [0x%08x] \n",g_PDE,g_PTE);  printf("DATA [0x%08x] \n",*(LPDWORD)0x80b99008);  system("Pause");  return 0;} 线性地址为:0x80b99008 转换为二进制 1000 0000 1011 1001 1001 0000 0000 1000
按照2-9-9-12分页格式转换:
2: 10 2h PDPTE
9: 0 0000 0101 005h PDE
9: 1 1001 1001 199h PTE
12: 0000 0000 1000 008h OFFSET
通过Windbg手动查看:
1).通过!process 0 0查看进程CR3

DirBase = Cr3 = PDPT.Base = 0x7eb54280
*2).查找PDPTE(巨细8字节)(PDPT(页目录指针表基址) + PDPTI(页目录指针项索引) 8)**
!dq(8Byte方式)查看物理地址

*3).查找PDE(巨细8字节)(PDT(页目录表基址) + PDI(页目录项索引) 8)**
查找需要将PDPTE后12位抹除(为PDPTE属性)

*4).查找PTE(巨细8字节)(PTT(页表基址) + PTI(页表项索引) 8)**
查找需要将PDE后12位抹除(为PDE属性)

5).查找线性地址对应物理地址(Physical Page + offset)
查找需要将PTE后12位抹除(为PTE属性)

线性地址0x80b99008对应物理地址为:#b99008

应用层不可以访问高2G内存是由于物理页属性限制修改U/S位即可改写
2.4 PS位

只对PDE有意义
PS = 0 指向PTE

PS = 1 没有PTE 直接指向物理页 低21位是页内偏移 大页(2 ^ 21)2MB

2.5 A位

A = 0 未访问(读大概写)
A = 1 已访问(读大概写)
2.6 D位

D = 0 没有被写过
D = 1 被写过
2.7 XD位

段的属性有可读、可写和可实行页的属性有可读、可写当RET实行返回的时候,如果我修改堆栈里面的数据指向一个我提前预备好的数据(把数据当作代码来实行,漏洞都是依赖这点,比如SQL注入也是)所以,Intel就做了硬件保护,做了一个不可实行位,XD=1时。那么你的软件溢出了也没有关系,即使你的EIP蹦到了危险的“数据区”,也是不可以实行的!在PAE分页模式下,PDE与PTE的最高位为XD/NX位.  3.PDT PTT基址

2-9-9-12分页模式1.页表被映射到了从0xC0000000到0xC07FFFFF的8M地址空间(4(PDT) * 512(PTE) * 4096)2.在这1024个表中有一张特殊的表:页目录表3.页目录被映射到了0xC0600000开始处的16K地址空间0xc0600000 指向页目录表(PDT)0xc0000000 指向第一张页表(PTT)页目录表着实是一张特殊的页表,它是第0x600张页表。页目录表中每项PTE都指向一张页表,其中第0x600项指向了页目录表自己PDPI(PDPE INDEX) PDI(PDE INDEX) PTI(PTE INDEX)访问页目录表的公式:0xC0600000 + PDPI * 4KB + PDI * 8访问页表的公式:0xC0000000 + PDPI * 2MB + PDI * 4KB + PTI * 84.MmIsAddressValid(Win7 x86 2-9-9-12)

.text:00411717                                                 ; BOOLEAN __stdcall MmIsAddressValid(PVOID VirtualAddress).text:00411717                                                                 public _MmIsAddressValid@4.text:00411717                                                 _MmIsAddressValid@4 proc near           ; CODE XREF: IopIsAddressRangeValid(x,x)+31↑p.text:00411717                                                                                         ; sub_4C9A84+13↓p ....text:00411717.text:00411717                                                 VirtualAddress  = dword ptr  8.text:00411717.text:00411717 8B FF                                                           mov     edi, edi        ; 热补丁.text:00411719 55                                                              push    ebp.text:0041171A 8B EC                                                           mov     ebp, esp        ; 提拔栈底.text:0041171C 8B 55 08                                                        mov     edx, [ebp+VirtualAddress] ; edx = 线性地址(Param).text:0041171F E8 84 33 0A 00                                                  call    _MiIsAddressValid@8 ; MiIsAddressValid(x,x).text:00411724 5D                                                              pop     ebp             ; 恢复栈底.text:00411725 C2 04 00                                                        retn    4               ; 返回.text:00411725                                                 _MmIsAddressValid@4 endp.text:004B4AA8                                                 ; __stdcall MiIsAddressValid(x, x).text:004B4AA8                                                 _MiIsAddressValid@8 proc near           ; CODE XREF: MiMakeSystemAddressValidSystemWs(x,x)+E↑p.text:004B4AA8                                                                                         ; MiMakeSystemAddressValidSystemWs(x,x)+10C↑p ....text:004B4AA8.text:004B4AA8                                                 var_8           = dword ptr -8.text:004B4AA8                                                 var_4           = dword ptr -4.text:004B4AA8.text:004B4AA8 8B FF                                                           mov     edi, edi        ; 热补丁.text:004B4AAA 55                                                              push    ebp.text:004B4AAB 8B EC                                                           mov     ebp, esp        ; 提拔栈底.text:004B4AAD 51                                                              push    ecx.text:004B4AAE 51                                                              push    ecx             ; 保存寄存器数据.text:004B4AAF 8B C2                                                           mov     eax, edx        ; eax = 线性地址.text:004B4AB1 C1 E8 12                                                        shr     eax, 12h        ; eax 右移 18位.text:004B4AB4 25 F8 3F 00 00                                                  and     eax, 3FF8h      ; (eax >> 0x12) & 0x3FF8(0011 1111 1111 1000) == PDPTI * 4KB + PDI * 8.text:004B4AB9 2D 00 00 A0 3F                                                  sub     eax, 3FA00000h  ; sub 0x3FA00000 = add 0xC0600000.text:004B4AB9                                                                                         ; 0xC0600000是页目录表被映射的起始线性地址.text:004B4ABE 8B 08                                                           mov     ecx, [eax]      ; 取出PDE低4字节数据存入ecx.text:004B4AC0 8B 40 04                                                        mov     eax, [eax+4]    ; 取出PDE高4字节数据存入eax.text:004B4AC3 89 45 FC                                                        mov     [ebp-4], eax    ; 将PDE高4字节数据存储在局部变量ebp - 4 中.text:004B4AC6 8B C1                                                           mov     eax, ecx        ; PDE低4字节(大部分属性位在低12位)放入eax.text:004B4AC8 83 E0 01                                                        and     eax, 1          ; 与运算判定P位是否为1.text:004B4ACB 6A 00                                                           push    0.text:004B4ACD 89 45 F8                                                        mov     [ebp-8], eax.text:004B4AD0 58                                                              pop     eax.text:004B4AD1 74 04                                                           jz      short loc_4B4AD7 ; P位为0无效页跳转返回.text:004B4AD3 85 C0                                                           test    eax, eax.text:004B4AD5 74 04                                                           jz      short loc_4B4ADB.text:004B4AD7.text:004B4AD7                                                 loc_4B4AD7:                             ; CODE XREF: MiIsAddressValid(x,x)+29↑j.text:004B4AD7 32 C0                                                           xor     al, al          ; 清空al.text:004B4AD9 C9                                                              leave                   ; mov esp, ebp.text:004B4AD9                                                                                         ; pop ebp.text:004B4ADA C3                                                              retn                    ; 返回.text:004B4ADB                                                 ; ---------------------------------------------------------------------------.text:004B4ADB.text:004B4ADB                                                 loc_4B4ADB:                             ; CODE XREF: MiIsAddressValid(x,x)+2D↑j.text:004B4ADB 56                                                              push    esi             ; 保留寄存器数据.text:004B4ADC BE 80 00 00 00                                                  mov     esi, 80h ; '?'  ; esi = 0x80.text:004B4AE1 23 CE                                                           and     ecx, esi        ; PDE低4字节与0x80进行与运算 判定是否是大页.text:004B4AE3 6A 00                                                           push    0.text:004B4AE5 89 4D F8                                                        mov     [ebp-8], ecx.text:004B4AE8 58                                                              pop     eax.text:004B4AE9 74 04                                                           jz      short loc_4B4AEF ; 小页跳转.text:004B4AEB 85 C0                                                           test    eax, eax.text:004B4AED 74 3C                                                           jz      short loc_4B4B2B ; 大页跳转返回.text:004B4AEF.text:004B4AEF                                                 loc_4B4AEF:                             ; CODE XREF: MiIsAddressValid(x,x)+41↑j.text:004B4AEF C1 EA 09                                                        shr     edx, 9          ; edx 右移 9 位.text:004B4AF2 81 E2 F8 FF 7F 00                                               and     edx, 7FFFF8h    ; (edx >> 9) & 0x7FFFF8(0111 1111 1111 1111 1111 1000) = PDPTI * 2MB + PDI * 4KB + PTI * 8.text:004B4AF8 8B 8A 04 00 00 C0                                               mov     ecx, [edx-3FFFFFFCh] ; 获取PTE高4字节数据存入ecx.text:004B4AF8                                                                                         ; sub 0x3FFFFFFC = add 0xC0000004.text:004B4AFE 81 EA 00 00 00 40                                               sub     edx, 40000000h.text:004B4B04 8B 02                                                           mov     eax, [edx]      ; 获取PTE低4字节数据存入edx.text:004B4B04                                                                                         ; sub 0x40000000 = add 0xC0000000.text:004B4B04                                                                                         ; 0xC0000000是页表被映射的起始线性地址.text:004B4B06 89 4D FC                                                        mov     [ebp-4], ecx.text:004B4B09 8B C8                                                           mov     ecx, eax        ; ecx = PTE低4字节数据.text:004B4B0B 83 E1 01                                                        and     ecx, 1          ; 判定PTE.P位是否为1.text:004B4B0E 6A 00                                                           push    0.text:004B4B10 89 4D F8                                                        mov     [ebp-8], ecx.text:004B4B13 59                                                              pop     ecx.text:004B4B14 74 11                                                           jz      short loc_4B4B27 ; P = 0 无效页跳转返回.text:004B4B16 85 C9                                                           test    ecx, ecx.text:004B4B18 75 0D                                                           jnz     short loc_4B4B27.text:004B4B1A 23 C6                                                           and     eax, esi        ; esi = 0x80 与PTE低4字节进行与运算判定PAT位.text:004B4B1C 51                                                              push    ecx.text:004B4B1D 89 45 F8                                                        mov     [ebp-8], eax.text:004B4B20 58                                                              pop     eax.text:004B4B21 74 08                                                           jz      short loc_4B4B2B ; PAT = 0跳转返回.text:004B4B23 85 C0                                                           test    eax, eax.text:004B4B25 75 04                                                           jnz     short loc_4B4B2B.text:004B4B27.text:004B4B27                                                 loc_4B4B27:                             ; CODE XREF: MiIsAddressValid(x,x)+6C↑j.text:004B4B27                                                                                         ; MiIsAddressValid(x,x)+70↑j.text:004B4B27 32 C0                                                           xor     al, al          ; 清空al.text:004B4B29 EB 02                                                           jmp     short loc_4B4B2D.text:004B4B2B                                                 ; ---------------------------------------------------------------------------.text:004B4B2B.text:004B4B2B                                                 loc_4B4B2B:                             ; CODE XREF: MiIsAddressValid(x,x)+45↑j.text:004B4B2B                                                                                         ; MiIsAddressValid(x,x)+79↑j ....text:004B4B2B B0 01                                                           mov     al, 1           ; al置1.text:004B4B2D.text:004B4B2D                                                 loc_4B4B2D:                             ; CODE XREF: MiIsAddressValid(x,x)+81↑j.text:004B4B2D 5E                                                              pop     esi             ; 恢复esi寄存器数据.text:004B4B2E C9                                                              leave                   ; mov esp, ebp.text:004B4B2E                                                                                         ; pop ebp.text:004B4B2F C3                                                              retn                    ; 返回.text:004B4B2F                                                 _MiIsAddressValid@8 endp5.代码示例

5.1 0线性地址挂物理页

#include #include //PDE PTEDWORD dwCodePDE = 0;DWORD dwCodePTE = 0;DWORD dwZeroPDE = 0;DWORD dwZeroPTE = 0;//PAGELPDWORD g_lp = NULL;VOID _declspec(naked)Fun(){  __asm  {    //CODE PAGE    mov ecx, g_lp    //PDE    mov eax, ecx    shr eax, 0x12    and eax, 0x3FF8    sub eax, 0x3FA00000    mov eax, [eax]    mov dwCodePDE, eax    //PTE    shr ecx, 0x9    and ecx,0x7FFFF8    sub ecx,0x40000000    mov ecx, [ecx]    mov dwCodePTE, ecx    //0 PAGE    xor ecx, ecx    //PDE    mov eax, ecx    shr eax, 0x12    and eax, 0x3FF8    sub eax, 0x3FA00000    mov edx, eax    mov eax, [eax]    mov dwZeroPDE, eax    and eax, eax    jnz FLAG    mov eax, edx    mov edx, dwCodePDE    mov [eax], edxFLAG:    //PTE    shr ecx, 0x9        and ecx, 0x7FFFF8        sub ecx, 0x40000000        mov edx, dwCodePTE        mov [ecx], edx        mov dwZeroPTE, edx        retf  }}int main(){        //PAGE        g_lp = (LPDWORD)VirtualAlloc(NULL,0x100,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);        if (!g_lp)        {                MessageBox(NULL,"VirtualAlloc Fail !","ERROR",MB_OK|MB_ICONERROR);                exit(0);        }        g_lp[0] = 0x12345678;        printf("dwVar Addr = %08x  Data = %08x  PDPI = %x PDI = %x  PTE = %x  Offset = %x \n",                 g_lp,                 g_lp[0],                ((DWORD)g_lp >> 30) & 0x3,                ((DWORD)g_lp >> 21) & 0x1FF,                ((DWORD)g_lp >> 12) & 0x1FF,                ((DWORD)g_lp) & 0xFFF);        printf("Function Addr = %08x \n",Fun);        system("Pause");        //CALL GATE        CHAR calldata[6] = {0,0,0,0,0x48,0};        __asm        {                call fword ptr [calldata]        }        *(LPDWORD)0 = 0xFFFFFFFF;        printf("CODE PDE = %08X  PTE = %08X \n",dwCodePDE, dwCodePTE);        printf("ZERO PDE = %08X  PTE = %08X \n",dwZeroPDE, dwZeroPTE);        printf("Data = %08x \n",g_lp[0]);        system("Pause");        return 0;}
5.2 读取任意线性地址指定长度

#include #include //ADDRDWORD dwAddr;DWORD dwReadLen;//PDE PTE ATTRITUBEDWORD dwPDE[0x1000];DWORD dwPTE[0x1000];//Data BufferBYTE szData[0x1000];//Continue FlagDWORD dwFlag;//asmVOID _declspec(naked)GetAddrData(){  __asm  {    //SAVE DATA    pushad    pushfd    //Stack Save Info    mov eax, dwAddr    mov [esp - 0x4], eax    mov eax, dwReadLen    mov [esp - 0x8], eax    mov eax, 0    mov [esp - 0xC], eax    lea eax, dwPDE    mov [esp - 0x10], eax    lea eax, dwPTE    mov [esp - 0x14], eax    lea eax, szData    mov [esp - 0x18], eaxSTAR:    //Get Addr    mov ecx, [esp - 0x4]    mov eax, [esp - 0xC]    add ecx, eax      //PDE      mov eax, ecx    shr eax, 0x12    and eax, 0x3FF8    sub eax, 0x3FA00000    mov eax, [eax]    //SAVE PDE    mov edx, [esp - 0x10]    mov ebx, [esp - 0xC]    mov [edx + ebx * 4], eax    //CHECK PDE    mov ebx, eax    and ebx, 0x1    JZ END    mov ebx, eax    and ebx, 0x2    jz END    //PTE    mov eax, ecx    shr eax, 0x9    and eax, 0x7FFFF8    sub eax, 0x40000000    mov eax, [eax]    //SAVE PTE    mov edx, [esp - 0x14]    mov ebx, [esp - 0xC]    mov [edx + ebx * 4], eax    //CHECK PTE    mov ebx, eax    and ebx, 0x1    JZ END    mov ebx, eax    and ebx, 0x2    jz END    //Check Over GetData    mov ecx, [esp - 0x4]    mov eax, [esp - 0xC]    add ecx, eax    mov al, byte ptr [ecx]    mov edx, [esp - 0x18]    mov ebx, [esp - 0xC]    mov [edx + ebx * 1], alEND:    //INC Index    mov eax, [esp - 0xC]        add eax, 1        mov [esp - 0xC], eax        //DEC ReadLength and Check        mov eax, [esp - 0x8]        sub eax, 1        mov [esp - 0x8], eax        and eax, eax        jnz STAR        //LOAD DATA        popfd        popad        //RETF EIP CS ESP SS        retf  }}int main(){        //Global Descriptor Insert Data WIN7X86        printf("Descriptor %04xEC00`0008%04x \n",HIWORD(GetAddrData),LOWORD(GetAddrData));        system("Pause");        //Entry        while (0x1F)        {                //Clean and Init                system("cls");                memset(dwPDE,0,sizeof(dwPDE[0]) * (sizeof(dwPDE) / sizeof(dwPDE[0])));                memset(dwPTE,0,sizeof(dwPTE[0]) * (sizeof(dwPTE) / sizeof(dwPTE[0])));                memset(szData,0,sizeof(szData[0]) * (sizeof(szData) / sizeof(szData[0])));                BYTE dwTest[10] = {0};                printf("%08x \n",dwTest);                for (int j = 0; j < 10; j++)                {                        dwTest[j] = j;                }                printf("Please Input Address(HEX) : ");                scanf("%x",&dwAddr);                printf("Please Input Readlen(DEC) : ");                scanf("%d",&dwReadLen);                //Output Info                printf("Addr [0x%08x]  Readlength [%d] \n",dwAddr,dwReadLen);                //CALL GATE                CHAR calldata[6] = {0,0,0,0,0x48,0};                __asm                {                        call fword ptr [calldata]                }                //Output Data                printf("\n");                for (int i = 0; i < dwReadLen; i++)                {                        printf("Addr [0x%08x]  PDE [0x%08x]  PTE[0x%08x]  Data[0x%02x] \n",dwAddr + i, dwPDE, dwPTE, szData);                }                printf("\n");                //Continue or Exit                printf("Continue / Exit [1/0] : ");                scanf("%d",&dwFlag);                if (!dwFlag)                {                        exit(0);                }        }        return 0;}
5.3 使用0x1000线性地址输出页数据

#include #include //PAGELPDWORD g_lp = NULL;DWORD dwPDE;DWORD dwPTE;DWORD dwAdd;//Load PDE PTEVOID _declspec(naked)Fun(){  __asm  {    //SAVE DATA    pushad    pushfd    //Get addr    mov ecx, g_lp    //PDE      mov eax, ecx    shr eax, 0x12    and eax, 0x3FF8    sub eax, 0x3FA00000    mov eax, [eax]    mov dwPDE, eax    //PTE    mov eax, ecx    shr eax, 0x9    and eax, 0x7FFFF8    sub eax, 0x40000000    mov eax, [eax]    mov dwPTE, eax    //Get 0x1000    mov ecx, 0x1000    //PDE    mov eax, ecx    shr eax, 0x12    and eax, 0x3FF8    sub eax, 0x3FA00000    mov edx, eax    mov eax, [eax]    and eax, 0x1    JNZ FLAG    mov eax, edx    mov edx, dwPDE    mov [eax], edxFLAG:    //PTE    mov eax, ecx                shr eax, 0x9                and eax, 0x7FFFF8                sub eax, 0x40000000                mov edx, dwPTE                mov [eax], edx                //LOAD DATA                popfd                popad                //RET                retf  }}int main(){        //virtual Page        g_lp = (LPDWORD)VirtualAlloc(NULL,sizeof(DWORD) * 100,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);        if (!g_lp)        {                MessageBox(NULL,"VirtualAlloc Fail ! ","ERROR",MB_OK|MB_ICONERROR);                exit(0);        }        //intit         for (int i = 0; i < 100; i++)        {                g_lp = (DWORD)&g_lp;        }        dwAdd = 0x1000;        dwPDE = 0;        dwPTE = 0;        printf("Descriptor %04xEC00`0008%04x \n",HIWORD(Fun), LOWORD(Fun));        system("Pause");        system("cls");        //CALL GATE        CHAR calldata[6] = {0,0,0,0,0x48,0};        __asm        {                call fword ptr [calldata]        }        printf("Addr [0x%08x]  PDE[0x%08x]  PTE[0x%08x] \n\n", DWORD(g_lp), dwPDE, dwPTE);        for (int j = 0; j < 100; j++)        {                printf("Addr [0x%08x]  PDE[0x%08x]  PTE[0x%08x]  Data [0x%08x]\n",0x1000 + j * 4,dwPDE,dwPTE,*(LPDWORD)(0x1000 + j * 4));        }        system("Pause");        return 0;}
5.4 0线性地址实行SHELLCODE

#include #include LPVOID g_lp = NULL;DWORD g_PTE = 0;CHAR szData[] = {  0x6a,0x0,0x6a,0x0,0x6a,0x0,0x6a,0x0,//PUSH 0  0xb8,0x0,0x0,0x0,0x0,               //MOV EAX, XXXXXXXX  0xFF,0xd0,                          //CALL EAX  0xC3                                //RET};_declspec(naked)VOID Fun(){  __asm  {    //获取线性地址    mov ecx, g_lp    //获取PTE    mov eax, ecx    shr eax, 0x9    and eax, 0x7FFFF8    sub eax, 0x40000000    mov eax, [eax]    mov g_PTE, eax    //0 PAGE    xor ecx, ecx    //设置PTE    shr ecx, 0x9    and ecx, 0x7FFFF8    sub ecx, 0x40000000    mov edx, g_PTE    mov [ecx], edx    iretd  }}int main(){  //SHELLCODE  *(LPDWORD)&szData[9] = (DWORD)MessageBox;  //GETPAGEDATA    g_lp  = VirtualAlloc(NULL,0x64,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);   //INITMEM  memset(g_lp,0,0x64);  memcpy(g_lp,szData,sizeof(szData));  //SET 0ADDR PTE  printf("FUNADDR [0x%08x] \n",Fun);  system("pause");  __asm  {    //eq 80b99500 0040ee00`00081000    INT 0x20  }  printf("PTE [0x%08x] \n",g_PTE);  __asm  {    mov eax, 0    call eax  }  system("pause");  return 0;}
来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
楼主热帖
回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|12558网页游戏私服论坛 |网站地图

GMT+8, 2024-4-27 03:29 , Processed in 0.125000 second(s), 31 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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