ObpLookupDirectoryEntryEx函式逆向分析
阿新 • • 發佈:2022-03-19
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; }