ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

11.10-10-12分页

2021-09-21 16:35:05  阅读:287  来源: 互联网

标签:10 12 PTE mov 11.10 eax PDE ecx


目录

0.Win7设置10-10-12分页

1.10-10-12分页规则

2.10-10-12分页PDE PTE属性探测

<1>.P位

<2>.R/W位

<3>.U/S位

<4>.PS位

<5>.A位

<6>.D位

3.PDT PTT 基址

4.MmIsAddressValid(Win x86 10-10-12)

5.代码实例

<1>.通过代码给0线性地址挂物理页并读写

<2>.0线性地址实现SHELLCODE


0.Win7设置10-10-12分页

CMD:

关闭指令(开启10-10-12分页)                         
bcdedit /set pae ForceDisable  
bcdedit /set nx AlwaysOff      

开启指令(开启2-9-9-12分页)
bcdedit /set pae forceEnable
bcdedit /set nx OptIn 

1.10-10-12分页规则

x86下每个进程有4GB线性地址空间,但是有些地址无法访问,这是因为线性地址对应物理地址为空或者对应物理页属性限制.

代码示例:
MOV EAX, DWORD PTR DS:[0x12345678]
有效地址: 0x12345678
线性地址: DS.BASE + 0x12345678
物理地址: 10-10-12分页 通过高31-22位定位PDE,通过21-12位定位PTE,通过PTE指向基址 + 11-00位定位页内偏移

每个进程都有一个CR3(CR3是一个寄存器,每个核心一个) CR3指向一个物理页(4KB),10-10-12分页模式下CR3指向PDT

分页规则
物理页: 4KB(4096BYTE)
10: PDE(4BYTE),物理页(4KB),一张物理页可以存储 4096 / 4 (1024),要遍历每一个PDE 2^10
10: PTE(4BYTE),物理页(4KB),一张物理页可以存储 4096 / 4 (1024),要遍历每一个PTE 2^10
12: 物理页(4KB),要遍历每一个字节 2^12

10-10-12线性地址上限: 1024 * 1024 * 4096 4GB
10-10-12物理地址上限: 2^32(物理地址宽度)   4GB

相同物理页 
MOV EAX, DWORD PTR DS:[0x12345FFF] 
MOV EAX, DWORD PTR DS:[0x12345EEE] 
线性地址前20位(PDE PTE)决定在哪张物理页,后12位(OFFSET)决定页内偏移 

PTE规则
PTE可以没有物理页,且只能对应一个物理页.
多个PTE也可以指向同一个物理页.  

2.10-10-12分页PDE PTE属性探测

测试代码使用内核函数MmIsAddressValid实现原理后文将分析

如果代码执行后不生效TLB(后需章节介绍)没有刷新,切换进程或打开新进程后在运行

<1>.P位

P = 1 有效的物理页

P = 0 无效的物理页

#include <stdio.h>
#include <windows.h>

DWORD g_Data = 0x12345678;
DWORD g_offs = (DWORD)&g_Data & 0xFFF;
DWORD g_PDE = 0;
DWORD g_PTE = 0;

_declspec(naked) VOID ChangePTEAttribute()
{
  __asm
  {
    //获取g_Data线性地址
    lea ecx, g_Data
    
    //获取PDE
    mov eax, ecx
    shr eax, 0x14
    and eax, 0xFFC
    sub eax, 0x3FD00000
    mov eax, [eax]
    mov g_PDE, eax
	
    //PDE->P
    test al, 1
    jz END
	
    //获取PTE
    mov eax, ecx
    shr eax, 0xA
    and eax, 0x3FFFFC
    sub eax, 0x40000000
    mov eax, [eax]
    mov g_PTE, eax
	
    //PTE->P
    test al, 1
    jz END
	
    //获取0线性地址
    mov ecx, 0
	
    //0线性地址挂PTE
    mov eax, ecx
    shr eax, 0xA
    and eax, 0x3FFFFC
    sub eax, 0x40000000
    mov edx, g_PTE
    mov [eax], edx
	
END:
    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
	}
	
	//中断门执行返回后 0线性地址与g_Data变量地址对应的为同一张物理页
	*(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

按照10-10-12分页格式转换:

10:00 0000 0001 001h PDE

10:00 0001 0010 012h PTE

12:0000 0011 0000 030h OFFSET

通过Windbg手动查看:

1).通过!process 0 0查找进程CR3

DriBase = Cr3 = PDT.Base = 0x0a207000h

2).查找PDE(大小4字节)(PDT(页目录表基址) + PDI(页目录项索引) * 4)

!dd(4Byte方式)查看物理地址

3).查找PTE(大小4字节)(PTT(页表基址) + PTI(页表项索引) * 4)

查找需要将PDE后12位抹除(为PDE属性)

4).查找线性地址对应物理地址(Physical Page + offset)

查找需要将PTE后12位抹除(为PTE属性)

变量线性地址0x00412030对应物理地址为:#44c94030

0线性地址默认不可访问是因为没有挂有效物理地址

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

<2>.R/W位

R/W = 0 只读

R/W = 1 可读可写

