写在前面

  此系列是本人一个字一个字码出来的,包括示例和实验截图。由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新。 如有好的建议,欢迎反馈。码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作。如想转载,请把我的转载信息附在文章后面,并声明我的个人信息和本人博客地址即可,但必须事先通知我

你如果是从中间插过来看的,请仔细阅读 羽夏看Win系统内核——简述 ,方便学习本教程。

  看此教程之前,问几个问题,基础知识储备好了吗?上一节教程学会了吗?上一节课的练习做了吗?没有的话就不要继续了。


华丽的分割线


练习及参考

本次答案均为参考,可以与我的答案不一致,但必须成功通过。

2️⃣ 自己实验有和没有DEP保护的程序,看看效果。

点击查看答案

  这题目有一个坑,接下来请我娓娓道来。

  首先说一句:你设置操作系统的DEP保护所有程序有效了吗?(具体启用查看上一节教程,选中为除下列选定程序之外的所有程序和服务启用DEP,直接点确定),不然不起效果,白皮书原话:

  If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 2-MByte region controlled by this entry; see Section 4.6); otherwise, reserved (must be 0).

  也就是说IA32_EFERNXE位为0,就算最高位是1也是无尽于是。我们更改这个选项就是使它为1,这个就是是坑。好了,根据我的代码先运行一下:

  发现报错了,这个和10-10-12分页的不同之处。然后把PAGE_READWRITE改为PAGE_EXECUTE_READWRITE,然后再运行:

  这次运行成功,既然它们的页的首地址都是一样的,我们来看看它们的PDE或者PTE哪里不同,先是PAGE_READWRITE的:


  1. PROCESS 8947dda0 SessionId: 0 Cid: 0690 Peb: 7ffde000 ParentCid: 0204
  2. DirBase: 13b00380 ObjectTable: e1702740 HandleCount: 18.
  3. Image: mytest.exe
  4. kd> !dq 13b00380
  5. #13b00380 00000000`4ac31001 00000000`4a972001
  6. #13b00390 00000000`4ac33001 00000000`4aa70001
  7. #13b003a0 00000000`baf903c0 00000000`4a8a3001
  8. #13b003b0 00000000`4a6a4001 00000000`4a5a1001
  9. #13b003c0 00000000`baf90360 00000000`4a1a6001
  10. #13b003d0 00000000`4a227001 00000000`4a264001
  11. #13b003e0 00000000`baf90400 00000000`00000000
  12. #13b003f0 00000000`00000000 00000000`00000000
  13. kd> !dq 4ac31000
  14. #4ac31000 00000000`4a92a067 00000000`4aa13067
  15. #4ac31010 00000000`4aaa9067 00000000`4ab2f067
  16. #4ac31020 00000000`00000000 00000000`00000000
  17. #4ac31030 00000000`00000000 00000000`00000000
  18. #4ac31040 00000000`00000000 00000000`00000000
  19. #4ac31050 00000000`00000000 00000000`00000000
  20. #4ac31060 00000000`00000000 00000000`00000000
  21. #4ac31070 00000000`00000000 00000000`00000000
  22. kd> !dq 4aa13000+1d0*8
  23. #4aa13e80 80000000`4adc7067 00000000`00000000
  24. #4aa13e90 00000000`00000000 00000000`00000000
  25. #4aa13ea0 00000000`00000000 00000000`00000000
  26. #4aa13eb0 00000000`00000000 00000000`00000000
  27. #4aa13ec0 00000000`00000000 00000000`00000000
  28. #4aa13ed0 00000000`00000000 00000000`00000000
  29. #4aa13ee0 00000000`00000000 00000000`00000000
  30. #4aa13ef0 00000000`00000000 00000000`00000000

  然后是PAGE_EXECUTE_READWRITE


  1. PROCESS 895c8da0 SessionId: 0 Cid: 068c Peb: 7ffdf000 ParentCid: 0204
  2. DirBase: 13b00300 ObjectTable: e168ea78 HandleCount: 18.
  3. Image: mytest.exe
  4. kd> !dq 13b00300
  5. #13b00300 00000000`4711c001 00000000`472dd001
  6. #13b00310 00000000`4735e001 00000000`4741b001
  7. #13b00320 00000000`319e5001 00000000`31ae6001
  8. #13b00330 00000000`31b27001 00000000`31b64001
  9. #13b00340 00000000`37e87001 00000000`37c88001
  10. #13b00350 00000000`37d89001 00000000`37c46001
  11. #13b00360 00000000`baf903a0 00000000`46a2a001
  12. #13b00370 00000000`46a6b001 00000000`46ba8001
  13. kd> !dq 4711c000
  14. #4711c000 00000000`475d6067 00000000`472bf067
  15. #4711c010 00000000`47715067 00000000`4751b067
  16. #4711c020 00000000`00000000 00000000`00000000
  17. #4711c030 00000000`00000000 00000000`00000000
  18. #4711c040 00000000`00000000 00000000`00000000
  19. #4711c050 00000000`00000000 00000000`00000000
  20. #4711c060 00000000`00000000 00000000`00000000
  21. #4711c070 00000000`00000000 00000000`00000000
  22. kd> !dq 472bf000+1d0*8
  23. #472bfe80 00000000`476b3067 00000000`00000000
  24. #472bfe90 00000000`00000000 00000000`00000000
  25. #472bfea0 00000000`00000000 00000000`00000000
  26. #472bfeb0 00000000`00000000 00000000`00000000
  27. #472bfec0 00000000`00000000 00000000`00000000
  28. #472bfed0 00000000`00000000 00000000`00000000
  29. #472bfee0 00000000`00000000 00000000`00000000
  30. #472bfef0 00000000`00000000 00000000`00000000

  可以看出PTE的最高位置为1,导致这个页被认为是数据,不是代码,故导致内存访问错误,如果我们在访问之前改了它,那么就能访问它吗?结果是可以的,我就不赘述了。


