为了在虚拟运行之后,客户机被宿主机接管,驱动程序代码还能被访问,BP使用了和windows一样的虚拟地址映射方式,以下四个常量:
#define PML4_BASE 0xFFFFF6FB7DBED000
#define PDP_BASE 0xFFFFF6FB7DA00000
#define PD_BASE  0xFFFFF6FB40000000
#define PT_BASE  0xFFFFF68000000000
和windows内核的下面四个常量对应(WRK中base/ntos/inc/amd64.h(2528)):
#define PXE_BASE          0xFFFFF6FB7DBED000UI64
#define PPE_BASE          0xFFFFF6FB7DA00000UI64
#define PDE_BASE          0xFFFFF6FB40000000UI64
#define PTE_BASE          0xFFFFF68000000000UI64
      7B40000000
这四个常量的计算方法如下:
首先选定PTE_BASE,windows选择把页表映射到虚拟地址0xFFFFF68000000000UI64的位置,则后面的PDE_BASE、PPE_BASE和PXE_BASE依次算出
PDE_BASE = ((PTE_BASE & 0x0000FFFFFFFFF000) >> 12) * 8 + PTE_BASE = 0xF68000000 * 8 + PTE_BASE = 0x7B40000000 + PTE_BASE = 0xFFFFF6FB40000000
PPE_BASE = ((PDE_BASE & 0x0000FFFFFFFFF000) >> 12) * 8 + PTE_BASE = 0xF6FB40000 * 8 + PTE_BASE = 0x7B7DA00000 + PTE_BASE = 0xFFFFF6FB7DA00000
PXE_BASE = ((PPE_BASE & 0x0000FFFFFFFFF000) >> 12) * 8 + PTE_BASE = 0xF6FB7DA00 * 8 + PTE_BASE = 0x7B7DBED000 + PTE_BASE = 0xFFFFF6FB7DBED000
这里需要注意的是IA32体系当前的虚拟地址空间是2^48B=256TB,高16位是符号扩展位,在实际计算中要去掉,因此在这里使用了掩码0x0000FFFFFFFFF000,而每个页表项占8个字节
下面这个常量指出了虚拟地址PXE_BASE页表项所在的位置
#define PXE_SELFMAP       0xFFFFF6FB7DBEDF68UI64
PXE_SELFMAP = ((PXE_BASE & 0x0000FFFFFFFFF000) >> 12) * 8 + PTE_BASE = 0xF6FB7DBED * 8 + PTE_BASE = 0x7B7DBEDF68 + PTE_BASE = 0xFFFFF6FB7DBEDF68

在MmInitManager函数中首先初始化BP维护的g_PageTableList和g_PageTableListLock,g_PageTableList将BP通过windows内核API ExAllocatePoolWithTag或者MmAllocateContiguousMemorySpecifyCache从操作系统分配出来的非分页内存链接在一起,g_PageTableListLock则是进行操作链表的同步锁。
BP维护如下所示的三种分配类型的内存页面
typedef enum
{
  PAT_DONT_FREE = 0,  //表示这个内存页面不是单独分配的,是在一大块连续内存的中间位置,不能被释放
  PAT_POOL,   //表示这个内存页面是通过调用ExAllocatePoolWithTag从非分页池中分配的第一个内存页
  PAT_CONTIGUOUS  //表示这个内存页面是通过调用MmAllocateContiguousMemorySpecifyCache分配的第一个内存页
} PAGE_ALLOCATION_TYPE;
内存页有如下标志
#define AP_PAGETABLE 1       // 表示是宿主机的页表
#define AP_PT  2
#define AP_PD  4
#define AP_PDP  8
#define AP_PML4  16
分别表示作为各级页表的内存页

接着调用ExAllocatePoolWithTag从非分页池中分配一个内存页作为PML4-table,调用MmSavePage将这块内存的宿主机虚拟地址PML4_BASE、客户机虚拟地址Pml4Page(从ExAllocatePoolWithTag返回的操作系统维护的虚拟地址)和物理地址g_PageMapBasePhysicalAddress(调用MmGetPhysicalAddress获取)映射关系分配结构体保存在g_PageTableList链表中,成功之后调用MmCreateMapping建立虚拟地址PML4_BASE和物理地址g_PageMapBasePhysicalAddress的实际映射,该函数调用MmUpdatePageTable更新页表实现这个动作。

具体代码如下:

NTSTATUS NTAPI MmInitManager (
)
{
  PVOID Pml4Page;
  NTSTATUS Status;
  PHYSICAL_ADDRESS l1, l2, l3;

InitializeListHead (&g_PageTableList);
  KeInitializeSpinLock (&g_PageTableListLock);

Pml4Page = ExAllocatePoolWithTag (NonPagedPool, PAGE_SIZE, ITL_TAG);
  if (!Pml4Page)
    return STATUS_INSUFFICIENT_RESOURCES;
  RtlZeroMemory (Pml4Page, PAGE_SIZE);

g_PageMapBasePhysicalAddress = MmGetPhysicalAddress (Pml4Page);

if (!NT_SUCCESS
      (Status =
       MmSavePage (g_PageMapBasePhysicalAddress, (PVOID) PML4_BASE, Pml4Page, PAT_POOL, 1, AP_PAGETABLE | AP_PML4))) {
    DbgPrint ("MmInitManager(): MmSavePage() failed to save PML4 page, status 0x%08X/n", Status);
    return Status;
  }

if (!NT_SUCCESS (Status = MmCreateMapping (g_PageMapBasePhysicalAddress, (PVOID) PML4_BASE, FALSE))) {
    DbgPrint ("MmInitManager(): MmCreateMapping() failed to map PML4 page, status 0x%08X/n", Status);
    return Status;
  }

return STATUS_SUCCESS;
}

