테스트환경 : windows 10 x64 build 19041

OBJECT_HEADER에서 OBJECT_HEADER_NAME_INFO를 어떻게 얻을까 다양한 방법으로 구글링해보다가 ObQueryNameInfo(PVOID pObject) 함수가 있다는 것을 발견했습니다. 이 함수를 쓰면 POBJECT_HEADER_NAME_INFO 주소를 리턴하더군요. 어떻게 얻나 궁금해서 windbg로 까봤습니다.

0: kd> u ObQueryNameInfo
nt!ObQueryNameInfo:
fffff803`6987b920 0fb641ea        movzx   eax,byte ptr [rcx-16h]
fffff803`6987b924 4883c1d0        add     rcx,0FFFFFFFFFFFFFFD0h
fffff803`6987b928 a802            test    al,2
fffff803`6987b92a 7416            je      nt!ObQueryNameInfo+0x22 (fffff803`6987b942)
fffff803`6987b92c 83e003          and     eax,3
fffff803`6987b92f 488d154aa55a00  lea     rdx,[nt!ObpInfoMaskToOffset (fffff803`69e25e80)]
fffff803`6987b936 0fb60410        movzx   eax,byte ptr [rax+rdx]
fffff803`6987b93a 482bc8          sub     rcx,rax
fffff803`6987b93d 488bc1          mov     rax,rcx
fffff803`6987b940 c3              ret

먼저 인자에서 0x16을 뺀것을 포인터 참조해서 저장하고, 그 다음은 0x30만큼 빼고 주소를 저장하네요. (인자로는 DRIVER_OBJECT 0xffffc28f1318ce30 를 줘봤습니다. )

일단 0x30만큼 뺀 것은 OBJECT_HADER 구조체였습니다. (대충 감으로 때려맞춤...)

kd> dt _OBJECT_HEADER 0xffffc28f1318ce30-0x30
nt!_OBJECT_HEADER
   +0x000 PointerCount     : 0n3
   +0x008 HandleCount      : 0n0
   +0x008 NextToFree       : (null) 
   +0x010 Lock             : _EX_PUSH_LOCK
   +0x018 TypeIndex        : 0x13 ''
   +0x019 TraceFlags       : 0 ''
   +0x019 DbgRefTrace      : 0y0
   +0x019 DbgTracePermanent : 0y0
   +0x01a InfoMask         : 0x2 ''
   +0x01b Flags            : 0x12 ''
   +0x01b NewObject        : 0y0
   +0x01b KernelObject     : 0y1
   +0x01b KernelOnlyAccess : 0y0
   +0x01b ExclusiveObject  : 0y0
   +0x01b PermanentObject  : 0y1
   +0x01b DefaultSecurityQuota : 0y0
   +0x01b SingleHandleEntry : 0y0
   +0x01b DeletedInline    : 0y0
   +0x01c Reserved         : 0xffffc28f
   +0x020 ObjectCreateInfo : 0x00000000`00000001 _OBJECT_CREATE_INFORMATION
   +0x020 QuotaBlockCharged : 0x00000000`00000001 Void
   +0x028 SecurityDescriptor : 0xffffb20d`a6735cee Void
   +0x030 Body             : _QUAD

0x16만큼 뺀것은 +0x1A에 위치해 있는 InfoMask 필드네요. InfoMask & 2 가 참이면 InfoMask & 3을 하여 index로 사용합니다. (예제에서는 2 & 3 = 2(index))

그 다음으로 ObpInfoMaskToOffset 에서 index를 사용하여 오프셋을 꺼내옵니다.

(BYTE*)ObpInfoMaskToOffset(0xfffff803`69e25e80) + index(2) (예제는 fffff803`69e25e82가 되겠군요.)

2: kd> db fffff803`69e25e80
fffff803`69e25e80  00 20 20 40 10 30 30 50-20 40 40 60 30 50 50 70  .  @.00P @@`0PPp
fffff803`69e25e90  10 30 30 50 20 40 40 60-30 50 50 70 40 60 60 80  .00P @@`0PPp@``.
fffff803`69e25ea0  10 30 30 50 20 40 40 60-30 50 50 70 40 60 60 80  .00P @@`0PPp@``.
fffff803`69e25eb0  20 40 40 60 30 50 50 70-40 60 60 80 50 70 70 90   @@`0PPp@``.Ppp.
fffff803`69e25ec0  10 30 30 50 20 40 40 60-30 50 50 70 40 60 60 80  .00P @@`0PPp@``.
fffff803`69e25ed0  20 40 40 60 30 50 50 70-40 60 60 80 50 70 70 90   @@`0PPp@``.Ppp.
fffff803`69e25ee0  20 40 40 60 30 50 50 70-40 60 60 80 50 70 70 90   @@`0PPp@``.Ppp.
fffff803`69e25ef0  30 50 50 70 40 60 60 80-50 70 70 90 60 80 80 a0  0PPp@``.Ppp.`...

OBJECT_HEADER 주소에서 꺼내온 0x20(OBJECT_HEADER_NAME_INFO 구조체 사이즈)만큼 빼고 해당 주소를 리턴합니다.

예제는 0xffffc28f1318ce00 - 0x20 = 0xffffc28f1318cde0

kd> dt _OBJECT_HEADER_NAME_INFO 0xffffc28f1318cde0
nt!_OBJECT_HEADER_NAME_INFO
   +0x000 Directory        : 0xffffb20d`a66ec5a0 _OBJECT_DIRECTORY
   +0x008 Name             : _UNICODE_STRING "KernelV"
   +0x018 ReferenceCount   : 0n0
   +0x01c Reserved         : 0

잘 얻어졌습니다.

ObpInfoMaskToOffset는 0x100개의 배열이며, 직접 생성할 수도 있습니다. (아래의 소스에 자세히 나와있습니다.)

github.com/hfiref0x/WinObjEx64/blob/master/Source/WinObjEx64/kldbg.c

 

 

+ Recent posts