点击查看代码
  1. #include "stdafx.h"
  2. #include <iostream>
  3. #include <windows.h>
  4. char shellcode[]={
  5. 0x6A,0x00, //PUSH 0
  6. 0x6A,0x00, //PUSH 0
  7. 0x6A, 0x00 , //PUSH 0
  8. 0x6A ,0x00 , //PUSH 0
  9. 0xB8, 0x00 ,0x00 ,0x00, 0x00 , //MOV EAX,0000
  10. 0xFF, 0xD0 , //CALL EAX
  11. 0xC3 //RET
  12. };
  13. int main(int argc, char* argv[])
  14. {
  15. int msgbox=(int)MessageBoxW;
  16. *(int*)&shellcode[9]=msgbox;
  17. LPVOID scaddr = VirtualAlloc(NULL,1024,MEM_COMMIT,PAGE_READWRITE);
  18. memcpy(scaddr,shellcode,sizeof(shellcode));
  19. printf("Shellcode物理页:%p\n",scaddr);
  20. _asm
  21. {
  22. mov eax,scaddr;
  23. call eax;
  24. }
  25. VirtualFree(scaddr,0,MEM_RELEASE);
  26. system("pause");
  27. return 0;
  28. }

TLB

  CPU通过页的方式对物理内存进行了,需要通过某种运算方式才能访问真正的内存。但是,如果频繁访问某一个线性地址,每次都得通过推算到真正的物理地址然后进行读写操作,是不是挺浪费效率的?Intel就考虑到性能的问题,提供了TLB这一个机制,提供缓存提高读写效率。

  TLB的全称为Translation Lookaside Buffer,它的结构如下:

LA(线性地址) PA(物理地址) ATTR(属性) LRU(统计)
0x81010111 …… …… 1

  对于TLB,给出如下说明:

  1. ATTR(属性):属性是PDPE PDE PTE三个属性AND起来的. 如果是10-10-12分页就是PDEPTE

  2. 不同的CPU这个表的大小不一样。

  3. 只要Cr3变了,TLB立马刷新,一核一套TLB

  学到现在我们知道,操作系统的高2G映射基本不变,如果Cr3改了,TLB刷新重建高2G以上很浪费。所以PDEPTE中有个G标志位,如果G位为1刷新TLB时将不会刷新PDE/PTEG位为1的页,当TLB满了,根据统计信息将不常用的地址废弃,最近最常用的保留。

  TLB有不同的种类,用于不同的缓存目的,它在X86体系里的实际应用最早是从Intel486CPU开始的,在X86体系的CPU里边,一般都设有如下4组TLB

  第一组:缓存一般页表(4K字节页面)的指令页表缓存:Instruction-TLB

  第二组:缓存一般页表(4K字节页面)的数据页表缓存:Data-TLB

  第三组:缓存大尺寸页表(2M/4M字节页面)的指令页表缓存:Instruction-TLB

  第四组:缓存大尺寸页表(2M/4M字节页面)的数据页表缓存:Data-TLB

CPU缓存

  CPU缓存是位于CPU与物理内存之间的临时存储器,它的容量比内存小的多但是交换速度却比内存要快得多。它可以做的很大,但不是TLB,它们有很大的不同。TLB存的是线性地址与物理地址的对应关系,CPU缓存存的是物理地址与内容对应关系。

  更多的细节请参考白皮书的Chapter 11 Memory Cache Control,本篇教程主要是针对内核安全层面,就不再赘述了。

PWT 与 PCD

  PWT全称为Page Write ThroughPWT = 1时,写Cache的时候也要将数据写入内存中。

  PCD全称为Page Cache DisablePCD = 1时,禁止某个页写入缓存,直接写内存。比如,做页表用的页,已经存储在TLB中了,可能不需要再缓存了。

本节练习

本节的答案将会在下一节进行讲解,务必把本节练习做完后看下一个讲解内容。不要偷懒,实验是学习本教程的捷径。

  俗话说得好,光说不练假把式,如下是本节相关的练习。如果练习没做好,就不要看下一节教程了,越到后面,不做练习的话容易夹生了,开始还明白,后来就真的一点都不明白了。本节练习很少,请保质保量的完成。

