15_TLB中的G属性
》 TLB 是为了增加访问内存的效率
即 如果 是 29 9 12 分页 请求数据 可能需要访问 4次内存;为了解决这个问题;出现了 TLB (虚拟地址到物理地址的转换关系),如果目标地址在TLB缓存中,那么直接从TLB 取出 物理地址;
》 这个实验做起来很麻烦,因为:
TLB 是CPU 内部的,没法通过汇编指令访问TLB;
调试器,也没有办法知道 TLB 中有哪些项
只有通过实验现象 结果,来证明其存在。
内存访问的步骤:

》 注意 TLB 产生异常 3; 不会回到 2;而是产生 0x0E 异常。

1 简单实验查看 快表 带来的影响:
图解:

代码:
// 7_TLB_test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#define PTE(x) ( (DWORD*)(0xc0000000 + ((x >> 12) << 3)))
#define PDE(X) ( (DWORD*)(0xc0600000 + ((x >> 21) << 3)))
DWORD g_out;
#pragma section("data seg", read, write)
_declspec(allocate("data seg"))DWORD pagel[1024]; //41d000
_declspec(allocate("data seg"))DWORD page2[1024]; //41c000
//0x401000
void _declspec(naked) IdtEntry()
{
__asm mov eax, ds: [0x405000]
//确保虚拟地址在TLB中
PTE(0x41c000)[0] = PTE(0x41d000)[0];
PTE(0x41c000)[1] = PTE(0x41d000)[1];
g_out = page2[0];
__asm {
iretd
}
}
void _declspec(naked) go() {
{
pagel[0] = 1; //确保物理页存在
page2[0] = 2;
}
__asm int 0x20
__asm ret
}
//eq 8003f500 0040ee00~ 00081000
void main()
{
if ((DWORD)IdtEntry != 0x401040)
{
printf("wrong addr: %p", IdtEntry);
exit(-1);
}
go();
printf("%d\n", g_out);
system("pause");
}
效果:

蓝屏:
太快了 。。。 截图不到。。。额
解决蓝屏:
由于 是对同一个物理页释放了两次造成了蓝屏;
所以 保存好 原来的pte值;
所以在 中断返回之前,将那个 虚拟页的 pte 修改回来即可
刷新TLB,解决 结果和我们预期差异

这个cr3 的切换 会导致 没有 g 属性的tlb 失效。即清除;
原因很简单,因为 这个 cr3都切换了 tlb 中的虚拟地址没有g属性的;已经在当前cr3 中没有意义了。虽然 这里切换的是自己的,但是一样可以达到效果。
改后的代码:
// 7_TLB_test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#define PTE(x) ( (DWORD*)(0xc0000000 + ((x >> 12) << 3)))
#define PDE(X) ( (DWORD*)(0xc0600000 + ((x >> 21) << 3)))
DWORD g_out;
DWORD g_OldPte[2];
#pragma section("data seg", read, write)
_declspec(allocate("data seg"))DWORD pagel[1024]; //41d000
_declspec(allocate("data seg"))DWORD page2[1024]; //41c000
//0x401000
void _declspec(naked) IdtEntry()
{
// 确保虚拟地址在TLB中
__asm mov eax, ds: [0x405000];
// 保存旧的pte ,以用来恢复pte 解决不蓝屏
g_OldPte[0] = PTE(0x41c000)[0];
g_OldPte[1] = PTE(0x41c000)[1];
PTE(0x41c000)[0] = PTE(0x41d000)[0];
PTE(0x41c000)[1] = PTE(0x41d000)[1];
__asm{
mov eax,cr3
mov cr3,eax
}
g_out = page2[0];
// 恢复到原来的pte
PTE(0x41c000)[0]=g_OldPte[0];
PTE(0x41c000)[1]=g_OldPte[1];
__asm {
iretd
}
}
void _declspec(naked) go() {
{
pagel[0] = 1; //确保物理页存在
page2[0] = 2;
}
__asm int 0x20
__asm ret
}
//eq 8003f500 0040ee00~ 00081000
void main()
{
if ((DWORD)IdtEntry != 0x401040)
{
printf("wrong addr: %p", IdtEntry);
exit(-1);
}
go();
printf("%d\n", g_out);
system("pause");
}
之后的效果:

数据正确了 ,而且没有蓝屏
2 有G属性的TLB 项
查看 pte 有无G位:

一般3环的 pte 没有G位。内核属性为 G位这样TLB 就不会被刷新出去。
设置我们3环的页G位有效--不被刷出TLB:

代码:
// 7_TLB_test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#define PTE(x) ( (DWORD*)(0xc0000000 + ((x >> 12) << 3)))
#define PDE(X) ( (DWORD*)(0xc0600000 + ((x >> 21) << 3)))
DWORD g_out;
DWORD g_OldPte[2];
#pragma section("data seg", read, write)
_declspec(allocate("data seg"))DWORD pagel[1024]; //41d000
_declspec(allocate("data seg"))DWORD page2[1024]; //41c000
//0x401000
void _declspec(naked) IdtEntry()
{
// 确保虚拟地址在TLB中
__asm mov eax, ds: [0x405000];
// 保存旧的pte ,以用来恢复pte 解决不蓝屏
g_OldPte[0] = PTE(0x41c000)[0];
g_OldPte[1] = PTE(0x41c000)[1];
PTE(0x41c000)[0] = PTE(0x41d000)[0]|0x100;// 设置G位
PTE(0x41c000)[1] = PTE(0x41d000)[1];
__asm{
mov eax,cr3
mov cr3,eax
}
// 调用调用;确保在 TL B 中
__asm mov eax, ds:[0x41c000];
// 恢复到原来的pte
//---- 这样
// 按道理 后面一旦后面刷新 TLB 将 普通 TLB 刷新出去,
// 那么 g_out = page2[0] 的值就 应该是 正常 的原 pte 对应的数据 -- 2。
PTE(0x41c000)[0] = g_OldPte[0];
PTE(0x41c000)[1] = g_OldPte[1];
__asm
{
mov eax,cr3
mov cr3,eax
}
g_out = page2[0]; // 讲道理 在非G位下 应该是2(原PTE解析出的) -- 但是这里我们设置了PTE 的G位,
// so 这里应该是 TLB快表中 对应的 1;
__asm {
iretd
}
}
void _declspec(naked) go() {
{
pagel[0] = 1; //确保物理页存在
page2[0] = 2;
}
__asm int 0x20
__asm ret
}
//eq 8003f500 0040ee00~ 00081000
void main()
{
if ((DWORD)IdtEntry != 0x401040)
{
printf("wrong addr: %p", IdtEntry);
exit(-1);
}
go();
printf("%d\n", g_out);
system("pause");
}
测试结果:
果然 G位的TLB 不会被 刷新出去:

当然 还可以强行更新 TLB 项,无视G位:
__asm invlpg ds: [0x41c000] //强行更新TLB项,无视G位

