1. 程式人生 > 其它 >ObpLookupDirectoryEntryEx函式逆向分析

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