前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一、保护模式

一、保护模式

作者头像
zhang_derek
发布2022-09-21 20:00:13
1.1K0
发布2022-09-21 20:00:13
举报
文章被收录于专栏:有趣的django有趣的django

一、保护模式

1.1.双机调试

1.添加debug调试模式

2.虚拟机设置

代码语言:javascript
复制
\\.\pipe\com1

3.windbg

代码语言:javascript
复制
-y SRV*D:\mysymbol*http://msdl.microsoft.com/download/symbols -b -k com:port=\\.\pipe\com1,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 = "abcdefghijklmn\r\n";

//裸函数
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 = %x\r\n",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("%x\r\n",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("%x\r\n",test);   //00401000
	DbgPrint = (DbgPrintProc)0x83e5741f; //u nt!DbgPrint的地址
	datouyu = (char *)malloc(30);
	memset(datouyu,0,30);
	memcpy(datouyu,"datouyu!\r\n",strlen("datouyu!\r\n"));

	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("%x\r\n",test);   //00401000
	system("pause");

	__asm
	{
		int 32;
	}
    printf("%x\r\n",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("%x\r\n",sizeof(tss));
	printf("请输入的你的CR3:");
	DWORD dwCr3 = 0;
	scanf("%x",&dwCr3);   //输入CR3地址,!process 0 0 查看当前调试程序的cr3
	tss.CR3 = dwCr3;

	printf("%x\r\n",&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("%x\r\n",sizeof(tss));
	printf("请输入的你的CR3:");
	DWORD dwCr3 = 0;
	scanf("%x",&dwCr3);   //输入CR3地址,!process 0 0 查看当前调试程序的cr3
	tss.CR3 = dwCr3;

	printf("%x\r\n",&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:\Windows\System32
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("%x\r\n	",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("%x\r\n",*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("%x\r\n	",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("%x\r\n",*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=%x\r\n",addr1,addr2,test1);
	system("pause");

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

	__asm
	{
		call fword ptr bufcode;
	}
	system("pause");
	printf("temp1 = %x,temp2 = %x\r\n",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)的代码
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-08-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、保护模式
    • 1.1.双机调试
      • 1.2.段选择子和段描述符
        • 段描述符
      • 1.3.调用门
        • 1.4.中断门
          • 1.5.劫持int 3
            • 1.6.陷进门
              • 1.7.任务段
                • 1.8.任务门
                  • 1.9.101012分页
                    • 1.9.1.开启101012分页
                    • 1.9.2.拆分线性地址
                    • 1.9.3.PDT,PDE,PTT,PTE
                  • 1.10.零地址
                    • 1.11.页属性
                      • 1.12.页基址
                        • 1.13.29912分页
                          • 1.13.1.拆分线性地址
                          • 1.13.2.页基址
                          • 1.13.3.页属性
                        • 1.14.缓存
                          • 1.15.TLB
                            • 1.16.控制寄存器
                            领券
                            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档