• ObpLookupDirectoryEntryEx函数逆向分析


    0x00前言

    操作系统:windows 11

    工具:vs,IDA,windbg

    这是《深入解析Windows Kenrel》系列文章的第3章对象管理

    0x01逆向分析

    这个函数主要查询指定的目录对象中是否包含某对象

    函数原型

    __int64 __fastcall ObpLookupDirectoryEntryEx(
            PADAPTER_OBJECT DmaAdapter,             // 被搜索的目录对象
            unsigned __int16 *a2,                   // 要搜索的名字
            char a3,                                // 是否区分大小写
            __int64 a4,                             // 是否查询shaow目录
            char a5,                                // shaow结构体
            __int64 a6)                             // 查询详细信息结构通过这个返回

    ida伪代码分析

    __int64 __fastcall ObpLookupDirectoryEntryEx(
            PADAPTER_OBJECT DmaAdapter,             // 被搜索的目录对象
            unsigned __int16 *a2,                   // 要搜索的名字
            char a3,                                // 是否区分大小写
            __int64 a4,                             // 是否查询shaow目录
            char a5,                                // shaow结构体
            __int64 a6)                             // 查询详细信息通过这个返回
    {
      unsigned __int16 *v6; // rdi
      char v7; // r12
      bool v9; // r14
      unsigned int v10; // r11d
      unsigned __int64 v12; // rbx
      unsigned int v13; // r10d
      int v14; // r10d
      unsigned int v15; // edx
      int v16; // r10d
      __int64 v17; // rdx
      __int64 v18; // rsi
      __int64 v20; // r10
      __int64 v21; // rax
      __int128 v22; // rt0
      struct _DMA_ADAPTER *ShadowDirectory; // rbx
      __int64 v24; // r9
    
      v6 = (unsigned __int16 *)*((_QWORD *)a2 + 1); // name内容
      v7 = a4;
      v9 = (a3 & 0x40) != 0;                        // 是否区分大小写  64
      v10 = *a2 >> 1;                               // 宽字节  /2代表真实长度
      if ( v10 < 4 )
      {
        v13 = 0;                                    // hash值
      }
      else
      {
        v12 = 0i64;
        do
        {
          a4 = *(_QWORD *)v6;
          if ( (*(_QWORD *)v6 & 0xFF80FF80FF80FF80ui64) != 0 )
          {
            v20 = 4i64;
            do
            {
              v21 = (unsigned __int16)a4;
              if ( (unsigned __int16)a4 >= 0x61u )
              {
                if ( (unsigned __int16)a4 <= 0x7Au )
                  v21 = (unsigned int)(unsigned __int16)a4 - 32;
                else
                  v21 = (unsigned __int16)NLS_UPCASE((unsigned __int16)a4);
              }
              *(_QWORD *)&v22 = a4;
              *((_QWORD *)&v22 + 1) = v21;
              a4 = v22 >> 16;
              --v20;
            }
            while ( v20 );
          }
          else
          {
            a4 &= 0xFFDFFFDFFFDFFFDFui64;
          }
          v6 += 4;
          v10 -= 4;
          v12 = a4 + (v12 >> 1) + 3 * v12;
        }
        while ( v10 >= 4 );
        v13 = v12 + HIDWORD(v12);
      }
      while ( v10 )                                 // v10 真实长度
      {
        v15 = *v6;                                  // name的buffer
        v16 = (v13 >> 1) + 3 * v13;
        ++v6;
        --v10;
        if ( v15 < 0x61 )                           // 小于字符a 
          goto LABEL_12;
        if ( v15 > 0x7A )                           // 大于字符z
        {
          a4 = (unsigned __int16)NLS_UPCASE((unsigned __int16)v15);// hash值计算
          v13 = a4 + v14;
        }
        else
        {
          v16 -= 32;                                // 确保不是小写字母
    LABEL_12:
          v13 = v15 + v16;
        }
      }
      LOBYTE(a4) = v9;                              // 是否忽略大小写
      *(_DWORD *)(a6 + 24) = v13;                   // context 参数的values 和index项
      *(_WORD *)(a6 + 28) = v13 % 0x25;             // hash表的大小是37
      v18 = ObpLookupDirectoryUsingHash(DmaAdapter, a2, a6, a4);// 返回判断是否找到这个对象
      if ( !v18 && v7 )                             // 没找到的话再去shadow 找
      {
        do
        {
          LOBYTE(v17) = a5;                         // shadow结构体
          ShadowDirectory = (struct _DMA_ADAPTER *)ObpGetShadowDirectory(DmaAdapter, v17);// 一直到找到为止
          if ( ShadowDirectory )                    // 是否可以
          {
            if ( *(_BYTE *)(a6 + 30) )
            {
              ObfReferenceObject(DmaAdapter);       // 增加引用计数
              ObpUnlockDirectory(DmaAdapter, a6);
              ObpLockDirectoryShared(a6, ShadowDirectory);
              HalPutDmaAdapter(DmaAdapter);
            }
            LOBYTE(v24) = v9;
            v18 = ObpLookupDirectoryUsingHash(ShadowDirectory, a2, a6, v24);
          }
          DmaAdapter = ShadowDirectory;
        }
        while ( !v18 && ShadowDirectory );
      }
      return v18;
    }

    过程比较简单主要unicode 字符串对比在

    ObpLookupDirectoryUsingHash 函数实现
    void *__fastcall ObpLookupDirectoryUsingHash(__int64 a1, const UNICODE_STRING *a2, __int64 a3, BOOLEAN a4)
    {
      char v5; // bp
      __int64 **v9; // rsi
      __int64 *v10; // rdi
      int v11; // r15d
      void *v12; // rdi
      struct _DMA_ADAPTER *v13; // rcx
      void *result; // rax
    
      v5 = *(_BYTE *)(a3 + 30);
      v9 = (__int64 **)(a1 + 8i64 * *(unsigned __int16 *)(a3 + 28));
      if ( !v5 )
        ObpLockDirectoryShared(a3, a1);             // 是否有锁
      v10 = *v9;
      if ( !*v9 )
        goto LABEL_15;
      v11 = *(_DWORD *)(a3 + 24);                   // 长度
      do
      {
        if ( *((_DWORD *)v10 + 4) == v11            // 长度和内容一样
          && RtlEqualUnicodeString(                 // 比较2个unicode 是否相等
               a2,
               (PCUNICODE_STRING)(v10[1] - 48 - ObpInfoMaskToOffset[*(_BYTE *)(v10[1] - 48 + 26) & 3] + 8),
               a4) )
        {
          break;
        }
        v9 = (__int64 **)v10;                       // 强转2级指针
        v10 = (__int64 *)*v10;                      // 下一个节点
      }
      while ( v10 );
      if ( v10 )                                    // 是否找到了
      {
        v12 = (void *)v10[1];                       // object 对象
        ObfReferenceObject(v12);                    // 增加引用计数
        if ( !v5 )
        {
          ObpUnlockDirectory(a1, a3);               // 解封
          v9 = 0i64;
        }
        v13 = *(struct _DMA_ADAPTER **)(a3 + 8);
        if ( v13 )
          HalPutDmaAdapter(v13);
        *(_QWORD *)(a3 + 8) = v12;                  // a3 out参数
        result = v12;
        *(_QWORD *)(a3 + 16) = v9;                  // 返回值
      }
      else
      {
    LABEL_15:
        if ( !v5 )
          ObpUnlockDirectory(a1, a3);
        return 0i64;
      }
      return result;
    }
  • 相关阅读:
    JavaScript对象模型执行模型
    jQuery+CSS实现的图片滚动效果
    js笔记作用域(执行上下文[execution context],活动对象) 闭包
    JavaScript中的值类型和引用类型
    程序员第一定律:关于技能与收入
    JavaScript 秘密花园 http://bonsaiden.github.com/JavaScriptGarden/zh/
    程序员三大世界观 如何看待HTML5
    10 条建议让你创建更好的 jQuery 插件
    html 打印
    面向对象的 Javascript (声明篇)
  • 原文地址:https://www.cnblogs.com/feizianquan/p/16027693.html
Copyright © 2020-2023  润新知