1️⃣ 在10-10-12分页模式下体会TLB的存在。要求:通过代码挂物理页,不能通过Windbg挂。原物理页挂完写入值读取,然后把地址换物理页继续读取,看看值是否发生变化。然后改页属性为全局页,重复上述操作。然后用INVLPG指令之后再看看值是否变化。

下一篇

  保护模式篇——中断与异常和控制寄存器

保护模式篇——TLB与CPU缓存的更多相关文章

  1. 保护模式篇——PAE分页

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...

  2. 羽夏看Win系统内核——保护模式篇

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...

  3. TLB和CPU缓存

    TLB 如果每次应用程序访问一个线性地址都需要先解析(查PDT,PTT)那么效率十分低,为了提高执行效率CPU在CPU内部建立了一个TLB表,此表和寄存器一样访问速度极高.其会记录线性地址和物理地址之 ...

  4. x64 番外篇——保护模式相关

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...

  5. MIT 6.828 JOS学习笔记6. Appendix 1: 实模式(real mode)与保护模式(protected mode)

    在我们阅读boot loader代码时,遇到了两个非常重要的概念,实模式(real mode)和保护模式(protected mode). 首先我们要知道这两种模式都是CPU的工作模式,实模式是早期C ...

  6. 鸿蒙内核源码分析(工作模式篇) | CPU是韦小宝,七个老婆 | 百篇博客分析OpenHarmony源码 | v36.04

    百篇博客系列篇.本篇为: v36.xx 鸿蒙内核源码分析(工作模式篇) | CPU是韦小宝,七个老婆 | 51.c.h .o 硬件架构相关篇为: v22.xx 鸿蒙内核源码分析(汇编基础篇) | CP ...

  7. CPU保护模式深入探秘

    原文链接为:http://www.chinaunix.net/old_jh/23/483510.html 保护方式的体系结构 主要问题:          保护方式的寄存器模型          保护 ...

  8. 基础篇-Windows保护模式

    1 一般来说,80x86(80386及其以后的各代CPU)可以在三种模式下运转:实模式,保护模式,V86模式.实模式就是古老的MS-DOS的运行环境.Win95只利用了两种模式:保护模式和V86模式. ...

  9. CPU保护模式DPL、CPL简易理解

    现代INTEL CPU都有保护模式,实模式这两种CPU运行模式.当CPU加电,CPU初始化时就运行在是模式下,然后现代操作系统会从实模式跳转到保护模式! 为什么需要保护模式? 在最开始编程的汇编时代, ...

随机推荐

  1. vue element-ui .el-dialog 限制高度

    <style scoped> /deep/ .el-dialog {   height: 78vh;   overflow: auto; }   </style>

  2. noip模拟38

    \(\color{white}{\mathbb{深秋总有廖落处,雁归每是菊败时,名之以:残菊}}\) 这场比赛几乎全场都在打暴力,几乎人均切掉的 \(t1\) 没有想到双指针,\(t3\) 的暴力也没 ...

  3. vue-过滤器(filter)的使用详解

    前言 Vue 允许我们在项目中定义过滤器对我们页面的文本展示进行格式的控制,本文就来总结一下过滤器在项目中的常见使用方法. 正文 1.局部过滤器的注册 (1)无参局部过滤器 <div id=&q ...

  4. Delphi使用AcroPDF ActiveX显示PDF文件

    效果展示 调用方式 放入窗体即可使用,不想安装太多组件,可使用纯代码方式调用 interface ..... var AcroPDF: TAcroPDF; .... implementation .. ...

  5. CSS001. 纯CSS实现瀑布流(纵向排序)

    通过 Multi-columns 相关的属性 column-count.column-gap 配合 break-inside 来实现瀑布流布局. 首先对包裹图片的盒子增加样式,column-count ...

  6. (5)java Spring Cloud+Spring boot+mybatis企业快速开发架构之SpringCloud-Spring Boot简介

    ​Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是简化新 Spring 应用的初始搭建以及开发过程.该框架使用了特定的方式进行配置,从而使开发人员不再需要定义样板化的配置 ...

  7. C# .NET Core 3.1 中 AssemblyLoadContext 的基本使用

    C# .NET Core 3.1 中 AssemblyLoadContext 的基本使用 前言 之前使用 AppDomain 写过一个动态加载和释放程序的案例,基本实现了自己"兔死狗烹&qu ...

  8. Marvell 88SE9215 AHCI驱动笔记

    禁止转载!禁止转载!禁止转载! 一.Marvell 88SE9215.AHCI与SATA简介 1.Marvell 88SE9215 1)概述 88SE9215是一个四端口,兼容3 Gbps和6 Gbp ...

  9. 一文彻底搞懂Hive的数据存储与压缩

    目录 行存储与列存储 行存储的特点 列存储的特点 常见的数据格式 TextFile SequenceFile RCfile ORCfile 格式 数据访问 Parquet 测试 准备测试数据 存储空间 ...

  10. 动态查看及加载PHP扩展

    在编译并完成 php.ini 的配置之后,我们就成功的安装了一个 PHP 的扩展.不过, PHP 也为我们提供了两个在动态运行期间可以查看扩展状态以及加载未在 php.ini 中进行配置的扩展的函数. ...