一、保护模式

2022-09-21 20:00:13 浏览数 (3)

一、保护模式

1.1.双机调试

1.添加debug调试模式

2.虚拟机设置

代码语言:javascript复制
\.pipecom1

3.windbg

代码语言:javascript复制
-y SRV*D:mysymbol*http://msdl.microsoft.com/download/symbols -b -k com:port=\.pipecom1,baud=115200,pipe

4.加载符号表

代码语言:javascript复制
lm    		 #查看符号有没有下载成功

ld * 		 #加载所有符号表

1.2.段选择子和段描述符

windbg

代码语言:javascript复制
r gdtr

#d:查看内存   db:一字节  dw:两字节  dd:四字节  dq:八字节
dq 80b97000   

dq 80b97000 L40   #查看多少项

eq #修改

段选择子

ds:0023

代码语言:javascript复制
#0023拆分二进制 0000000000100 0 11

RPL:11  			  ->请求特权级别为3
Ti:0				  ->查找GDT表
index:0000000000100    ->索引为4,查找GDT表索引为4的段描述符
段描述符

段描述符:00cff300`0000ffff

二进制:00000000 1100 1111 1 11 1 0011 00000000

P

代码语言:javascript复制
P=1:有效
P=0:无效

S

代码语言:javascript复制
S=0:表示系统段
S=1:表示代码段或者数据段

Type

D/B

代码语言:javascript复制
#1.Type为代码段时,这个标志被称为D标志
D/B为1:表示默认为32位的地址
D/B为0:表示默认为16位的地址

#2.Type为普通数据段时,这个标志被称为B标志;分为堆栈段和向下扩展的数据段两种情况
堆栈段
D/B为1:使用的是32位的栈指针(ESP)
D/B为0:使用的是16位的栈指针(SP)

向下扩展的数据段
D/B为1:段地址上限为FFFFFFFF
D/B为0:段地址上限为FFFFF

G

代码语言:javascript复制
粒度标志
G=0:段限长以字节为单位
G=1:段限长以4KB为单位

AVL和21位

代码语言:javascript复制
AVL:  可以被系统软件使用
21位: 保留,设置位0

RPL, DPL和CPL

权限

代码语言:javascript复制
RPL:请求的特权级
DPL:描述符特权级
CPL:当前特权级

1.3.调用门

当段描述符的S标志位0,该描述符为系统描述符

  调用门

Offset in Segment

代码语言:javascript复制
函数的逻辑地址

Segment Selector

代码语言:javascript复制
目标代码段的段选择子(提权)

Param Count

代码语言:javascript复制
参数个数

调用门实验

1.vs2008属性修改

代码语言:javascript复制
链接器->常规—>启用增量链接->改成“否”
链接器->高级—>随机基址->改成“禁用”

2.代码

代码语言:javascript复制
// 1.调用门.cpp : 定义控制台应用程序的入口点。
//

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

typedef int (__cdecl *DbgPrintX)(_In_z_ _Printf_format_string_ const char * _Format, ...);
DbgPrintX DbgPrint = NULL;
char * strtest = "abcdefghijklmnrn";

//裸函数
void _declspec(naked)test()
{
	__asm
	{
		push fs;
		push 0x30;
		pop fs;
		mov eax,[strtest];
		push eax;
		call DbgPrint;
		add esp,4;   //__cdecl外平栈,压入一个参数
		pop fs;
		retf;
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	char bufcode []= {0,0,0,0,0x48,0};
	DbgPrint = (DbgPrintX)0x83e2241f;   //u nt!DbgPrint的地址
	printf("function addr = %xrn",test);   //00401000

	system("pause");

	__asm
	{
		call fword ptr bufcode;
	}

	system("pause");
	return 0;
}

 打开DebugView,证明已经提权成功

 3.windbg构建调用门描述符

代码语言:javascript复制
 #函数地址00401000,cs=0008 其它位固定写法
 
0040EC00`00081000   #构建调用门

r gdtr
dq 80b97000
eq 80b97048 0040EC00`00081000

4.堆栈变化

代码语言:javascript复制
#无参 

返回地址
cs
esp
ss

#有参  
返回地址
cs
参数1
参数2
esp
ss

1.4.中断门

中断门描述符

中断门在idt表里面,构建一个类似int 3 功能的中断门描述符

代码语言:javascript复制
eq 80b97500 0040ee00`00081000  #构建中断门

