4000-520-616
欢迎来到免疫在线!(蚂蚁淘生物旗下平台)  请登录 |  免费注册 |  询价篮
主营:原厂直采,平行进口,授权代理(蚂蚁淘为您服务)
咨询热线电话
4000-520-616
当前位置: 首页 > 新闻动态 >
热卖商品
新闻详情
学习BluePill源码笔记-1_XboxMicro-CSDN博客_bluepill
来自 : CSDN技术社区 发布时间:2021-03-25

VT-X太高端霸气上档次了.....本菜本着自虐的精神~来学习BluePill的工作方式

BluePill有好几种方式启动 当然ShellCode这种高端霸气上档次的方式俺们菜菜当然用不到啦~

本菜的初学笔记 大牛勿笑 砸场可以 脏话不要 谢谢合作~


一、BluePill的内存管理

1.1驱动的入口点(newbp.c) 内存管理的起始位置

NTSTATUS DriverEntry ( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath){ NTSTATUS Status;#ifdef USE_COM_PRINTS PioInit ((PUCHAR) COM_PORT_ADDRESS);#endif ComInit (); Status MmInitManager (); if (!NT_SUCCESS (Status)) { _KdPrint (( NEWBLUEPILL: MmInitManager() failed with status 0x%08hX\\n , Status)); return Status; }#ifdef USE_LOCAL_DBGPRINTS Status DbgRegisterWindow (g_BpId); if (!NT_SUCCESS (Status)) { _KdPrint (( NEWBLUEPILL: DbgRegisterWindow() failed with status 0x%08hX\\n , Status)); MmShutdownManager (); return Status; }#endif _KdPrint (( \\r\\n _KdPrint (( NEWBLUEPILL v%d.%d.%d.%d. Instance Id: 0x%02X\\n , (NBP_VERSION 48) 0xff, (NBP_VERSION 32) 0xff, (NBP_VERSION 16) 0xff, NBP_VERSION 0xff, g_BpId)); // We need it only for VMX // TODO: this should be conditionally executed only if Arch VMX Status MmInitIdentityPageTable (); if (!NT_SUCCESS (Status)) { _KdPrint (( NEWBLUEPILL: MmInitIdentifyPageTable() failed with status 0x%08hX\\n , Status));#ifdef USE_LOCAL_DBGPRINTS DbgUnregisterWindow ();#endif MmShutdownManager (); return Status; } Status MmMapGuestKernelPages (); if (!NT_SUCCESS (Status)) { _KdPrint (( BEWBLUEPILL: MmMapGuestKernelPages() failed with status 0x%08hX\\n , Status));#ifdef USE_LOCAL_DBGPRINTS DbgUnregisterWindow ();#endif MmShutdownManager (); return Status; }#ifdef RUN_BY_SHELLCODE _KdPrint (( NEWBLUEPILL: Image base: 0x%p, image size: 0x%x\\n , DriverObject, (ULONG64) RegistryPath)); Status MmMapGuestPages (DriverObject, (ULONG) BYTES_TO_PAGES ((ULONG64) RegistryPath));#else Status MmMapGuestPages (DriverObject- DriverStart, BYTES_TO_PAGES (DriverObject- DriverSize));#endif if (!NT_SUCCESS (Status)) { _KdPrint (( NEWBLUEPILL: MmMapGuestPages() failed to map guest NewBluePill image with status 0x%08hX\\n , Status));#ifdef USE_LOCAL_DBGPRINTS DbgUnregisterWindow ();#endif MmShutdownManager (); return Status; } _KdPrint (( NEWBLUEPILL: g_PageMapBasePhysicalAddress: 0x%p\\n , g_PageMapBasePhysicalAddress)); if (!NT_SUCCESS (Status HvmInit ())) { _KdPrint (( NEWBLUEPILL: HvmInit() failed with status 0x%08hX\\n , Status));#ifdef USE_LOCAL_DBGPRINTS DbgUnregisterWindow ();#endif MmShutdownManager (); return Status; } if (!NT_SUCCESS (Status HvmSwallowBluepill ())) { _KdPrint (( NEWBLUEPILL: HvmSwallowBluepill() failed with status 0x%08hX\\n , Status));#ifdef USE_LOCAL_DBGPRINTS DbgUnregisterWindow ();#endif MmShutdownManager (); return Status; }#ifndef RUN_BY_SHELLCODE DriverObject- DriverUnload DriverUnload;#endif _KdPrint (( NEWBLUEPILL: Initialization finished\\n #if DEBUG_LEVEL 1 _KdPrint (( NEWBLUEPILL: RFLAGS %#x, CR8 %#x\\n , RegGetRflags (), RegGetCr8 ()));#endif return STATUS_SUCCESS;}

1.2

首先 DriverEntry是进入了MmInitManager();函数(page.c)


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;}

