详解TesSafe.sys逆向定位PTE_BASE OS 逆向

admin 2019-9-6 508

众所周知windows 10 14316开始实现了页表随机化,之前WRK里给出的#define PTE_BASE 0xFFFFF68000000000h 不再有效

那么各路神仙是怎么定位新的PTE_BASE的呢?

著名国际友人tandasat是通过特征码定位的:

// Get PTE_BASE from MmGetVirtualForPhysical
  const auto p_MmGetVirtualForPhysical =
      UtilGetSystemProcAddress(L"MmGetVirtualForPhysical");
  if (!p_MmGetVirtualForPhysical) {
    return STATUS_PROCEDURE_NOT_FOUND;
  }
 
  static const UCHAR kPatternWin10x64[] = {
      0x48, 0x8b, 0x04, 0xd0,  // mov     rax, [rax+rdx*8]
      0x48, 0xc1, 0xe0, 0x19,  // shl     rax, 19h
      0x48, 0xba,              // mov     rdx, ????????`????????  ; PTE_BASE
  };
  auto found = reinterpret_cast<ULONG_PTR>(
      UtilMemMem(p_MmGetVirtualForPhysical, 0x30, kPatternWin10x64,
                 sizeof(kPatternWin10x64)));
  if (!found) {
    return STATUS_PROCEDURE_NOT_FOUND;
  }
 
  found += sizeof(kPatternWin10x64);
  HYPERPLATFORM_LOG_DEBUG("Found a hard coded PTE_BASE at %016Ix", found);
 
  const auto pte_base = *reinterpret_cast<ULONG_PTR *>(found);
  const auto index = (pte_base >> kUtilpPxiShift) & kUtilpPxiMask;
  const auto pde_base = pte_base | (index << kUtilpPpiShift);
  const auto ppe_base = pde_base | (index << kUtilpPdiShift);
  const auto pxe_base = ppe_base | (index << kUtilpPtiShift);
 
  g_utilp_pxe_base = static_cast<ULONG_PTR>(pxe_base);
  g_utilp_ppe_base = static_cast<ULONG_PTR>(ppe_base);
  g_utilp_pde_base = static_cast<ULONG_PTR>(pde_base);
  g_utilp_pte_base = static_cast<ULONG_PTR>(pte_base);
 
  g_utilp_pxi_shift = kUtilpPxiShift;
  g_utilp_ppi_shift = kUtilpPpiShift;
  g_utilp_pdi_shift = kUtilpPdiShift;
  g_utilp_pti_shift = kUtilpPtiShift;
 
  g_utilp_pxi_mask = kUtilpPxiMask;
  g_utilp_ppi_mask = kUtilpPpiMask;
  g_utilp_pdi_mask = kUtilpPdiMask;
  g_utilp_pti_mask = kUtilpPtiMask;
  return status;

那么鹅厂是如何定位的呢? 

国际惯例直接上伪代码

char __fastcall InitializePteBase(char a1)
{
  char v1; // bl
  PHYSICAL_ADDRESS pml4t; // rdi
  __int64 *pml4t_va; // r11
  int slot; // edx
  __int64 index; // rcx
  __int64 v6; // r8
 
  v1 = 0;
  if ( a1 )
  {
    pml4t.QuadPart = __readcr3();
    pml4t_va = (__int64 *)MmMapIoSpace(pml4t, 0x1000ui64, MmCached);
    if ( pml4t_va )
    {
      slot = 0;
      index = 0i64;
      while ( (pml4t_va[index] & 0xFFFFFFFFF000i64) != pml4t.QuadPart )
      {
        ++index;
        ++slot;
        if ( index >= 512 )
          goto LABEL_8;
      }
      v1 = 1;
      v6 = (slot + 0x1FFFE00i64) << 39;
      g_pte_base = (slot + 0x1FFFE00i64) << 39;
      g_pxe_selfmapping_index = slot;
      g_pde_base = v6 + ((__int64)slot << 30);
      g_ppe_base = v6 + ((__int64)slot << 30) + ((__int64)slot << 21);
      g_pxe_base = (void *)(g_ppe_base + ((__int64)slot << 12));
      g_pxe_end = (__int64)g_pxe_base + 4096;
      g_pte_end = v6 + 0x8000000000i64;
LABEL_8:
      MmUnmapIoSpace(pml4t_va, 0x1000ui64);
    }
  }
  else
  {
    g_pxe_selfmapping_index = 493i64;
    v1 = 1;
    g_pte_base = 0xFFFFF68000000000i64;
    g_pde_base = 0xFFFFF6FB40000000i64;
    g_ppe_base = 0xFFFFF6FB7DA00000i64;
    g_pxe_base = (void *)0xFFFFF6FB7DBED000i64;
    g_pxe_end = 0xFFFFF6FB7DBEE000i64;
    g_pte_end = 0xFFFFF70000000000i64;
  }
  return v1;
}

先以当前cr3为物理地址映射成虚拟地址,相当于访问cr3所指向的pml4t表

然后在这个[512]的表(数组)中找到一项指向当前cr3的

也就是所谓的页表自映射,这一项PML4E所指向的物理页page_frame_number代表它自己这个表

满足这样的映射关系的PML4E所代表的虚拟地址空间也就相当于页表本身,一共0x8000000000/8 (512/8=64GB)个PTE

我们先从无随机化的情况论证:

大家都知道x64的线性地址是分成9① 9② 9③ 9④ 12⑤ 五部分进行地址翻译的:①代表pml4e索引,②代表pdpte索引,③代表pde索引,④代表pte索引,⑤代表页内偏移

无随机化的情况下第[493]项pml4e指向cr3,第[493]项pml4e是111101101(9位),左移39位让其变为第39~47位代表pml4e索引并补齐48~63位FFFF000000000000(保留位)

就是这样

刚好就是PTE_BASE

那么只要找到 指向当前cr3的pml4e index,将其左移39位并补上FFFF000000000000就得到了PTE_BASE

也就是代码中的 g_pte_base = (slot + 0x1FFFE00i64) << 39;(注意) 0x1FFFE00i64左移39位就是 FFFF000000000000

计算PDE_BASE也只需要将这个能够自映射的index左移30位让其变为30~38位代表pdpte索引,再加上PTE_BASE就等于PDE_BASE了

也就是

g_pde_base = g_pte_base + ((__int64)slot << 30);

PPE_BASE和PXE_BASE同理

注意有一点:win10 1803之后MmMapIoSpace不再允许映射页表相关的物理地址,因此只能用MmGetVirtualForPhysical代替,或者自己实现映射物理地址(方法很多)


少客联盟- 版权声明 1、本主题所有言论和图片纯属会员个人意见,与少客联盟立场无关。
2、本站所有主题由该帖子作者发表,该帖子作者admin少客联盟享有帖子相关版权。
3、少客联盟管理员和版主有权不事先通知发贴者而删除本文。
4、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者admin少客联盟的同意。
5、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任。
6、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责。
7、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意。
8、官方反馈邮箱:chinasuc@chinasuc.cn


上一篇:Windows 10特定注册表项
下一篇:网站主机 详解介绍
Whatever is worth doing is worth doing well. juvenile hacker league
最新回复 (0)
    • 少客联盟
      2
        登录 注册 QQ登录(停用)
返回