这里面的一个重要函数就是MmUpdatePageTable,它递归更新在映射过程中所需要引入的内存页的页表映射关系。今天到这里,待续........

Blue Pill源代码分析(2)相关推荐

  1. 从Blue Pill、硬件虚拟化谈安全防护完备性上的一个小原则

    这篇博客说说一个安全防护系统完备性上所需的一个小原则:防护系统与被防护对象所用资源的完全隔离,包括防护系统自身工作所依赖的资源不能依赖被防护对象.听起来是原理很简单的一个点,实现中往往很复杂.例如操作 ...

  2. Android系统默认Home应用程序(Launcher)的启动过程源代码分析

    在前面一篇文章中,我们分析了Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还需要有一个Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home应 ...

  3. 《LINUX3.0内核源代码分析》第一章:内存寻址

    https://blog.csdn.net/ekenlinbing/article/details/7613334 摘要:本章主要介绍了LINUX3.0内存寻址方面的内容,重点对follow_page ...

  4. Scrapy源代码分析-经常使用的爬虫类-CrawlSpider(三)

    CrawlSpider classscrapy.contrib.spiders.CrawlSpider 爬取一般站点经常使用的spider.其定义了一些规则(rule)来提供跟进link的方便的机制. ...

  5. Android 中View的绘制机制源代码分析 三

    到眼下为止,measure过程已经解说完了,今天開始我们就来学习layout过程.只是在学习layout过程之前.大家有没有发现我换了编辑器,哈哈.最终下定决心从Html编辑器切换为markdown编 ...

  6. Android应用程序进程启动过程的源代码分析(1)

    Android应用程序框架层创建的应用程序进程具有两个特点,一是进程的入口函数是ActivityThread.main,二是进程天然支持Binder进程间通信机制:这两个特点都是在进程的初始化过程中实 ...

  7. AFNetworking 源代码分析

    关于其他 AFNetworking 源代码分析的其他文章: AFNetworking 概述(一) AFNetworking 的核心 AFURLSessionManager(二) 处理请求和响应 AFU ...

  8. Hadoop源代码分析 - MapReduce(转载)

    1. Hadoop源代码分析(MapReduce概论) http://caibinbupt.javaeye.com/blog/336467

  9. RTMPdump(libRTMP) 源代码分析 3: AMF编码

    2019独角兽企业重金招聘Python工程师标准>>> 注:此前写了一些列的分析RTMPdump(libRTMP)源代码的文章,在此列一个列表: RTMPdump 源代码分析 1: ...

最新文章

  1. 三大趋势在移动互联网发展
  2. 实数系的基本定理_初中篇1|知实数-为什么0.9的循环等于1?
  3. 配置Tomcat使用HTTP/2
  4. python pyquery库_python解析HTML之:PyQuery库的介绍与使用
  5. 支持Dubbo生态发展,阿里巴巴启动新的开源项目 Nacos
  6. css背景图background - 多背景定义
  7. 2020年,RocketMQ面试题 -面试题驱动RocketMQ学习
  8. Android 通过Socket 和服务器通讯
  9. 金属100寸“电视”却无屏,语音识别+DTS+1080P,微鲸M1测评
  10. print python 带回车_python标准库threading源码解读【二】
  11. Markdown语言调整图片居中、大小
  12. bootstrap在php中怎弄,bootstrap插件怎么用
  13. Inno Setup 系列之自定义卸载文件名称的脚本
  14. Python通过selenium操作edge浏览器
  15. 如何在线修改图片分辨率?怎么调整300dpi分辨率?
  16. MDI打开文件时指定目录
  17. 央行最新公布2019支付牌照持牌机构公司列表,共255家(附清单)
  18. IDOC的处理函数IDOC_INPUT_ORDERS的增强点的分析
  19. 小米官网首页(html+css+JavaScript)
  20. Linux内存管理(二):页面查询过程简述

热门文章

  1. 湖北职业高考计算机专业对口的学校有哪些,湖北技能高考能进哪些专科学校
  2. 怎么无损放大图片?试试这个简单方法
  3. Android实现多张图片合成GIF
  4. Java初学者第一天笔记
  5. 社群空间站v3.5.2 微信社群人脉系统社群空间站PHP源码
  6. C语言学习之设圆半径r=1.5,圆柱高h=3,求圆周长、圆面积、圆球表面积、圆球体积、圆柱体积。
  7. 从项目中卸载SteamVR
  8. Python也可以抢网速,我下了十部电影,室友才一部
  9. 如何在线CAJ转换成Word文档
  10. 华为任正非:活下来!