MmInitManage 初始化了LIST_ENTRY结构和自旋锁后开辟了一页大小的内存。这个内存是用来构造Pml4页表的 接着调用到重要函数MmSavePage。第一个参数是刚才开辟的内存池的物理地址 第二个参数则是PML4_BASE。

MmSavePage 第三个参数是Pml4Page 也就是刚才开辟的内存池。第四个参数类型为PAGE_ALLOCATION_TYPE 定义如下 (page.h)

typedef enum{ PAT_DONT_FREE 0, PAT_POOL, PAT_CONTIGUOUS} PAGE_ALLOCATION_TYPE;
第五个参数uNumberOfPages 前面只开辟了PAGE_SIZE 这里自然写1。第六个为flag。


1.3 看到这里 俺来自我科普一些x64的知识了。

1.3.1 PML4_BASE定义如下 (common.h)

#define PML4_BASE 0xFFFFF6FB7DBED000#define PDP_BASE 0xFFFFF6FB7DA00000#define PD_BASE 0xFFFFF6FB40000000#define PT_BASE 0xFFFFF68000000000
等下 PML4_BASE是啥

在amd64.h中可以找到似曾相识的定义

#define PXE_BASE 0xFFFFF6FB7DBED000UI64#define PPE_BASE 0xFFFFF6FB7DA00000UI64#define PDE_BASE 0xFFFFF6FB40000000UI64#define PTE_BASE 0xFFFFF68000000000UI64
查了下资料 64位中目前只用到48位地址计算页表。所以 在用工具看到XX内核地址时 地址都是0xFFFF....开头的。显然 这前面的4个F是无用的。PTE的基址约定为0xFFFFF68000000000。

根据页表换算公式 在这里列举一下 )

PDE ((lVirtualAddress 21) 3) 0x3FF8 0xC0600000;PTE ((lVirtualAddress 12) 3) 0x7FFFF8 0xC0000000;

上述公式是在x86 开启PAE模式下推导得到的。

在x64非PAE模式下 很少有PAE模式的机子 PAE Flag位于CR4的第五个bit上 我们的计算方式如下


PDE_BASE ((PTE_BASE 0x0000FFFFFFFFF000) 12) * 8 PTE_BASE 0xF68000000 * 8 PTE_BASE 0x7B40000000 PTE_BASE 0xFFFFF6FB40000000PPE_BASE ((PDE_BASE 0x0000FFFFFFFFF000) 12) * 8 PTE_BASE 0xF6FB40000 * 8 PTE_BASE 0x7B7DA00000 PTE_BASE 0xFFFFF6FB7DA00000PXE_BASE ((PPE_BASE 0x0000FFFFFFFFF000) 12) * 8 PTE_BASE 0xF6FB7DA00 * 8 PTE_BASE 0x7B7DBED000 PTE_BASE 0xFFFFF6FB7DBED000
等下 掩码0x0000FFFFFFFFF000是啥 显然是把刚才所说的4个F也就是16个无效位全给清除掉。

等下 PPE和PXE又是啥呢 本菜继续查资料。


1.3.2 64位地址翻译机制 

在64位中 每级页表寻址部分长度位9位。x64体系中 普通页的大小仍为4KB 然而数据表示却为64位长 因此一个4KB页在x64体系结构下只能包含512项内容。为了保证页对齐和页为单位的页表内容换入换出 x64下每级页表寻址部分长度定位9位。


\"\"

\"\"


这四级页表的缩写在BluePill中分别为PML4、PDP、PD和PT。说实话 我看到这里还是晕晕的 于是到msdn上再好好的论证了一下。

Intel refers to each entry as PML4-Table Entry. Internally we refer to this as the eXtended Page directory Entry (PXE).  Regardless of how you refer to these entries they contain indexes into the PDP table (Page Directory Pointer Table).

PML4 Page map level 4 PXE

PDP Page Directory Pointer Table PPE

换句话说 PXE放的东西就是PPE PPE放的东西是PDE PDE放的东西就是PTE。


1.3.3

我们来做一个小实验 查看线性地址翻译过程

kd r cr3cr3 0000000000187000kd !pte fffff800 01661860 VA fffffffffffff800PXE at FFFFF6FB7DBEDFF8 PPE at FFFFF6FB7DBFFFF8 PDE at FFFFF6FB7FFFFFF8 PTE at FFFFF6FFFFFFFFF8contains 00000000001F4063 contains 00000000001F3063 contains 00000000001F5063 contains 0000000000000000pfn 1f4 ---DA--KWEV pfn 1f3 ---DA--KWEV pfn 1f5 ---DA--KWEV not valid