#include <stdio.h>
#include <windows.h>

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, 0x14
    and eax, 0xFFC
    sub eax, 0x3FD00000
    mov eax, [eax]
    mov g_PDE, eax

    //PDE->P
    test al, 1
    jz END

    //获取PTE
    mov eax, ecx
    shr eax, 0xA
    and eax, 0x3FFFFC
    sub eax, 0x40000000
    mov edx, [eax]
    mov g_PTE, edx

    //PTE->P
    test dl, 1
    jz END

    //页属性修改可读可写
    or dl, 2
    mov [eax], edx

END:
    iretd
  }
}

int main()
{
  printf("INTERRUPT ADDR [0x%08x]  \n",ChangePTEAttribute);
  printf("ADDR [0x%08X] DATA [%s] \n",Data, Data);  
  system("Pause");
  
  __asm
  {
	  //通过中断门提权修改页属性
	  //eq 80b99500 0040ee00`00081005
	  INT 0x20
  }
  
  //默认情况Data[0]对应物理页属性为只读 通过修改可以改写
  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

按照10-10-12分页格式转换:

10:00 0000 0001 001h PDE

10:00 0001 0000 010h PTE

12:0001 0000 1100 10Ch OFFSET

通过Windbg手动查看:

1).通过!process 0 0查找进程CR3

DriBase = Cr3 = PDT.Base = 0x492e8000h

2).查找PDE(大小4字节)(PDT(页目录表基址) + PDI(页目录项索引) * 4)

!dd(4Byte方式)查看物理地址

3).查找PTE(大小4字节)(PTT(页表基址) + PTI(页表项索引) * 4)

查找需要将PDE后12位抹除(为PDE属性)

4).查找线性地址对应物理地址(Physical Page + offset)

查找需要将PTE后12位抹除(为PTE属性)

变量线性地址0x0041010C对应物理地址为:#3fe1d10c

常量字符串不可以修改是因为物理页属性限制修改R/W即可改写

<3>.U/S位

U/S = 0 特权用户

U/S = 1 普通用户

2G以上是内核才能访问的原因是U/S位的设置问题,如果将内核的某个页设置为1就可以在R3访问了

0 1 2是系统环可以访问系统页和用户页0环是特权级环1、 2环虽然不是特权级环 但是是系统环 3环是用户环 可以访问用户页

#include <stdio.h>
#include <windows.h>

DWORD g_PDE = 0;
DWORD g_PTE = 0;

_declspec(naked) VOID ChangePTEAttribute()
{
  __asm
  {
    //获取线性地址
    mov ecx, 0x80b99008

    //获取PDE
    mov eax, ecx
    shr eax, 0x14
    and eax, 0xFFC
    sub eax, 0x3FD00000
    mov edx, [eax]

    test dl, 1
    jz END

    or dl, 4
    mov [eax], edx
    mov g_PDE, edx

    //获取PTE
    mov eax, ecx
    shr eax, 0xA
    and eax, 0x3FFFFC
    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, edx

END:
    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);
  //高2G空间默认为特权权限访问修改页属性后用户权限也可以访问
  printf("DATA [0x%08x] \n",*(LPDWORD)0x80b99008);
  system("Pause");
  return 0;
} 

地址为: 0x80B99008 转换为二进制 1000 0000 1011 1001 1001 0000 0000 1000

按照10-10-12分页格式转换:

10:10 0000 0010 202h PDE

10:11 1001 1001 399h PTE

12:0000 0000 1000 008h OFFSET

通过Windbg手动查看:

1).通过!process 0 0查找进程CR3

DriBase = Cr3 = PDT.Base = 0x491ef000h

2).查找PDE(大小4字节)(PDT(页目录表基址) + PDI(页目录项索引) * 4)

!dd(4Byte方式)查看物理地址

3).查找PTE(大小4字节)(PTT(页表基址) + PTI(页表项索引) * 4)

查找需要将PDE后12位抹除(为PDE属性)

4).查找线性地址对应物理地址(Physical Page + offset)

查找需要将PTE后12位抹除(为PTE属性)

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

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

<4>.PS位

只对PDE有意义

PS = 0 指向PTE

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

<5>.A位

A = 0 未访问(读或者写)

A = 1 已访问(读或者写)

<6>.D位

D = 0没有被写过

D = 1被写过

3.PDT PTT 基址

10-10-12分页模式

1.页表被映射到了从0xC0000000到0xC03FFFFF的4M地址空间(1024PTT * 4096)
2.在这1024个表中有一张特殊的表:页目录表
3.页目录被映射到了0xC0300000开始处的4K地址空间

0xc0300000 指向页目录表(PDT)
0xc0000000 指向第一张页表(PTT)
页目录表其实是一张特殊的页表,它是第0x300张页表。
页目录表中每项PTE都指向一张页表,其中第0x300项指向了页目录表自己

PDI(PDE INDEX) PTI(PTE INDEX)

访问页目录表的公式:
0xC0300000 + PDI * 4

访问页表的公式:
0xC0000000 + PDI * 4096 + PTI * 4

4.MmIsAddressValid(Win x86 10-10-12)

内核ntoskrnl.exe 10-10-12 分页

