首页
社区
课程
招聘
[讨论]关于判断有效地址 MmIsAddressValid的其它实现问题.
发表于: 2011-12-1 00:22 10295

[讨论]关于判断有效地址 MmIsAddressValid的其它实现问题.

2011-12-1 00:22
10295
PCHAR MiProtectionToString[] = {
   "MM_ZERO_ACCESS", //         0  // this value is not used.
   "MM_READONLY", //            1
   "MM_EXECUTE", //             2
   "MM_EXECUTE_READ", //        3
   "MM_READWRITE", //           4  // bit 2 is set if this is writable.
   "MM_WRITECOPY", //           5
   "MM_EXECUTE_READWRITE", //   6
   "MM_EXECUTE_WRITECOPY", //   7
   "MM_NOCACHE"            //   8
};

#if 1
#undef MmPrint
#define MmPrint(x)
#endif

VALIDITY_CHECK_STATUS
MmIsAddressValidExNotPae(
  IN PVOID Pointer
  )
{
  VALIDITY_CHECK_STATUS  Return = VCS_INVALID;
  

  MMPTE* Pde = MiGetPdeAddress(Pointer);

  MmPrint(("PDE is 0x%08x\n", Pde));
  if( Pde->u.Hard.Valid )
  {
    MmPrint(("PDE entry is valid, PTE PFN=%08x\n", Pde->u.Hard.PageFrameNumber));

    MMPTE* Pte = MiGetPteAddress(Pointer);

    MmPrint(("PTE is 0x%08x\n", Pte));
    if( Pte->u.Hard.Valid )
    {
      MmPrint(("PTE entry is valid, PFN=%08x\n", Pte->u.Hard.PageFrameNumber));
      Return = VCS_VALID;
    }
    else
    {
      //
      // PTE is not valid
      //

      MMPTE pte = *Pte;

      MmPrint(("Got invalid PTE [%08x]: Proto=%d,Transition=%d,Protection=0x%x,PageFilePFN=0x%x\n",
        pte.u.Long,
        pte.u.Soft.Prototype,
        pte.u.Soft.Transition,
        pte.u.Soft.Protection,
        pte.u.Soft.PageFileHigh));

      if( pte.u.Long )
      {
        if( pte.u.Soft.Prototype == 1 )
        {
          MmPrint(("PTE entry is not valid, points to prototype PTE.\n"));

          // more accurate check should be performed here for pointed prototype PTE!

          Return = VCS_PROTOTYPE;
        }
        else  // not a prototype PTE
        {
          if( pte.u.Soft.Transition != 0 )
          {
            //
            // This is a transition page. Consider it invalid.
            //

            MmPrint(("PTE entry is not valid, points to transition page.\n"));

            Return = VCS_TRANSITION;
          }
          else if (pte.u.Soft.PageFileHigh == 0)
          {
            //
            // Demand zero page
            //

            MmPrint(("PTE entry is not valid, points to demand-zero page.\n"));

            Return = VCS_DEMANDZERO;
          }
          else
          {
            //
            // Pagefile PTE
            //

            if( pte.u.Soft.Transition == 0 )
            {
              MmPrint(("PTE entry is not valid, VA is paged out (PageFile offset=%08x)\n",
                pte.u.Soft.PageFileHigh));

              Return = VCS_PAGEDOUT;
            }
            else
            {
              MmPrint(("PTE entry is not valid, Refault\n"));
            }
          }
        }
      }
      else
      {
        MmPrint(("PTE entry is completely invalid\n"));
      }
    }
  }
  else
  {
    MmPrint(("PDE entry is not valid\n"));
  }

  return Return;
}

上面传说中老外写的.

ULONG IsValidAddr( ULONG uAddr )
{
        ULONG uInfo;
        ULONG uCr4;
        ULONG uPdeAddr;
        ULONG uPteAddr;
        _asm
        {
                cli
                        push eax

                        _emit 0x0F
                        _emit 0x20
                        _emit 0xE0//mov eax,cr4

                        mov [uCr4], eax
                        pop eax
        }

        _asm sti

        uInfo = uCr4 & 0x20;//判断是否PAE模式
        if( uInfo != 0 )

                uPdeAddr = (uAddr>>21)*8+0xC0600000;//
       
        else
//先算PDE 相当于上面代码的#define MiGetPdeAddress(va)  ((MMPTE*)(((((ULONG)(va)) >> 22) << 2) + PDE_BASE))
                uPdeAddr = (uAddr>>22)*4+0xc0300000;

        KdPrint(("uPdeAddr pde:%.8X\n",uPdeAddr));
        if( (*(PULONG)uPdeAddr & 0x1) != 0 )
        {
                if( (*(PULONG)uPdeAddr & 0x80) != 0 )//
                {
                        KdPrint(("uPdeAddr and ok\n"));
                        return VALID_PAGE;
                }
                else
                {
                        if( uInfo != 0 )
                        {
                                uPteAddr = (uAddr>>12)*8+0xc0000000;
                        }
                        else
                        {
//算PTE#define MiGetPteAddress(va) ((MMPTE*)(((((ULONG)(va)) >> 12) << 2) + PTE_BASE))
                                uPteAddr = (uAddr>>12)*4+0xc0000000;
                        }
                        KdPrint(("uPteAddr pte:%.8X\n",uPteAddr));
                        if( (*(PULONG)uPteAddr & 0x1) != 0 )
                                return VALID_PAGE;
                        else
                                return PTEINVALID;
                }
        }
        else
                return PDEINVALID;

} 网上流传的               

NOT PAE 模式下,我发现  校验VAROOT地址是否是合法的,结果老外那份到PTE 就空了,测试很多地址基本不合法,
但是网上流传的那份代码,直接if( (*(PULONG)uPdeAddr & 0x80) != 0 )//
                {
                        KdPrint(("uPdeAddr and ok\n"));
                        return VALID_PAGE;
                }
返回合法。这是为虾米,请高手解答下下

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 204
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
我也被这个搞得焦头烂额

目前的办法基本上是 要么用 MmIsAddressValid 不行就换 ProbeForRead
2011-12-1 08:46
0
雪    币: 266
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
我自己去查查资料看看,到底神马情况。
2011-12-1 10:29
0
游客
登录 | 注册 方可回帖
返回
//