~继续将我们测试的地址0xfffff80001661860化为二进制

.formats fffff80001661860Evaluate expression: Hex: fffff800 01661860 Decimal: -8796069554080 Octal: 1777777600000131414140 Binary: 11111111 11111111 11111000 00000000 00000001 01100110 00011000 01100000 Chars: .....f. Time: ***** Invalid FILETIME Float: low 4.22618e-038 high -1.#QNAN Double: -1.#QNAN


通过Binary 得到如下字段

Sign extend               11111111 11111111

PML4 offset               111110000

PDP offset                 000000000

PD offset                    000001011

Page-Table offset         001100001

Physical Page Offset      1000 01100000

9 9 9 9 12 48bit (PML4 PDP PDE PTE PAGE OFFSET 48bit)

为了方便理解上面的字段 贴出IA32页表映射关系 (最常见的4KB式)

\"\"

 

以及页表的结构

\"\"

\"\"

参阅一些资料 x64非PAE模式下 物理地址如下计算

PML4 Address cr3  PML4 offset * sizeof(PTE)

PDP Address PML4 Address 0xfffffffffffff000 (PDP offset * sizeof(PTE))

PDE Address  PDP Address 0xfffffffffffff000 (PD offset * sizeof(PTE))

PTE Address  PDE Address 0xfffffffffffff000 (PT offset * sizeof(PTE))

Physical Address  PTE Address 0xfffffffffffff000 Physical Page Offset


1.4 执行MmSavePage函数 主要作用是保存对刚刚分配出来私有PML4级页表的描述信息。这个过程被一些文献称为“前私有页表初始化”。

static NTSTATUS NTAPI MmSavePage ( PHYSICAL_ADDRESS PhysicalAddress, PVOID HostAddress, PVOID GuestAddress, PAGE_ALLOCATION_TYPE AllocationType, ULONG uNumberOfPages, ULONG Flags){ PALLOCATED_PAGE AllocatedPage; if (!GuestAddress) return STATUS_INVALID_PARAMETER; AllocatedPage ExAllocatePoolWithTag (NonPagedPool, sizeof (ALLOCATED_PAGE), ITL_TAG); if (!AllocatedPage) return STATUS_INSUFFICIENT_RESOURCES; RtlZeroMemory (AllocatedPage, sizeof (ALLOCATED_PAGE)); PhysicalAddress.QuadPart PhysicalAddress.QuadPart 0x000ffffffffff000; HostAddress (PVOID) ((ULONG64) HostAddress 0xfffffffffffff000); AllocatedPage- AllocationType AllocationType; AllocatedPage- PhysicalAddress PhysicalAddress; AllocatedPage- HostAddress HostAddress; AllocatedPage- GuestAddress GuestAddress; AllocatedPage- uNumberOfPages uNumberOfPages; AllocatedPage- Flags Flags; ExInterlockedInsertTailList ( g_PageTableList, AllocatedPage- le, g_PageTableListLock); /* DbgPrint( MmSavePage(): PA 0x%X, HostVA 0x%p, GuestVA 0x%p, AT %d, FL 0x%X\\n , PhysicalAddress.QuadPart, HostAddress, GuestAddress, AllocationType, Flags); */ return STATUS_SUCCESS;}

MmSavePage进行参数检验后开辟了一块内存区域。这次开辟的是一个ALLOCATED_PAGE结构。这个结构如下 (page.h)

typedef struct _ALLOCATED_PAGE{ LIST_ENTRY le; ULONG Flags; PAGE_ALLOCATION_TYPE AllocationType; ULONG uNumberOfPages; // for PAT_CONTIGUOUS only PHYSICAL_ADDRESS PhysicalAddress; PVOID HostAddress; PVOID GuestAddress;} ALLOCATED_PAGE, *PALLOCATED_PAGE;
在下面这两行中

 PhysicalAddress.QuadPart PhysicalAddress.QuadPart 0x000ffffffffff000; HostAddress (PVOID) ((ULONG64) HostAddress 0xfffffffffffff000);

PhysicalAddress仅取中间的40位 HostAddress只取高52位。这两个处理是根据Intel和AMD的规范。该函数执行成功后 返回MmInitManager()继续执行。

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; }
接下来调用的MmCreateMapping()函数开始构建NewBluePill私有页表。


看球去啦 ~~


\"\" \"\" \"\" 点赞 \"\" \"\" 评论 1

本文链接: http://bluepillformen.immuno-online.com/view-731110.html

发布于 : 2021-03-25 阅读(0)
公司介绍
品牌分类
联络我们
服务热线:4000-520-616
(限工作日9:00-18:00)
QQ :1570468124
手机:18915418616