5.代码实例

<1>.通过代码给0线性地址挂物理页并读写

#include <stdio.h>
#include <windows.h>

//读写物理页地址
LPDWORD g_lp = NULL;

//记录PDE PTE
DWORD dwPDE = 0;
DWORD dwPTE = 0;

//0环权限修改PDE PTE
VOID _declspec(naked)Fun()
{
  __asm
  {
    pushad
    pushfd

    //获取物理页
    mov ecx, g_lp

    //PDE
    mov eax, ecx
    shr eax, 0x14
    and eax, 0x0FFC
    sub eax, 0x3FD00000
    mov eax, [eax]
    mov dwPDE, eax

    //PTE
    mov eax, ecx
    shr eax, 0xA
    and eax, 0x3FFFFC
    sub eax, 0x40000000
    mov eax, [eax]
    mov dwPTE, eax
	
    //获取0物理页
    xor ecx, ecx
	
    //PDE
    mov eax, ecx
    shr eax, 0x14
    and eax, 0x0FFC
    sub eax, 0x3FD00000
    //备份对应线性地址
    mov edx, eax
    mov eax, [eax]
	
    //判断是否存在PDE
    and eax, eax
    jnz Flag
    mov ebx, dwPTE
    mov [edx], ebx
	
Flag:
    //PTE
    mov eax, ecx
	shr eax, 0xA
	and eax, 0x3FFFFC
	sub eax, 0x40000000
	
	mov edx, dwPTE
	mov [eax], edx
	
	
	popfd
	popad
	
	retf
  }
  
}

int main()
{
	//Get 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("Data = %08x \n",g_lp[0]);
	system("Pause");
	
	//CALL GATE
	printf("Function Addr = %08x \n",Fun);
	system("Pause");
	CHAR calldata[6] = {0,0,0,0,0x48,0};
	__asm
	{
		call fword ptr [calldata]
	}
	
	printf("PDE = %08X  PTE = %08X \n",dwPDE,dwPTE);
	
	*(LPDWORD)0 = 0xFFFFFFFF;
	printf("Data = %08x \n",g_lp[0]);
	system("Pause");
	
	return 0;
}

<2>.0线性地址实现SHELLCODE

#include <stdio.h>
#include <windows.h>

//PTE PDE
DWORD dwCodePDE = 0;
DWORD dwCodePTE = 0;

DWORD dwZeroPDE = 0;
DWORD dwZeroPTE = 0;

//SHELLCODE
CHAR Data[] =
{
  0x6a,0x00,0x6a,0x00,0x6a,0x00,0x6a,0x00,//PUSH
  0xE8,0x00,0x00,0x00,0x00,        //CALL
  0xc3                  //ret
};

VOID _declspec(naked)Fun()
{
  __asm
  {
    //保留寄存器数据
    pushad
    pushfd

    //获取CODE PAGE
    lea ecx, Data
    
    //PDI
    shr eax, 0x14
    and eax, 0x00000FFC
    sub eax, 0x3FD00000
    mov eax, [eax]
    mov dwCodePDE, eax
    
    //获取LP PTI
    shr ecx, 0xA
    and ecx, 0x003FFFFC
    sub ecx, 0x40000000
    mov eax, [ecx]
    mov dwCodePTE, eax
    
    //0线性地址挂物理页
    xor ecx, ecx
    mov eax, ecx
    
    //PDI
    shr eax, 0x14
    and eax, 0x00000FFC
    sub eax, 0x3FD00000  
    mov edx, eax
    mov eax, [eax]
    mov dwZeroPDE, eax

    //判断PDE是否为0
    and eax, eax
    jnz FLAG

    mov eax, edx
    mov ebx, dwCodePDE
    mov [eax], ebx
    mov dwZeroPDE, ebx
    
FLAG:
    //修改0 PTE
    shr ecx, 0xA
	and ecx, 0x003FFFFC
	sub ecx, 0x40000000
  
	mov edx, dwCodePTE
	mov [ecx], edx
	mov ecx, [ecx]
	mov dwZeroPTE, ecx
        
	//恢复寄存器数据
	popfd
	popad
  
	retf
  }
}


int main()
{
	//获取函数地址
	DWORD dwAddr = (DWORD)MessageBox;
	
	//修正SHELLCODE
	DWORD dwOffset = (DWORD)Data & 0xFFF;
	*(LPDWORD)&Data[9] = dwAddr - (dwOffset + 13);
	
	printf("Function Addr = %08x \n", Fun);
	system("Pause");
	
	//CALL GATE
	CHAR calldata[6] = {0,0,0,0,0x48,0};
	__asm
	{
		call fword ptr [calldata]
		call [dwOffset]
	}
	
	printf("Code PDE = %08x  PTE = %08x \n",dwCodePDE,dwCodePTE);
	printf("Zero PDE = %08x  PTE = %08x \n",dwZeroPDE,dwZeroPTE);
	
	system("Pause");
	return 0;
} 

标签:10,12,PTE,mov,11.10,eax,PDE,ecx
来源: https://blog.csdn.net/m0_46125480/article/details/120400566

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有