代码

代码语言:javascript复制

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

void _declspec(naked)test()
{
	__asm
	{
		int 3;
		iretd;    //中断门用iretd返回
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	
	printf("%xrn",test);   //00401000
	system("pause");

	__asm
	{
		int 32;
		push 0x3b;
		pop fs;
	}
    
	return 0;
}

查看堆栈变化dds esp

代码语言:javascript复制
#向堆栈中压入五个值
返回地址
CS
EFLAG的IF位
ESP
SS

中断门影响的Eflags位

代码语言:javascript复制
中断门会把 VM TF IF NT 四个位置0
efl = 46

1.5.劫持int 3

1.把idt表中int 3位置处的段选择子0008改为0048(找我们自己构建的段描述符)

2.构建gdt48位置的段描述符

代码语言:javascript复制
#base = 函数地址 - int 3的段偏移 
48位置的base = 00401000 - 83e86c60 = 7C57A3A0

3.DbgPrint的地址

4.代码

代码语言:javascript复制
// 3.int3劫持.cpp : 定义控制台应用程序的入口点。
//

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

typedef int (__cdecl *DbgPrintProc)(_In_z_ _Printf_format_string_ const char * _Format, ...);
DbgPrintProc DbgPrint = NULL;
char * datouyu = NULL;

void _declspec(naked)test()
{
	__asm
	{
		sub esp,8;
		lea eax,haha;
		mov [esp],eax;
		mov [esp 4],0x8;
		jmp fword ptr [esp];
haha:
		add esp,8;
		push fs;
		push 0x30;
		pop fs;
		mov eax,[datouyu];
		push eax;
		call DbgPrint;
		add esp,4
		pop fs;
		mov eax,0x83e86c60  ;  //int 3地址
		jmp eax;

	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	printf("%xrn",test);   //00401000
	DbgPrint = (DbgPrintProc)0x83e5741f; //u nt!DbgPrint的地址
	datouyu = (char *)malloc(30);
	memset(datouyu,0,30);
	memcpy(datouyu,"datouyu!rn",strlen("datouyu!rn"));

	system("pause");

		__asm
	{
		int 3;

	}
	system("pause");
	return 0;
}

1.6.陷进门

陷进门描述符

构建陷进门

代码语言:javascript复制
eq 80b97500 0040ef00`00081000

代码

代码语言:javascript复制
// 4.陷进门.cpp : 定义控制台应用程序的入口点。
//

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

int eflags = 0;

void _declspec(naked)test()
{
	__asm
	{
		pushfd;
		pop eax;
		mov [eflags],eax;
		push fs;
		push 0x30;
		pop fs;
		int 3;
		pop fs;
		iretd;
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	eflags = 0;
	printf("%xrn",test);   //00401000
	system("pause");

	__asm
	{
		int 32;
	}
    printf("%xrn",eflags);
	system("pause");
	return 0;
}

 中断门影响的Eflags位

代码语言:javascript复制
陷进门会把 VM TF NT 三个位 置0
efl = 246

1.7.任务段

1.TSS

2.TSS描述符

3.操作系统默认的tr为28

 4.查看TSS结构

代码语言:javascript复制
kd> dt _KTSS
ntdll!_KTSS
    0x000 Backlink         : Uint2B
    0x002 Reserved0        : Uint2B
    0x004 Esp0             : Uint4B
    0x008 Ss0              : Uint2B
    0x00a Reserved1        : Uint2B
    0x00c NotUsed1         : [4] Uint4B
    0x01c CR3              : Uint4B
    0x020 Eip              : Uint4B
    0x024 EFlags           : Uint4B
    0x028 Eax              : Uint4B
    0x02c Ecx              : Uint4B
    0x030 Edx              : Uint4B
    0x034 Ebx              : Uint4B
    0x038 Esp              : Uint4B
    0x03c Ebp              : Uint4B
    0x040 Esi              : Uint4B
    0x044 Edi              : Uint4B
    0x048 Es               : Uint2B
    0x04a Reserved2        : Uint2B
    0x04c Cs               : Uint2B
    0x04e Reserved3        : Uint2B
    0x050 Ss               : Uint2B
    0x052 Reserved4        : Uint2B
    0x054 Ds               : Uint2B
    0x056 Reserved5        : Uint2B
    0x058 Fs               : Uint2B
    0x05a Reserved6        : Uint2B
    0x05c Gs               : Uint2B
    0x05e Reserved7        : Uint2B
    0x060 LDT              : Uint2B
    0x062 Reserved8        : Uint2B
    0x064 Flags            : Uint2B
    0x066 IoMapBase        : Uint2B
    0x068 IoMaps           : [1] _KiIoAccessMap
    0x208c IntDirectionMap  : [32] UChar

Previous Task Link存放的是上一个任务的段选择子

5.在gdt表48位置构建任务段

代码语言:javascript复制
eq 80b97048 0000e940`503020ac     #TSS地址为00405030   limit为20ac

6.代码

代码语言:javascript复制
// 5.任务段.cpp : 定义控制台应用程序的入口点。
//

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

struct _KiIoAccessMap
{
    UCHAR DirectionMap[32];                                                 //0x0
    UCHAR IoMap[8196];                                                      //0x20
}; 

typedef struct _KTSS
{
    USHORT Backlink;                                                        //0x0
    USHORT Reserved0;                                                       //0x2
    ULONG Esp0;                                                             //0x4
    USHORT Ss0;                                                             //0x8
    USHORT Reserved1;                                                       //0xa
    ULONG NotUsed1[4];                                                      //0xc
    ULONG CR3;                                                              //0x1c
    ULONG Eip;                                                              //0x20
    ULONG EFlags;                                                           //0x24
    ULONG Eax;                                                              //0x28
    ULONG Ecx;                                                              //0x2c
    ULONG Edx;                                                              //0x30
    ULONG Ebx;                                                              //0x34
    ULONG Esp;                                                              //0x38
    ULONG Ebp;                                                              //0x3c
    ULONG Esi;                                                              //0x40
    ULONG Edi;                                                              //0x44
    USHORT Es;                                                              //0x48
    USHORT Reserved2;                                                       //0x4a
    USHORT Cs;                                                              //0x4c
    USHORT Reserved3;                                                       //0x4e
    USHORT Ss;                                                              //0x50
    USHORT Reserved4;                                                       //0x52
    USHORT Ds;                                                              //0x54
    USHORT Reserved5;                                                       //0x56
    USHORT Fs;                                                              //0x58
    USHORT Reserved6;                                                       //0x5a
    USHORT Gs;                                                              //0x5c
    USHORT Reserved7;                                                       //0x5e
    USHORT LDT;                                                             //0x60
    USHORT Reserved8;                                                       //0x62
    USHORT Flags;                                                           //0x64
    USHORT IoMapBase;                                                       //0x66
    struct _KiIoAccessMap IoMaps[1];                                        //0x68
    UCHAR IntDirectionMap[32];                                              //0x208c
}KTSS; 

KTSS tss={0}; 

//申请栈空间
char bufEsp0[0x2000]={0};
char bufEsp3[0x2000]={0};

void __declspec(naked) test()
{
	__asm
	{
		int 3;
		pushfd;
		pop eax;
		or eax,0x4000;   //int 3会把efl的NT位置0,所有这里需要手动把Eflags的NT位置1
		push eax;
		popfd;
		iretd;
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	//tss.
	memset(bufEsp0,0,0x2000);
	memset(bufEsp3,0,0x2000);

	tss.Esp0 = (ULONG)bufEsp0   0x1FF0;  //堆栈是从大地址往小地址方向
	tss.Esp = (ULONG)bufEsp3   0x1FF0;
	tss.Ss0 = 0x10;
	tss.Ss = 0x10;
	tss.Cs = 0x8;
	tss.Ds = 0x23;
	tss.Es = 0x23;
	tss.Fs = 0x30;
	tss.EFlags = 2;
	tss.Eip = (ULONG)test;
	tss.IoMapBase = 0x20ac;

	printf("%xrn",sizeof(tss));
	printf("请输入的你的CR3:");
	DWORD dwCr3 = 0;
	scanf("%x",&dwCr3);   //输入CR3地址,!process 0 0 查看当前调试程序的cr3
	tss.CR3 = dwCr3;

	printf("%xrn",&tss);   //tss任务段地址
	system("pause");
	
	char bufcode[]={0,0,0,0,0x48,0};   //执行构建的任务段,执行完需要手动修复cr3
	
	__asm
	{
		call fword ptr bufcode;
	}
	system("pause");
	return 0;
}

7.手动修复cr3,使程序能正常返回。执行到打印TSS地址那里,然后进windbg手动修复cr3

代码语言:javascript复制
dg 28
dt _KTSS 801e4000
ed 801e4000 1c 7edae7a0

1.8.任务门

1.任务门

16-31位是任务段的选择子

2.代码

代码语言:javascript复制
// 6.任务门.cpp : 定义控制台应用程序的入口点。
//

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

struct _KiIoAccessMap
{
    UCHAR DirectionMap[32];                                                 //0x0
    UCHAR IoMap[8196];                                                      //0x20
}; 

typedef struct _KTSS
{
    USHORT Backlink;                                                        //0x0
    USHORT Reserved0;                                                       //0x2
    ULONG Esp0;                                                             //0x4
    USHORT Ss0;                                                             //0x8
    USHORT Reserved1;                                                       //0xa
    ULONG NotUsed1[4];                                                      //0xc
    ULONG CR3;                                                              //0x1c
    ULONG Eip;                                                              //0x20
    ULONG EFlags;                                                           //0x24
    ULONG Eax;                                                              //0x28
    ULONG Ecx;                                                              //0x2c
    ULONG Edx;                                                              //0x30
    ULONG Ebx;                                                              //0x34
    ULONG Esp;                                                              //0x38
    ULONG Ebp;                                                              //0x3c
    ULONG Esi;                                                              //0x40
    ULONG Edi;                                                              //0x44
    USHORT Es;                                                              //0x48
    USHORT Reserved2;                                                       //0x4a
    USHORT Cs;                                                              //0x4c
    USHORT Reserved3;                                                       //0x4e
    USHORT Ss;                                                              //0x50
    USHORT Reserved4;                                                       //0x52
    USHORT Ds;                                                              //0x54
    USHORT Reserved5;                                                       //0x56
    USHORT Fs;                                                              //0x58
    USHORT Reserved6;                                                       //0x5a
    USHORT Gs;                                                              //0x5c
    USHORT Reserved7;                                                       //0x5e
    USHORT LDT;                                                             //0x60
    USHORT Reserved8;                                                       //0x62
    USHORT Flags;                                                           //0x64
    USHORT IoMapBase;                                                       //0x66
    struct _KiIoAccessMap IoMaps[1];                                        //0x68
    UCHAR IntDirectionMap[32];                                              //0x208c
}KTSS; 

KTSS tss={0}; 

//申请栈空间
char bufEsp0[0x2000]={0};
char bufEsp3[0x2000]={0};

void __declspec(naked) test()
{
	__asm
	{
		int 3;
		pushfd;
		pop eax;
		or eax,0x4000;   //int 3会把efl的NT位置0,所有这里需要手动把Eflags的NT位置1
		push eax;
		popfd;
		iretd;
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	//tss.
	memset(bufEsp0,0,0x2000);
	memset(bufEsp3,0,0x2000);

	tss.Esp0 = (ULONG)bufEsp0   0x1FF0;  //堆栈是从大地址往小地址方向
	tss.Esp = (ULONG)bufEsp3   0x1FF0;
	tss.Ss0 = 0x10;
	tss.Ss = 0x10;
	tss.Cs = 0x8;
	tss.Ds = 0x23;
	tss.Es = 0x23;
	tss.Fs = 0x30;
	tss.EFlags = 2;
	tss.Eip = (ULONG)test;
	tss.IoMapBase = 0x20ac;

	printf("%xrn",sizeof(tss));
	printf("请输入的你的CR3:");
	DWORD dwCr3 = 0;
	scanf("%x",&dwCr3);   //输入CR3地址,!process 0 0 查看当前调试程序的cr3
	tss.CR3 = dwCr3;

	printf("%xrn",&tss);   //tss任务段地址
	system("pause");
	
	//char bufcode[]={0,0,0,0,0x48,0};   //执行构建的任务段,执行完需要手动修复cr3
	
	__asm
	{
		//call fword ptr bufcode;
		int 32
	}
	system("pause");
	return 0;
}

3.构建任务门和调用门

代码语言:javascript复制
r gdtr
dq gdtr
eq 80b97048 0000e940`50300068   #48位置构建调用门

r idtr
dq rdtr
eq 80b97500 0000e500`00480000   #500位置构建任务门

4.修复cr3

1.9.101012分页

1.9.1.开启101012分页

1.打开EasyBCD工具

添加新条目--名称--添加新条目

高级设置-->高级-->PAE改为禁用,不执行改为常关

高级设置-->开发-->勾上在内核调试模式下运行windows

2.kernel区分

代码语言:javascript复制
#C:WindowsSystem32
ntoskrnl.exe:101012分页使用的内核
ntkrnlpa.exe:29912分页使用的内核
1.9.2.拆分线性地址

1.用ce搜索记事本内本,得到线性地址0032E310

2.拆分线性地址

代码语言:javascript复制
#线性地址:0032E310
0000 0000 0011 0010 1110  0011 0001 0000     #二进制,从后面12位往前拆

#第一个10位,在最前面补两个0,偏移0
0000 0000 0000   			
#第二个10位,在最前面补两个0,偏移位32E
0011 0010 1110   
#12位,页内偏移310
0011 0001 0000       

3.windbg查看物理地址

代码语言:javascript复制
#1.查看记事本的cr3
!process 0 0   查看notepad cr3= 2ce48000

#2.第一个10
!dd 2ce48000 0*4    #得到地址5bd87867

#3.第二10
5bd87867 把后面三位去掉补000, 结果:5bd87000

!dd 5bd87000  32E*4      #得到地址71d34867

#4.12位
71d34867 把后面三位去掉补000, 结果:71d34000

!db 71d34000 310      #得到物理地址对应的内存数据

实验

1.9.3.PDT,PDE,PTT,PTE

物理页结构

代码语言:javascript复制
cr3:是页目录表基址
PDT:页目录表。每一个元素称为页目录项PDE,总共4K大小。4个字节组成一个元素,总共1024个PDE
PDE:页目录表项。每个页目录表项指向一个页表PTT
PTT:页表。每一个元素称为页表项PTE,总共4k大小。4个字节组成一个元素,总共1024个PTE
PTE:页表项。页表项指向的才是真正的物理页

1.10.零地址

实验目的:把A进程的物理页挂到B进程的0地址上,通过远程线程跑起来

1.0地址执行代码.cpp

代码语言:javascript复制
// 07.0地址执行代码.cpp : 定义控制台应用程序的入口点。
//

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

int _tmain(int argc, _TCHAR* argv[])
{
	int*x =  NULL;
	PVOID mem = VirtualAlloc(0,0x100,MEM_COMMIT,PAGE_EXECUTE_READWRITE);  //申请内存

	printf("%xrn	",mem);  
	char bufcode[]=
	{
		//硬编码
		0x6A,0,
		0x6A,0,
		0x6A,0,
		0x6A,0,
		0xb8,0,0,0,0,
		0xff,0xd0,
		0xc2,4,0
		
	};

	char user32[]={'u','s','e','r','3','2','.','d','l','l',0};
	char MessageBoxAA[]={"MessageBoxA"};

	HMODULE hmodule = LoadLibraryA(user32);
	ULONG messageBox = (ULONG)GetProcAddress(hmodule,MessageBoxAA);
	*(PULONG)&bufcode[9] = messageBox;
	memcpy(mem,bufcode,sizeof(bufcode));

	system("pause");
	
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE,3576);  //另一个进程的pid

	HANDLE hThread = CreateRemoteThread(hProcess,NULL,NULL,0,NULL,NULL,NULL);
	
	CloseHandle(hThread);
	system("pause");

	printf("%xrn",*x);
	
	system("pause");
	
	return 0;
}

2.test.cpp

代码语言:javascript复制
// 07.0地址执行代码.cpp : 定义控制台应用程序的入口点。
//


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

int _tmain(int argc, _TCHAR* argv[])
{
	int*x =  NULL;
	PVOID mem = VirtualAlloc(0,0x100,MEM_COMMIT,PAGE_EXECUTE_READWRITE);  //申请内存

	printf("%xrn	",mem);  
	char bufcode[]=
	{
		//硬编码
		0x6A,0,
		0x6A,0,
		0x6A,0,
		0x6A,0,
		0xb8,0,0,0,0,
		0xff,0xd0,
		0xc2,4,0
		
	};

	char user32[]={'u','s','e','r','3','2','.','d','l','l',0};
	char MessageBoxAA[]={"MessageBoxA"};

	HMODULE hmodule = LoadLibraryA(user32);
	ULONG messageBox = (ULONG)GetProcAddress(hmodule,MessageBoxAA);
	*(PULONG)&bufcode[9] = messageBox;
	memcpy(mem,bufcode,sizeof(bufcode));

	system("pause");
	
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE,3576);  //另一个进程的pid

	HANDLE hThread = CreateRemoteThread(hProcess,NULL,NULL,0,NULL,NULL,NULL);
	
	CloseHandle(hThread);
	system("pause");

	printf("%xrn",*x);
	
	system("pause");
	

	return 0;
}

3.挂物理页

把A进程的PTE挂到test进程的0地址

1.11.页属性

P

代码语言:javascript复制
0:表示不在内存中
1:表示在物理内存中

R/W

代码语言:javascript复制
0:只读
1:可读可写

U/S

代码语言:javascript复制
0:该页为超级用户权限
1:该页为普通用户权限

A

代码语言:javascript复制
是否曾经被访问过。

D

代码语言:javascript复制
是否曾经被写入过

PS

代码语言:javascript复制
0:页尺寸为4KB,页目录项指向一个页表
1:大页,页尺寸为32位寻址的4MB,页目录项指向一个页

G

代码语言:javascript复制
全局页。当一个页被表明为全局,并且CR4中的启用全局页(PGE)标志被置位时,一旦CR3寄存器被
载入或者发生任务切换,TLB中的页表或者指向页的目录项并不失效。这个标志可以防止使TLB中频繁
使用的页失效

1.12.页基址

1.分析MiIsAddressValid函数

2.通过上面分析得出结论

  • MiIsAddressValid函数只有一个参数,就是线性地址。
  • 判断一个线性地址是否有效,分大页和不是大页两种情况
代码语言:javascript复制
线性地址是否有效
#大页
PDE.p=1, PS=1 ,则有效

#不是大页
PDE.p=1,PS=0, PTE.p=1, PTE.PAT=0 则有效
  • PDE的页基址位C0300000
代码语言:javascript复制
#PDE计算
线性地址右移20位,然后and FFC
PDE:C0300000 上面的结果
  • PTE的页基址位C0000000
代码语言:javascript复制
#PTE计算
线性地址右移10位,然后and 3FFFFC
PDE:C0000000 上面的结果

3.实验证明页基址,拿gdtr当线性地址80b93000

代码语言:javascript复制
线性地址:80b93000
cr3= 7760e000
==================================
!dd 7760e000 202*4    第一个10
===================================
0018a063      把后面三位去掉补000, 结果:0018a000
!dd 0018a000  393*4
===================================
00b93163     把后面三位去掉补000, 结果:00b93000
!dd 00b93000

用页基址的方式查找

代码语言:javascript复制
线性地址:80b93000
#PDE
80b93000 >> 20   #右移20得到80b
80b & FFC    	 #得到808, PDE:C0300000 808

#PTE
80b93*4 & 3FFFFC   #得到202E4C,PTE:C0000000 202E4C

1.13.29912分页

1.13.1.拆分线性地址

1.用ce搜索记事本内本,得到线性地址002244E8

2.拆分线性地址

代码语言:javascript复制
线性地址:00224 4E8
0000 0000 0010 0010 1000 
00	      ->0		
00 0000 001   ->1
0 0010 1000   ->24
4e8                ->4e8

CR3:7edf85c0
PDPTE
!dq 7edf85c0 0*8

PDE
!dq 00000000`653df000 1*8

PTE
!dq 00000000`23b12000 24*8

物理页
!dq 80000000`22c70000 4e8

1.13.2.页基址

分析MiIsAddressValid函数

代码语言:javascript复制
PDE页基址:0xC0600000
PTE页基址:0XC0000000
1.13.3.页属性
代码语言:javascript复制
#XD位
XD=1:不可执行
XD=0:可执行

1.14.缓存

1.WC,WB,WT

代码语言:javascript复制
WC写组合,从L1拿地址,采用hash加密,一次64个字节

WB(write-back)回写,L1缓存,一次4个字节

WT直写

2.PAT,PCD,PWT

PAT(Page Attribute Table)

1.15.TLB

验证TLB的存在

代码语言:javascript复制
1.申请2个地址,分别赋值
2.把第一个地址挂在0地址上,然后访问,取出结果保存变量
3.把第二个地址挂在0地址上,然后访问,取出结果保存变量
4.观察变量1,变量2的结果有什么不同

实验

代码语言:javascript复制
// 08.TLB.cpp : 定义控制台应用程序的入口点。
//

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

PUCHAR addr1 = NULL;
PUCHAR addr2 = NULL;
ULONG temp1=0,temp2 = 0;

void __declspec(naked) test1()
{
	__asm
	{
		pushad;
		pushfd;
		push 0x30;
		pop fs;
	
		mov eax,[addr1];//线性地址1
		shr eax,0x9;    //下面三行汇编代码是取PTE,29912分页
		and eax,0x7ffff8;
		add eax,0xc0000000;
		mov ecx,[eax];   //取PTE低4字节
		mov edx,[eax 4]; //取PTE高4字节
		or ecx,0x100;    //把PTE的G位改成1
		mov dword ptr ds:[0xc0000000],ecx;
		mov dword ptr ds:[0xc0000004],edx;
		mov eax,dword ptr ds:[0];
		mov [temp1],eax;
	
		//mov eax,cr3;
		//mov cr3,eax;   //刷新cr3

		mov eax,[addr2];//线性地址2
		shr eax,0x9;
		and eax,0x7ffff8;
		add eax,0xc0000000;
		mov ecx,[eax];   //取低4字节
		mov edx,[eax 4]; //取高4字节

		mov dword ptr ds:[0xc0000000],ecx;
		mov dword ptr ds:[0xc0000004],edx;

		invlpg dword ptr ds:[0]  //清除0地址页的TLB项目

		mov eax,dword ptr ds:[0];
		mov [temp2],eax;


		push 0x3b;
		pop fs;
		popfd;
		popad;

		retf;
	}
}


int _tmain(int argc, _TCHAR* argv[])
{

	addr1 = (PUCHAR)VirtualAlloc(NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
	addr2 = (PUCHAR)VirtualAlloc(NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
	*(PULONG)addr1 = 0x1000;
	*(PULONG)addr2 = 0x2000;

	temp1 = 0;
	temp2 = 0;

	printf("addr1 = %x,addr2 = %x,test1=%xrn",addr1,addr2,test1);
	system("pause");

	char bufcode[]={0,0,0,0,0x48,0};   //调佣门

	__asm
	{
		call fword ptr bufcode;
	}
	system("pause");
	printf("temp1 = %x,temp2 = %xrn",temp1,temp2);
	system("pause");

	return 0;
}

1.16.控制寄存器

CR2

代码语言:javascript复制
保存出现异常的线性地址

CR0

代码语言:javascript复制
PE=1:开启保护模式
PG=1:开启分页模式
CD=1:关闭所有缓存
AM:对齐位
WP:写保护。wp=0:关闭写保护

CR4

代码语言:javascript复制
PSE:是否允许大页,如果PSE=0,即使PDE.ps=1大页也不生效
PAE:PAE=0是101012分页,PAE=1是29912分页
PGE:页表的G位是否有效,如果PGE=0,即使G=1也无效
SMAP:super mode execute protected #等于1(必须CR0的AM=1),内核(U/S=0)不能执行3环(U/S=1)的代码
SMEO:super mode access protected  #等于1,内核(U/S=0)不能访问3环(U/S=1)的代码

0 人点赞