标题: Win10的HANDLE_TABLE_ENTRY.ObjectPointerBits https://scz.617.cn/windows/201710261442.txt kd> dt nt!_HANDLE_TABLE_ENTRY +0x000 VolatileLowValue : Int8B +0x000 LowValue : Int8B +0x000 InfoTable : Ptr64 _HANDLE_TABLE_ENTRY_INFO +0x008 HighValue : Int8B +0x008 NextFreeHandleEntry : Ptr64 _HANDLE_TABLE_ENTRY +0x008 LeafHandleValue : _EXHANDLE +0x000 RefCountField : Int8B +0x000 Unlocked : Pos 0, 1 Bit +0x000 RefCnt : Pos 1, 16 Bits +0x000 Attributes : Pos 17, 3 Bits +0x000 ObjectPointerBits : Pos 20, 44 Bits +0x008 GrantedAccessBits : Pos 0, 25 Bits +0x008 NoRightsUpgrade : Pos 25, 1 Bit +0x008 Spare1 : Pos 26, 6 Bits +0x00c Spare2 : Uint4B Win10的HANDLE_TABLE_ENTRY没有Object成员,只有ObjectPointerBits,为了提取对 象(头)指针,必须这样: -------------------------------------------------------------------------- PHANDLE_TABLE_ENTRY ObjectTableEntry; POBJECT_HEADER ObjectHeader; /* * 方法A * * 在PDB中VolatileLowValue类型是int64 */ ObjectHeader = ( ObjectTableEntry->VolatileLowValue ) >> 16 ) & 0xFFFFFFFFFFFFFFF0; 或者 /* * 方法B */ ObjectHeader = ( ( ObjectTableEntry->ObjectPointerBits ) << 4 ) | 0xFFFF000000000000; -------------------------------------------------------------------------- 下面讲如何逆向得到上述两种算法。 反汇编nt!ObpReferenceObjectByHandleWithTag()。Win10使用TypeIndex时有个混淆 机制涉及全局变量ObHeaderCookie。去IDA中F5,Alt-T搜"ObHeaderCookie",定位: kd> u nt!ObpReferenceObjectByHandleWithTag+0x19e l 1 fffff800`831324be 0fb6057b9eecff movzx eax,byte ptr [nt!ObHeaderCookie (fffff800`82ffc340)] -------------------------------------------------------------------------- index = ObHeaderCookie ^ ObjectHeader->TypeIndex ^ ( ( ObjectHeader >> 8 ) & 0xff ); -------------------------------------------------------------------------- 上面的ObjectHeader本来不是这个名字,但我知道这个混淆算法细节,自然推断出哪 个是ObjectHeader。 然后在F5结果中向低址方向寻找对ObjectHeader的赋值操作: kd> u nt!ObpReferenceObjectByHandleWithTag+0xe4 l 4 fffff800`83132404 488bd6 mov rdx,rsi // Handle fffff800`83132407 498bc9 mov rcx,r9 // HandleTable fffff800`8313240a e801050000 call nt!ExpLookupHandleTableEntry fffff800`8313240f 488bf8 mov rdi,rax // rdi=ObjectTableEntry kd> u nt!ObpReferenceObjectByHandleWithTag+0x33e l 5 fffff800`8313265e 488b1f mov rbx,qword ptr [rdi] // rdi=ObjectTableEntry fffff800`83132661 488bcf mov rcx,rdi fffff800`83132664 0f1007 movups xmm0,xmmword ptr [rdi] fffff800`83132667 48c1fb10 sar rbx,10h // rbx=ObjectTableEntry->VolatileLowValue fffff800`8313266b 4883e3f0 and rbx,0FFFFFFFFFFFFFFF0h // rbx=ObjectHeader kd> u nt!ObpReferenceObjectByHandleWithTag+0x18e l 7 fffff800`831324ae 488bc3 mov rax,rbx // rbx=ObjectHeader fffff800`831324b1 48c1e808 shr rax,8 fffff800`831324b5 0fb6c8 movzx ecx,al // ecx=( ObjectHeader >> 8 ) & 0xff fffff800`831324b8 0fb64318 movzx eax,byte ptr [rbx+18h] // eax=ObjectHeader->TypeIndex fffff800`831324bc 33c8 xor ecx,eax fffff800`831324be 0fb6057b9eecff movzx eax,byte ptr [nt!ObHeaderCookie] fffff800`831324c5 33c8 xor ecx,eax nt!ObpReferenceObjectByHandleWithTag+0x33e附近的代码用C语言描述: -------------------------------------------------------------------------- /* * ObjectTableEntry第1个qword低20位与ObjectHeader无关,最终结果低4位恒为0 * * 在PDB中VolatileLowValue类型是int64 */ ObjectHeader = ( ObjectTableEntry->VolatileLowValue ) >> 16 ) & 0xFFFFFFFFFFFFFFF0; -------------------------------------------------------------------------- 不考虑符号位扩展的情况下,前述C代码等价于: -------------------------------------------------------------------------- ObjectHeader = ( ( ObjectTableEntry->ObjectPointerBits ) << 20 ) >> 16; -------------------------------------------------------------------------- 观察到ObjectPointerBits最高位总是1,此时若考虑符号位扩展,上述C代码修正成: -------------------------------------------------------------------------- ObjectHeader = ( ( ( ObjectTableEntry->ObjectPointerBits ) << 20 ) >> 16 ) | 0xFFFF000000000000; -------------------------------------------------------------------------- ObjectHeader = ( ( ObjectTableEntry->ObjectPointerBits ) << 4 ) | 0xFFFF000000000000; -------------------------------------------------------------------------- 在C编程时,将VolatileLowValue定义成int64,直接对之进行>>,方法A更接近汇编 语义;方法B强烈依赖于ObjectPointerBits最高位总是1的事实,偏离汇编语义。不 过,可能方法B更接近源代码C语义。因为只是逆向,权当瞎猜,微软用sar指令,可 能就是让ObjectPointerBits省2个字节的意思。