这时候 TLB 中就没有之前那个虚拟地址的TLB 虚拟项了。这时候就是正常的值了。
利用:inline Hook
前面 我们 hook 系统函数 systemfastcallentry 是修改 cr0 无视 WP位 页写保护。
现在我们可以使用 直接 修改 systemfastcallentry( ) 所在的pte;为 可写的状态;并且使用强行刷新TLB 将那个pte在TLB中的数据刷新
PTE(XXX)[0] =...;
PTE(XXX)[1] = ..;
__asm invlpg ds: [XXX] //强行更新TLB项,无视G位
15_TLB中的G属性的更多相关文章
- [翻译svg教程]svg 中的g元素
svg 中的<g>元素用来组织svg元素.如果一组svg元素被g元素包裹了,你可以通过对g元素进行变换(transform),被g元素包裹的元素也将被变换,就好这些被svg包裹的元素是一个 ...
- meta标签中的http-equiv属性使用介绍(转载)
meta是html语言head区的一个辅助性标签.也许你认为这些代码可有可无.其实如果你能够用好meta标签,会给你带来意想不到的效果,meta标签的作用有:搜索引擎优化(SEO),定义页面使用语言, ...
- C++:调整基类成员在派生类中的访问属性的其他方法(同名成员和访问声明)
4.3 调整基类成员在派生类中的访问属性的其他方法 4.3.1 同名函数 在定义派生类的时候,C++语言允许在派生类中说明的成员与基类中的成员名字相同,也就是 说,派生类可以重新说明与基类成员同名的成 ...
- iOS开发——UI篇&文字渐变效果:图层中的mask属性
文字渐变效果:图层中的mask属性 本次文章,主要讲述的是图层中的mask属性,利用它,可以做出文字渐变效果! 一.文字渐变效果: 二.文字渐变实现思路: 1.创建一个颜色渐变层,渐变图层跟文字控件一 ...
- java 对list中对象按属性排序
实体对象类 --略 排序类----实现Comparator接口,重写compare方法 package com.tang.list; import java.util.Comparator; publ ...
- css样式表中四种属性选择器
学习此连接的总结http://developer.51cto.com/art/201009/226158.htmcss样式表中四种属性选择器1> 简易属性 tag[class]{ font-we ...
- js对象中动态读取属性值 动态属性值 js正则表达式全局替换
$(document).ready(function(){ var exceptionMsg = '${exception.message }'; var exceptionstr = ''; //j ...
- 小强的HTML5移动开发之路(13)——HTML5中的全局属性
来自:http://blog.csdn.net/dawanganban/article/details/18179483 一.accssskey 快捷键 <!DOCTYPE HTML> ...
- 【JVM虚拟机】(8)--深入理解Class中--方法、属性表集合
#[JVM虚拟机](8)--深入理解Class中--方法.属性表集合 之前有关class文件已经写了两篇博客: 1.[JVM虚拟机](5)---深入理解JVM-Class中常量池 2.[JVM虚拟机] ...
随机推荐
- Ubuntu14.04.1LTS不能上网解决方法之一
我们在装好了Ubuntu之后,打开浏览器,显示Server not found. 1.点击网络图标,显示如下: 2.进入etc/NetworkManager,找到 Networkmanager.con ...
- 例行性工作排程 (crontab)
说白了,就是一些例行工作的日常执行的排序程序 Linux 工作排程的种类: at,cron 鸟叔说,atd并不是在所有版本都是开启的,但是centos7默认是开启的 [root@localhost ...
- python re.I compile search
import restring = "The quick brown fox jumps over the lazy dog."a_list = string.split()pat ...
- 【Luogu】【关卡2-12】递推与递归二分(2017年10月)
任务说明:递推,层层递进,由基础推向顶层.二分不仅可以用来查找数据,还可以确定最合适的值. P1192 台阶问题 有N级的台阶,你一开始在底部,每次可以向上迈最多K级台阶(最少1级),问到达第N级台阶 ...
- Linux下Golang Socket编程原理分析与代码实现
在POSIX标准推出后,socket在各大主流OS平台上都得到了很好的支持.而Golang是自带Runtime的跨平台编程语言,Go中提供给开发者的Socket API是建立在操作系统原生Socket ...
- mongoose 数据库连接
1安装mongoose npm install mongoose 安装成功 2.打开数据库 mongod --path E:\mongo 成功 创建一个db.js var mongoose = req ...
- Zookeeper用作注册中心的原理
RPC框架中有3个重要的角色: 注册中心 :保存所有服务的名字,服务提供者的ip列表,服务消费者的IP列表: 服务提供者: 提供跨进程服务: 服务消费者: 寻找到指定命名的服务并消费. 一:Zooke ...
- CSS制作红桃心
这里主要用到了before与after属性之前之后 代码: <!DOCTYPE html> <html> <head> <meta charset=" ...
- 逆向思维——cf1241D
/* 给定一个序列a,每次可以把值为x的所有元素放到a的首部或尾部,问将a变为lis的最少操作步数 对原序列离散化后重新打标记, 可以反着来考虑这个问题:即固定连续的元素值为[l,r]的点不动,那么剩 ...
- IDHTTP
Delphi IDHTTP用法详解 一.IDHTTP的基本用法 IDHttp和WebBrowser一样,都可以实现抓取远端网页的功能,但是http方式更快.更节约资源,缺点是需要手动维护cook,连接 ...