Debugging/Windows

Objects and Handles

haewon83 2023. 4. 15. 00:54

 

  • Object
    • A single, run-time instance of a statically defined object type (File, Process..)
  • Object attribute
    • A field of data in an object that partially defines the object's state
  • Object methods
    • The means for manipulating objects, usually read or change the object attributes
    • Open method for a process would accept a process identifier as input and return a pointer to the object as output
  • Handle
    • A reference to an instance of an object
    • All user-mode processes must own a handle to an object before their threads can use the object
  • A process is an instance of the process object type; a file is an instance of the file object type, and so on
  • Objects provide a convenient means for accomplishing the following four important operating system tasks:
    • Providing human-readable names for system resources
    • Sharing resources and data among processes
    • Protecting resources from unauthorized access
    • Reference tracking, which allows the system to know when an object is no longer in use so that it can be automatically de-allocated
  • When a process creates or opens an object by name, it receives a handle that represents its access to the object
  • Referring to an object by its handle is faster than using its name because the object manager can skip the name lookup and find the object directly
  • Processes can also acquire handles to objects by
    • Inheriting handles at process creation time
    • Receiving a duplicated handle from another process

 

Handle API examples

BOOL CreateProcessA(
  [in, optional]      LPCSTR                lpApplicationName,
  [in, out, optional] LPSTR                 lpCommandLine,
  [in, optional]      LPSECURITY_ATTRIBUTES lpProcessAttributes,
  [in, optional]      LPSECURITY_ATTRIBUTES lpThreadAttributes,
  [in]                BOOL                  bInheritHandles,
  [in]                DWORD                 dwCreationFlags,
  [in, optional]      LPVOID                lpEnvironment,
  [in, optional]      LPCSTR                lpCurrentDirectory,
  [in]                LPSTARTUPINFOA        lpStartupInfo,
  [out]               LPPROCESS_INFORMATION lpProcessInformation
);
 
[out] lpProcessInformation
A pointer to a PROCESS_INFORMATION structure that receives identification information about the new process.
Handles in PROCESS_INFORMATION must be closed with CloseHandle when they are no longer needed. ### <---
 
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
 
void _tmain( int argc, TCHAR *argv[] )
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
 
    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );
 
    if( argc != 2 )
    {
        printf("Usage: %s [cmdline]\n", argv[0]);
        return;
    }
 
    // Start the child process.
    if( !CreateProcess( NULL,   // No module name (use command line)
        argv[1],        // Command line
        NULL,           // Process handle not inheritable
        NULL,           // Thread handle not inheritable
        FALSE,          // Set handle inheritance to FALSE
        0,              // No creation flags
        NULL,           // Use parent's environment block
        NULL,           // Use parent's starting directory
        &si,            // Pointer to STARTUPINFO structure
        &pi )           // Pointer to PROCESS_INFORMATION structure
    )
    {
        printf( "CreateProcess failed (%d).\n", GetLastError() );
        return;
    }
 
    // Wait until child process exits.
    WaitForSingleObject( pi.hProcess, INFINITE );
 
    // Close process and thread handles.
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
}
 
HANDLE CreateFileA(
  [in]           LPCSTR                lpFileName,
  [in]           DWORD                 dwDesiredAccess,
  [in]           DWORD                 dwShareMode,
  [in, optional] LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  [in]           DWORD                 dwCreationDisposition,
  [in]           DWORD                 dwFlagsAndAttributes,
  [in, optional] HANDLE                hTemplateFile
);
 
BOOL DuplicateHandle(
  [in]  HANDLE   hSourceProcessHandle,
  [in]  HANDLE   hSourceHandle,
  [in]  HANDLE   hTargetProcessHandle,
  [out] LPHANDLE lpTargetHandle,
  [in]  DWORD    dwDesiredAccess,
  [in]  BOOL     bInheritHandle,
  [in]  DWORD    dwOptions
);
 
#include <windows.h>
 
DWORD CALLBACK ThreadProc(PVOID pvParam);
 
int main()
{
    HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);
    HANDLE hMutexDup, hThread;
    DWORD dwThreadId;
 
    DuplicateHandle(GetCurrentProcess(),
                    hMutex,
                    GetCurrentProcess(),
                    &hMutexDup,
                    0,
                    FALSE,
                    DUPLICATE_SAME_ACCESS);
 
    hThread = CreateThread(NULL, 0, ThreadProc,
        (LPVOID) hMutexDup, 0, &dwThreadId);
 
    // Perform work here, closing the handle when finished with the
    // mutex. If the reference count is zero, the object is destroyed.
    CloseHandle(hMutex);
 
    // Wait for the worker thread to terminate and clean up.
    WaitForSingleObject(hThread, INFINITE);
    CloseHandle(hThread);
    return 0;
}
 
DWORD CALLBACK ThreadProc(PVOID pvParam)
{
    HANDLE hMutex = (HANDLE)pvParam;
 
    // Perform work here, closing the handle when finished with the
    // mutex. If the reference count is zero, the object is destroyed.
    CloseHandle(hMutex);
    return 0;
}

 

Object는 Resource의 추상화 개체

예를 들어, Harddisk Device는 Device의 특성과 Device에 대해서 수행될 수 있는 Operation을 Object에 기술

 

Object Manager는 이러한 Object를 관리하며, "Ob"는 Object Manager의 Prefix

 

Object는 named와 un-named가 있으며,

  • named object는 Object Manager에 의해서 global namespace에 위치
  • un-named object의 경우에는 user-mode에서 직접 접근이 불가하며, kernel-mode에서 실제 주소를 알고 있는 component가 접근 가능
  • 하지만 user-mode에서 명시적으로 Win32 API를 이용하여(CreateEvent, CreateMutex...) un-named object를 만든 경우에는 user-mode에서 접근 가능(Handle을 획득했기 때문에)

 

Object Namespace는 filesystem 계층 구조와 유사하며, System Startup 시점에 In-memory에 구성

Object Namespace 구성 항목

  • Root(\)
  • Directories
  • Symbolic links
  • Objects

 

Object Namespace는 Sysinternals의 WinObj 도구를 이용하여 다음 화면과 같이 확인 가능

https://learn.microsoft.com/en-us/sysinternals/downloads/winobj

 

Object Namespace는 System-wide 측면의 Container와 Session 측면의 Container로 분류

  • System-wide Container
    • \Driver
    • \Device
    • \Filesystem
    • \ObjectType

 

  • Session Container
    • \Windows
    • \DosDevices
    • \BaseNamedObjects

 

Windbg를 통해 Object Namespace 확인 방법

 

object namespace from root

3: kd> !object \
Object: ffffd60166c08060  Type: (ffffe60d7ae92a60) Directory
    ObjectHeader: ffffd60166c08030 (new version)
    HandleCount: 0  PointerCount: 57
    Directory Object: 00000000  Name: \
 
    Hash Address          Type                      Name
    ---- -------          ----                      ----
     01  ffffe60d7bc97d50 Mutant                    PendingRenameMutex
         ffffd60166c07ba0 Directory                 ObjectTypes
     02  ffffe60d7e6d4260 FilterConnectionPort      storqosfltport
     03  ffffe60d7b6ddd10 FilterConnectionPort      MicrosoftMalwareProtectionRemoteIoPortWD
     05  ffffd60166c2e490 SymbolicLink              SystemRoot
     06  ffffd60168304a20 Directory                 Sessions
         ffffe60d7b6dd8f0 FilterConnectionPort      MicrosoftMalwareProtectionVeryLowIoPortWD
     08  ffffd60166c09d80 Directory                 ArcName
     09  ffffe60d7e6d2a50 FilterConnectionPort      WcifsPort
         ffffd60166cac5e0 Directory                 NLS
     10  ffffe60d7ea5de60 Event                     LanmanServerAnnounceEvent
         ffffe60d7e75ddb0 ALPC Port                 ThemeApiPort
         ffffe60d7d1c1d00 Device                    UdfsCdRom
         ffffd60168304480 Directory                 Windows
         ffffd60166c075b0 Directory                 GLOBAL??
     11  ffffd60168305920 Directory                 RPC Control
         ffffe60d7b73f530 ALPC Port                 PdcPort
     13  ffffe60d7dd5fbc0 Event                     DSYSDBG.Debug.Trace.Memory.2b4
         ffffe60d7bcae7e0 Event                     EFSInitEvent
     14  ffffd60168303340 SymbolicLink              Dfs
         ffffe60d7b7eed80 Device                    clfs
     15  ffffe60d7d585670 Event                     CsrSbSyncEvent
         ffffe60d7b972d70 ALPC Port                 SeRmCommandPort
     16  ffffd60166c09540 SymbolicLink              DosDevices
     17  ffffd60168305560 Directory                 KnownDlls32
     18  ffffd60166c10e40 Key                       \REGISTRY
     19  ffffd6016a8670c0 Directory                 BaseNamedObjects
     20  ffffd60168484e10 Section                   Win32kCrossSessionGlobals
         ffffe60d7af68d30 ALPC Port                 PowerPort
     21  ffffe60d7e516310 ALPC Port                 SmSsWinStationApiPort
         ffffe60d7d52e530 Event                     UniqueInteractiveSessionIdEvent
         ffffd60166cce3e0 Directory                 UMDFCommunicationPorts
     22  ffffd601683040c0 Directory                 KnownDlls
         ffffe60d7b958b20 Device                    FatCdrom
         ffffe60d7b9588f0 Device                    Fat
         ffffe60d7aecfd30 ALPC Port                 PowerMonitorPort
     23  ffffe60d7b7aedc0 Device                    Ntfs
         ffffd60166cac960 Directory                 FileSystem
         ffffd60166c05830 Directory                 KernelObjects
     24  ffffe60d7b6dd4d0 FilterConnectionPort      MicrosoftMalwareProtectionControlPortWD
     26  ffffe60d7d155d30 ALPC Port                 SeLsaCommandPort
         ffffd60166c09230 Directory                 Callback
     28  ffffd60166c08820 Directory                 Security
     29  ffffe60d7d1b0d00 Device                    UdfsDisk
     30  ffffe60d7b6dd580 FilterConnectionPort      MicrosoftMalwareProtectionAsyncPortWD
         ffffd60166c08ae0 Directory                 Device
     32  ffffd60166c88e30 SymbolicLink              DriverData
     34  ffffd6016a843c90 Section                   LsaPerformance
         ffffe60d7bcebc70 ALPC Port                 SmApiPort
     35  ffffe60d7e6d47e0 FilterConnectionPort      CLDMSGPORT
         ffffe60d7b6ddf20 FilterConnectionPort      MicrosoftMalwareProtectionPortWD
         ffffd60166c2eb50 SymbolicLink              OSDataRoot
     36  ffffe60d7dd608e0 Event                     SAM_SERVICE_STARTED
         ffffd60166cac7a0 Directory                 Driver
         ffffd60166c79d80 Directory                 DriverStores

 

object namespace from filesystem

3: kd> !object \Filesystem
Object: ffffd60166cac960  Type: (ffffe60d7ae92a60) Directory
    ObjectHeader: ffffd60166cac930 (new version)
    HandleCount: 0  PointerCount: 34
    Directory Object: ffffd60166c08060  Name: FileSystem
 
    Hash Address          Type                      Name
    ---- -------          ----                      ----
     02  ffffe60d7eb16df0 Driver                    mrxsmb
     03  ffffe60d7eb19e30 Driver                    mrxsmb20
         ffffe60d7e822e50 Driver                    storqosflt
     04  ffffe60d7e5cb060 Driver                    luafv
         ffffe60d7b7ea5a0 Driver                    Wof
     11  ffffe60d7b9428f0 Driver                    rdbss
         ffffe60d7b8022e0 Device                    CdfsRecognizer
     12  ffffe60d7b7f2b00 Device                    UdfsDiskRecognizer
         ffffe60d7af020a0 Driver                    Fs_Rec
     13  ffffe60d7b8ee8f0 Driver                    Msfs
     15  ffffe60d7b970c30 Driver                    Dfsc
     17  ffffe60d7af27e30 Driver                    srvnet
     19  ffffe60d7e747e10 Driver                    wcifs
         ffffd60166cceae0 Directory                 Filters
     21  ffffe60d7eab8df0 Driver                    bowser
         ffffe60d7b7ccc80 Driver                    FltMgr
     22  ffffe60d7b7f2d40 Device                    FatCdRomRecognizer
     23  ffffe60d7aeeeb60 Driver                    Ntfs
     24  ffffe60d7e7e2e30 Driver                    CldFlt
         ffffe60d7b90cba0 Driver                    Npfs
         ffffe60d7b86de10 Driver                    Mup
         ffffe60d7af15970 Driver                    RAW
     25  ffffe60d7b802b80 Device                    ReFSRecognizer
         ffffe60d7b7edd80 Driver                    WdFilter
     27  ffffe60d7b749d20 Driver                    fastfat
     31  ffffe60d7b7f1d80 Device                    FatDiskRecognizer
     32  ffffe60d7b802dc0 Device                    ReFSv1Recognizer
     33  ffffe60d7ae80e30 Driver                    srv2
         ffffe60d7b9368f0 Driver                    NetBIOS
         ffffe60d7ba64e20 Driver                    FileCrypt
         ffffe60d7b7f3cf0 Device                    ExFatRecognizer
     34  ffffe60d7d4c2e30 Driver                    udfs
     35  ffffe60d7b8020a0 Device                    UdfsCdRomRecognizer

 

object namespace for C drive

3: kd> !object \Global??\c:
Object: ffffd60168185380  Type: (ffffe60d7ae927a0) SymbolicLink ### <--
    ObjectHeader: ffffd60168185350 (new version)
    HandleCount: 0  PointerCount: 1
    Directory Object: ffffd60166c075b0  Name: C:
    Flags: 00000000 ( Local )
    Target String is '\Device\HarddiskVolume4' ### <--
    Drive Letter Index is 3 (C:)

 

Object는 Object Header와 Object Body로 구성

 

Object Manager는 Object Header를 관리하고, Object Body는 Object를 실제로 사용하는 Component가 소유

Object가 Memory Manager가 관리하는 Pool(Paged or Non-paged)에 공간을 할당해야 하기 때문에, Pool에 할당하는 Memory Block은 Pool Header + Object Header + Object Body Size(EPROCESS, ...)

 

object allocation

1: kd> bl
     0 e Disable Clear  fffff807`390b4f50     0001 (0001) nt!ObCreateObject
 
1: kd> g
Breakpoint 0 hit
nt!ObCreateObject:
fffff807`390b4f50 4883ec58        sub     rsp,58h
 
4: kd> k
 # Child-SP          RetAddr           Call Site
00 ffffab0a`f239f1a8 ffffac55`c67d11f2 nt!ObCreateObject
01 ffffab0a`f239f1b0 ffffac55`c67c40b1 win32kbase!CompositionObject::Create+0x5e
02 ffffab0a`f239f220 ffffac55`c67c3f3a win32kbase!CreateSharedResourceObject+0x9d
03 ffffab0a`f239f2c0 ffffac55`c677a2c5 win32kbase!DirectComposition::CApplicationChannel::CreateInternalSharedResource+0x46
04 ffffab0a`f239f320 ffffac55`c67798ed win32kbase!DirectComposition::CApplicationChannel::ProcessCommandBufferIterator+0x925
05 ffffab0a`f239f420 fffff807`38bd5c05 win32kbase!NtDCompositionProcessChannelBatchBuffer+0x19d
06 ffffab0a`f239f4c0 00007ff8`25d23724 nt!KiSystemServiceCopyEnd+0x25
07 00000089`695cf2a8 00007ff8`2292a2bc 0x00007ff8`25d23724
08 00000089`695cf2b0 00000000`00000000 0x00007ff8`2292a2bc
 
4: kd> bp nt!ObpAllocateObject
 
4: kd> bl
     0 e Disable Clear  fffff807`390b4f50     0001 (0001) nt!ObCreateObject
     1 e Disable Clear  fffff807`3908f7c0     0001 (0001) nt!ObpAllocateObject
 
4: kd> gu
WARNING: Software breakpoints on session addresses can cause bugchecks.
Use hardware execution breakpoints (ba e) if possible.
Breakpoint 1 hit
nt!ObpAllocateObject:
fffff807`3908f7c0 4c894c2420      mov     qword ptr [rsp+20h],r9
 
4: kd> k
 # Child-SP          RetAddr           Call Site
00 ffffab0a`f239f0d8 fffff807`390593b1 nt!ObpAllocateObject
01 ffffab0a`f239f0e0 fffff807`390b4f8d nt!ObCreateObjectEx+0xf1
02 ffffab0a`f239f150 ffffac55`c67d11f2 nt!ObCreateObject+0x3d
03 ffffab0a`f239f1b0 ffffac55`c67c40b1 win32kbase!CompositionObject::Create+0x5e
04 ffffab0a`f239f220 ffffac55`c67c3f3a win32kbase!CreateSharedResourceObject+0x9d
05 ffffab0a`f239f2c0 ffffac55`c677a2c5 win32kbase!DirectComposition::CApplicationChannel::CreateInternalSharedResource+0x46
06 ffffab0a`f239f320 ffffac55`c67798ed win32kbase!DirectComposition::CApplicationChannel::ProcessCommandBufferIterator+0x925
07 ffffab0a`f239f420 fffff807`38bd5c05 win32kbase!NtDCompositionProcessChannelBatchBuffer+0x19d
08 ffffab0a`f239f4c0 00007ff8`25d23724 nt!KiSystemServiceCopyEnd+0x25
09 00000089`695cf2a8 00007ff8`2292a2bc 0x00007ff8`25d23724
0a 00000089`695cf2b0 00000000`00000000 0x00007ff8`2292a2bc
 
4: kd> bp nt!ExAllocatePoolWithTag
 
4: kd> bl
     0 e Disable Clear  fffff807`390b4f50     0001 (0001) nt!ObCreateObject
     1 e Disable Clear  fffff807`3908f7c0     0001 (0001) nt!ObpAllocateObject
     2 e Disable Clear  fffff807`38d56030     0001 (0001) nt!ExAllocatePoolWithTag
 
4: kd> gu
Breakpoint 2 hit
nt!ExAllocatePoolWithTag:
fffff807`38d56030 48895c2408      mov     qword ptr [rsp+8],rbx
 
4: kd> k
 # Child-SP          RetAddr           Call Site
00 ffffab0a`f239f058 fffff807`3908f960 nt!ExAllocatePoolWithTag   ## Allocation Size + POOL_HEADER
01 ffffab0a`f239f060 fffff807`390593b1 nt!ObpAllocateObject+0x1a0 ## Allocation Size of Object Header + Object Body
02 ffffab0a`f239f0e0 fffff807`390b4f8d nt!ObCreateObjectEx+0xf1
03 ffffab0a`f239f150 ffffac55`c67d11f2 nt!ObCreateObject+0x3d
04 ffffab0a`f239f1b0 ffffac55`c67c40b1 win32kbase!CompositionObject::Create+0x5e
05 ffffab0a`f239f220 ffffac55`c67c3f3a win32kbase!CreateSharedResourceObject+0x9d
06 ffffab0a`f239f2c0 ffffac55`c677a2c5 win32kbase!DirectComposition::CApplicationChannel::CreateInternalSharedResource+0x46
07 ffffab0a`f239f320 ffffac55`c67798ed win32kbase!DirectComposition::CApplicationChannel::ProcessCommandBufferIterator+0x925
08 ffffab0a`f239f420 fffff807`38bd5c05 win32kbase!NtDCompositionProcessChannelBatchBuffer+0x19d
09 ffffab0a`f239f4c0 00007ff8`25d23724 nt!KiSystemServiceCopyEnd+0x25
0a 00000089`695cf2a8 00007ff8`2292a2bc 0x00007ff8`25d23724
0b 00000089`695cf2b0 00000000`00000000 0x00007ff8`2292a2bc

 

Object Header는 Pool Header 다음에 위치하고, Object Header 다음에 Object Body가 위치

Object Header 구성

  • Object 유형
  • Object Retention 정보
  • Security Descriptor

 

nt!_OBJECT_HEADER

1: kd> dt nt!_POOL_HEADER
   +0x000 PreviousSize     : Pos 0, 8 Bits
   +0x000 PoolIndex        : Pos 8, 8 Bits
   +0x002 BlockSize        : Pos 0, 8 Bits
   +0x002 PoolType         : Pos 8, 8 Bits
   +0x000 Ulong1           : Uint4B
   +0x004 PoolTag          : Uint4B
   +0x008 ProcessBilled    : Ptr64 _EPROCESS
   +0x008 AllocatorBackTraceIndex : Uint2B
   +0x00a PoolTagHash      : Uint2B
 
1: kd> dt nt!_OBJECT_HEADER
   +0x000 PointerCount     : Int8B
   +0x008 HandleCount      : Int8B
   +0x008 NextToFree       : Ptr64 Void
   +0x010 Lock             : _EX_PUSH_LOCK
   +0x018 TypeIndex        : UChar
   +0x019 TraceFlags       : UChar
   +0x019 DbgRefTrace      : Pos 0, 1 Bit
   +0x019 DbgTracePermanent : Pos 1, 1 Bit
   +0x01a InfoMask         : UChar
   +0x01b Flags            : UChar
   +0x01b NewObject        : Pos 0, 1 Bit
   +0x01b KernelObject     : Pos 1, 1 Bit
   +0x01b KernelOnlyAccess : Pos 2, 1 Bit
   +0x01b ExclusiveObject  : Pos 3, 1 Bit
   +0x01b PermanentObject  : Pos 4, 1 Bit
   +0x01b DefaultSecurityQuota : Pos 5, 1 Bit
   +0x01b SingleHandleEntry : Pos 6, 1 Bit
   +0x01b DeletedInline    : Pos 7, 1 Bit
   +0x01c Reserved         : Uint4B
   +0x020 ObjectCreateInfo : Ptr64 _OBJECT_CREATE_INFORMATION
   +0x020 QuotaBlockCharged : Ptr64 Void
   +0x028 SecurityDescriptor : Ptr64 Void
   +0x030 Body             : _QUAD

 

할당된 Pool된 정보와 이와 연관된 Object Header 정보

Object Header Address = Object Address - sizeof(_OBJECT_HEADER)

example : Process Object Header

!process 0 0
...
...
...
PROCESS ffffd88e78cc6080 ### <-- Object Address
    SessionId: 0  Cid: 0a98    Peb: 36affa000  ParentCid: 0344
    DirBase: 18f151000  ObjectTable: ffffc68a84177d40  HandleCount: 169.
    Image: WmiPrvSE.exe
 
3: kd> !pool ffffd88e78cc6080 2 ### <--
Pool page ffffd88e78cc6080 region is Nonpaged pool
*ffffd88e78cc6000 size:  900 previous size:    0  (Allocated) *Proc ### <--
        Pooltag Proc : Process objects, Binary : nt!ps
 
3: kd> !object ffffd88e78cc6080
Object: ffffd88e78cc6080  Type: (ffffd88e75294e80) Process
    ObjectHeader: ffffd88e78cc6050 (new version)
    HandleCount: 6  PointerCount: 196603
 
3: kd> dt nt!_OBJECT_HEADER ffffd88e78cc6050
   +0x000 PointerCount     : 0n196603
   +0x008 HandleCount      : 0n6
   +0x008 NextToFree       : 0x00000000`00000006 Void
   +0x010 Lock             : _EX_PUSH_LOCK
   +0x018 TypeIndex        : 0xe ''
   +0x019 TraceFlags       : 0 ''
   +0x019 DbgRefTrace      : 0y0
   +0x019 DbgTracePermanent : 0y0
   +0x01a InfoMask         : 0x88 ''
   +0x01b Flags            : 0 ''
   +0x01b NewObject        : 0y0
   +0x01b KernelObject     : 0y0
   +0x01b KernelOnlyAccess : 0y0
   +0x01b ExclusiveObject  : 0y0
   +0x01b PermanentObject  : 0y0
   +0x01b DefaultSecurityQuota : 0y0
   +0x01b SingleHandleEntry : 0y0
   +0x01b DeletedInline    : 0y0
   +0x01c Reserved         : 0xfeb948d9
   +0x020 ObjectCreateInfo : 0xfffff807`47c517c0 _OBJECT_CREATE_INFORMATION
   +0x020 QuotaBlockCharged : 0xfffff807`47c517c0 Void
   +0x028 SecurityDescriptor : 0xffffc68a`8472c4e4 Void
   +0x030 Body             : _QUAD

 

※ Windows Server 2016 기준

Object Type을 확인하려면 Object Header의 TypeIndex field 값을 이용해야 합니다.

TypeIndex field를 이용하여 Index 값을 구해야 하는데 공식은 다음과 같습니다.

Index = TypeIndex ^ 2nd least significate byte of OBJECT_HEADER address ^ nt!ObHeaderCookie

https://medium.com/@ashabdalhalim/a-light-on-windows-10s-object-header-typeindex-value-e8f907e7073a

 

아래 예제를 통해 계산하는 방법을 살펴보겠습니다.

TypeIndex field는 0xe

OBJECT_HEADER address는 ffffd88e78cc6050, 하위 두 번째 byte는 60

nt!ObHeaderCookie의 byte 값은 69

이 값들을 XOR 연산 :  e ^ 60 ^ 69 = 00000000`00000007

 

이제 이 계산된 Index 값을 nt!ObTypeIndexTable의 Index로 활용하여 Object Type을 확인합니다.

$ptrsize는 Pseudo-Register

$ptrsize : The size of a pointer. In kernel mode, this size is the pointer size on the target computer.

poi : 주소 안의 값을 참조

 

nt!_OBJECT_TYPE

3: kd> dt nt!_OBJECT_HEADER ffffd88e78cc6050 TypeIndex
   +0x018 TypeIndex : 0xe ''
 
3: kd> db nt!ObHeaderCookie L1
fffff807`47d545dc  69
 
3: kd> ? e ^ 60 ^ 69
Evaluate expression: 7 = 00000000`00000007
 
3: kd> dt nt!_OBJECT_TYPE poi(nt!ObTypeIndexTable + (0x7 * @$ptrsize ))
   +0x000 TypeList         : _LIST_ENTRY [ 0xffffd88e`75294e80 - 0xffffd88e`75294e80 ]
   +0x010 Name             : _UNICODE_STRING "Process" ### <-- Object Type
   +0x020 DefaultObject    : (null)
   +0x028 Index            : 0x7 ''
   +0x02c TotalNumberOfObjects : 0x46
   +0x030 TotalNumberOfHandles : 0x22b
   +0x034 HighWaterNumberOfObjects : 0x4b
   +0x038 HighWaterNumberOfHandles : 0x24b
   +0x040 TypeInfo         : _OBJECT_TYPE_INITIALIZER ### <---
   +0x0b8 TypeLock         : _EX_PUSH_LOCK
   +0x0c0 Key              : 0x636f7250
   +0x0c8 CallbackList     : _LIST_ENTRY [ 0xffffc68a`80cb1200 - 0xffffc68a`80cb1200 ]
 
3: kd> dt _OBJECT_TYPE_INITIALIZER (poi(nt!ObTypeIndexTable + (0x7 * @$ptrsize )) + 0x40)
nt!_OBJECT_TYPE_INITIALIZER
   +0x000 Length           : 0x78
   +0x002 ObjectTypeFlags  : 0xca
   +0x002 CaseInsensitive  : 0y0
   +0x002 UnnamedObjectsOnly : 0y1
   +0x002 UseDefaultObject : 0y0
   +0x002 SecurityRequired : 0y1
   +0x002 MaintainHandleCount : 0y0
   +0x002 MaintainTypeList : 0y0
   +0x002 SupportsObjectCallbacks : 0y1
   +0x002 CacheAligned     : 0y1
   +0x003 UseExtendedParameters : 0y0
   +0x003 Reserved         : 0y0000000 (0)
   +0x004 ObjectTypeCode   : 0x20
   +0x008 InvalidAttributes : 0xb0
   +0x00c GenericMapping   : _GENERIC_MAPPING
   +0x01c ValidAccessMask  : 0x1fffff
   +0x020 RetainAccess     : 0x101000
   +0x024 PoolType         : 200 ( NonPagedPoolNx )
   +0x028 DefaultPagedPoolCharge : 0x1000
   +0x02c DefaultNonPagedPoolCharge : 0x8a8
   +0x030 DumpProcedure    : (null)
   +0x038 OpenProcedure    : 0xfffff807`47d99140     long  nt!PspProcessOpen+0 ### <---
   +0x040 CloseProcedure   : 0xfffff807`47e04c50     void  nt!PspProcessClose+0 ### <---
   +0x048 DeleteProcedure  : 0xfffff807`47de0cb0     void  nt!PspProcessDelete+0 ### <---
   +0x050 ParseProcedure   : (null)
   +0x050 ParseProcedureEx : (null)
   +0x058 SecurityProcedure : 0xfffff807`47db7bc0     long  nt!SeDefaultObjectMethod+0 ### <---
   +0x060 QueryNameProcedure : (null)
   +0x068 OkayToCloseProcedure : (null)
   +0x070 WaitObjectFlagMask : 0
   +0x074 WaitObjectFlagOffset : 0
   +0x076 WaitObjectPointerOffset : 0

 

이제 Object가 Process Type인 것을 확인하였으니, 실제 구조체도 조회해보겠습니다.

Object Type별 구조체 예제

  • File: _FILE_OBJECT
  • Process: _EPROCESS
  • SymbolicLink: _OBJECT_SYMBOLIC_LINK
  • Token: _TOKEN
  • Thread: _ETHREAD
  • Mutant: _KMUTANT
  • Driver: _DRIVER_OBJECT
  • Key: _CM_KEY_BODY
  • Type: _OBJECT_TYPE

 

nt!_EPROCESS

3: kd> dt nt!_EPROCESS ffffd88e78cc6080
   +0x000 Pcb              : _KPROCESS
   +0x2d8 ProcessLock      : _EX_PUSH_LOCK
   +0x2e0 UniqueProcessId  : 0x00000000`00000a98 Void
   +0x2e8 ActiveProcessLinks : _LIST_ENTRY [ 0xfffff807`47c205e0 - 0xffffd88e`78f5f368 ]
   +0x2f8 RundownProtect   : _EX_RUNDOWN_REF
   +0x300 Flags2           : 0xd014
   +0x300 JobNotReallyActive : 0y0
   +0x300 AccountingFolded : 0y0
   +0x300 NewProcessReported : 0y1
   +0x300 ExitProcessReported : 0y0
   +0x300 ReportCommitChanges : 0y1
   +0x300 LastReportMemory : 0y0
   +0x300 ForceWakeCharge  : 0y0
   +0x300 CrossSessionCreate : 0y0
   +0x300 NeedsHandleRundown : 0y0
   +0x300 RefTraceEnabled  : 0y0
   +0x300 PicoCreated      : 0y0
   +0x300 EmptyJobEvaluated : 0y0
   +0x300 DefaultPagePriority : 0y101
   +0x300 PrimaryTokenFrozen : 0y1
   +0x300 ProcessVerifierTarget : 0y0
   +0x300 RestrictSetThreadContext : 0y0
   +0x300 AffinityPermanent : 0y0
   +0x300 AffinityUpdateEnable : 0y0
   +0x300 PropagateNode    : 0y0
   +0x300 ExplicitAffinity : 0y0
   +0x300 ProcessExecutionState : 0y00
   +0x300 EnableReadVmLogging : 0y0
   +0x300 EnableWriteVmLogging : 0y0
   +0x300 FatalAccessTerminationRequested : 0y0
   +0x300 DisableSystemAllowedCpuSet : 0y0
   +0x300 ProcessStateChangeRequest : 0y00
   +0x300 ProcessStateChangeInProgress : 0y0
   +0x300 InPrivate        : 0y0
   +0x304 Flags            : 0x144d0c01
   +0x304 CreateReported   : 0y1
   +0x304 NoDebugInherit   : 0y0
   +0x304 ProcessExiting   : 0y0
   +0x304 ProcessDelete    : 0y0
   +0x304 ManageExecutableMemoryWrites : 0y0
   +0x304 VmDeleted        : 0y0
   +0x304 OutswapEnabled   : 0y0
   +0x304 Outswapped       : 0y0
   +0x304 FailFastOnCommitFail : 0y0
   +0x304 Wow64VaSpace4Gb  : 0y0
   +0x304 AddressSpaceInitialized : 0y11
   +0x304 SetTimerResolution : 0y0
   +0x304 BreakOnTermination : 0y0
   +0x304 DeprioritizeViews : 0y0
   +0x304 WriteWatch       : 0y0
   +0x304 ProcessInSession : 0y1
   +0x304 OverrideAddressSpace : 0y0
   +0x304 HasAddressSpace  : 0y1
   +0x304 LaunchPrefetched : 0y1
   +0x304 Background       : 0y0
   +0x304 VmTopDown        : 0y0
   +0x304 ImageNotifyDone  : 0y1
   +0x304 PdeUpdateNeeded  : 0y0
   +0x304 VdmAllowed       : 0y0
   +0x304 ProcessRundown   : 0y0
   +0x304 ProcessInserted  : 0y1
   +0x304 DefaultIoPriority : 0y010
   +0x304 ProcessSelfDelete : 0y0
   +0x304 SetTimerResolutionLink : 0y0
   +0x308 CreateTime       : _LARGE_INTEGER 0x01d967d0`44de3e44
   +0x310 ProcessQuotaUsage : [2] 0x2bf8
   +0x320 ProcessQuotaPeak : [2] 0x34c8
   +0x330 PeakVirtualSize  : 0x00000201`04bb3000
   +0x338 VirtualSize      : 0x00000201`047d2000
   +0x340 SessionProcessLinks : _LIST_ENTRY [ 0xffffb600`2e1c5010 - 0xffffd88e`78f5f3c0 ]
   +0x350 ExceptionPortData : 0xffffd88e`7722dd30 Void
   +0x350 ExceptionPortValue : 0xffffd88e`7722dd30
   +0x350 ExceptionPortState : 0y000
   +0x358 Token            : _EX_FAST_REF
   +0x360 MmReserved       : 0
   +0x368 AddressCreationLock : _EX_PUSH_LOCK
   +0x370 PageTableCommitmentLock : _EX_PUSH_LOCK
   +0x378 RotateInProgress : (null)
   +0x380 ForkInProgress   : (null)
   +0x388 CommitChargeJob  : 0xffffd88e`79111990 _EJOB
   +0x390 CloneRoot        : _RTL_AVL_TREE
   +0x398 NumberOfPrivatePages : 0x192
   +0x3a0 NumberOfLockedPages : 0
   +0x3a8 Win32Process     : 0xffffc617`82802050 Void
   +0x3b0 Job              : 0xffffd88e`79111990 _EJOB
   +0x3b8 SectionObject    : 0xffffc68a`853a6600 Void
   +0x3c0 SectionBaseAddress : 0x00007ff7`b8860000 Void
   +0x3c8 Cookie           : 0x907252e
   +0x3d0 WorkingSetWatch  : (null)
   +0x3d8 Win32WindowStation : 0x00000000`00000164 Void
   +0x3e0 InheritedFromUniqueProcessId : 0x00000000`00000344 Void
   +0x3e8 Spare0           : (null)
   +0x3f0 OwnerProcessId   : 0x344
   +0x3f8 Peb              : 0x00000003`6affa000 _PEB
   +0x400 Session          : 0xffffb600`2e1c5000 _MM_SESSION_SPACE
   +0x408 Spare1           : (null)
   +0x410 QuotaBlock       : 0xfffff807`47c517c0 _EPROCESS_QUOTA_BLOCK
   +0x418 ObjectTable      : 0xffffc68a`84177d40 _HANDLE_TABLE
   +0x420 DebugPort        : (null)
   +0x428 WoW64Process     : (null)
   +0x430 DeviceMap        : 0xffffc68a`808137e0 Void
   +0x438 EtwDataSource    : 0xffffd88e`791914d0 Void
   +0x440 PageDirectoryPte : 0
   +0x448 ImageFilePointer : 0xffffd88e`78d587c0 _FILE_OBJECT
   +0x450 ImageFileName    : [15]  "WmiPrvSE.exe"
   +0x45f PriorityClass    : 0x2 ''
   +0x460 SecurityPort     : (null)
   +0x468 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO
   +0x470 JobLinks         : _LIST_ENTRY [ 0xffffd88e`791119b8 - 0xffffd88e`791119b8 ]
   +0x480 HighestUserAddress : 0x00007fff`ffff0000 Void
   +0x488 ThreadListHead   : _LIST_ENTRY [ 0xffffd88e`78fe4728 - 0xffffd88e`79058728 ]
   +0x498 ActiveThreads    : 4
   +0x49c ImagePathHash    : 0
   +0x4a0 DefaultHardErrorProcessing : 0
   +0x4a4 LastThreadExitStatus : 0n0
   +0x4a8 PrefetchTrace    : _EX_FAST_REF
   +0x4b0 LockedPagesList  : (null)
   +0x4b8 ReadOperationCount : _LARGE_INTEGER 0x0
   +0x4c0 WriteOperationCount : _LARGE_INTEGER 0x0
   +0x4c8 OtherOperationCount : _LARGE_INTEGER 0x6f
   +0x4d0 ReadTransferCount : _LARGE_INTEGER 0x0
   +0x4d8 WriteTransferCount : _LARGE_INTEGER 0x0
   +0x4e0 OtherTransferCount : _LARGE_INTEGER 0x5a0
   +0x4e8 CommitChargeLimit : 0x21e84
   +0x4f0 CommitCharge     : 0x1f0
   +0x4f8 CommitChargePeak : 0x4ec
   +0x500 Vm               : _MMSUPPORT_FULL
   +0x610 MmProcessLinks   : _LIST_ENTRY [ 0xfffff807`47c4c0e0 - 0xffffd88e`78f5f690 ]
   +0x620 ModifiedPageCount : 1
   +0x624 ExitStatus       : 0n259
   +0x628 VadRoot          : _RTL_AVL_TREE
   +0x630 VadHint          : 0xffffd88e`79516210 Void
   +0x638 VadCount         : 0x44
   +0x640 VadPhysicalPages : 0
   +0x648 VadPhysicalPagesLimit : 0
   +0x650 AlpcContext      : _ALPC_PROCESS_CONTEXT
   +0x670 TimerResolutionLink : _LIST_ENTRY [ 0x00000000`00000000 - 0x00000000`00000000 ]
   +0x680 TimerResolutionStackRecord : (null)
   +0x688 RequestedTimerResolution : 0
   +0x68c SmallestTimerResolution : 0
   +0x690 ExitTime         : _LARGE_INTEGER 0x0
   +0x698 InvertedFunctionTable : (null)
   +0x6a0 InvertedFunctionTableLock : _EX_PUSH_LOCK
   +0x6a8 ActiveThreadsHighWatermark : 9
   +0x6ac LargePrivateVadCount : 0
   +0x6b0 ThreadListLock   : _EX_PUSH_LOCK
   +0x6b8 WnfContext       : 0xffffc68a`853a88b0 Void
   +0x6c0 ServerSilo       : (null)
   +0x6c8 SignatureLevel   : 0 ''
   +0x6c9 SectionSignatureLevel : 0 ''
   +0x6ca Protection       : _PS_PROTECTION
   +0x6cb HangCount        : 0y000
   +0x6cb GhostCount       : 0y000
   +0x6cb PrefilterException : 0y0
   +0x6cc Flags3           : 0x40c008
   +0x6cc Minimal          : 0y0
   +0x6cc ReplacingPageRoot : 0y0
   +0x6cc Crashed          : 0y0
   +0x6cc JobVadsAreTracked : 0y1
   +0x6cc VadTrackingDisabled : 0y0
   +0x6cc AuxiliaryProcess : 0y0
   +0x6cc SubsystemProcess : 0y0
   +0x6cc IndirectCpuSets  : 0y0
   +0x6cc RelinquishedCommit : 0y0
   +0x6cc HighGraphicsPriority : 0y0
   +0x6cc CommitFailLogged : 0y0
   +0x6cc ReserveFailLogged : 0y0
   +0x6cc SystemProcess    : 0y0
   +0x6cc HideImageBaseAddresses : 0y0
   +0x6cc AddressPolicyFrozen : 0y1
   +0x6cc ProcessFirstResume : 0y1
   +0x6cc ForegroundExternal : 0y0
   +0x6cc ForegroundSystem : 0y0
   +0x6cc HighMemoryPriority : 0y0
   +0x6cc EnableProcessSuspendResumeLogging : 0y0
   +0x6cc EnableThreadSuspendResumeLogging : 0y0
   +0x6cc SecurityDomainChanged : 0y0
   +0x6cc SecurityFreezeComplete : 0y1
   +0x6cc VmProcessorHost  : 0y0
   +0x6d0 DeviceAsid       : 0n0
   +0x6d8 SvmData          : (null)
   +0x6e0 SvmProcessLock   : _EX_PUSH_LOCK
   +0x6e8 SvmLock          : 0
   +0x6f0 SvmProcessDeviceListHead : _LIST_ENTRY [ 0xffffd88e`78cc6770 - 0xffffd88e`78cc6770 ]
   +0x700 LastFreezeInterruptTime : 0
   +0x708 DiskCounters     : (null)
   +0x710 PicoContext      : (null)
   +0x718 EnclaveTable     : (null)
   +0x720 EnclaveNumber    : 0
   +0x728 EnclaveLock      : _EX_PUSH_LOCK
   +0x730 HighPriorityFaultsAllowed : 0
   +0x738 EnergyContext    : (null)
   +0x740 VmContext        : (null)
   +0x748 SequenceNumber   : 0x61
   +0x750 CreateInterruptTime : 0x962238fb
   +0x758 CreateUnbiasedInterruptTime : 0x962238fb
   +0x760 TotalUnbiasedFrozenTime : 0
   +0x768 LastAppStateUpdateTime : 0x962238fb
   +0x770 LastAppStateUptime : 0y0000000000000000000000000000000000000000000000000000000000000 (0)
   +0x770 LastAppState     : 0y000
   +0x778 SharedCommitCharge : 0x1f5
   +0x780 SharedCommitLock : _EX_PUSH_LOCK
   +0x788 SharedCommitLinks : _LIST_ENTRY [ 0xffffc68a`84ea3808 - 0xffffc68a`851a59c8 ]
   +0x798 AllowedCpuSets   : 0
   +0x7a0 DefaultCpuSets   : 0
   +0x798 AllowedCpuSetsIndirect : (null)
   +0x7a0 DefaultCpuSetsIndirect : (null)
   +0x7a8 DiskIoAttribution : (null)
   +0x7b0 DxgProcess       : 0xffffc68a`85679b80 Void
   +0x7b8 Win32KFilterSet  : 0
   +0x7c0 ProcessTimerDelay : _PS_INTERLOCKED_TIMER_DELAY_VALUES
   +0x7c8 KTimerSets       : 0
   +0x7cc KTimer2Sets      : 0
   +0x7d0 ThreadTimerSets  : 3
   +0x7d8 VirtualTimerListLock : 0
   +0x7e0 VirtualTimerListHead : _LIST_ENTRY [ 0xffffd88e`78cc6860 - 0xffffd88e`78cc6860 ]
   +0x7f0 WakeChannel      : _WNF_STATE_NAME
   +0x7f0 WakeInfo         : _PS_PROCESS_WAKE_INFORMATION
   +0x820 MitigationFlags  : 0x21
   +0x820 MitigationFlagsValues : <unnamed-tag>
   +0x824 MitigationFlags2 : 0
   +0x824 MitigationFlags2Values : <unnamed-tag>
   +0x828 PartitionObject  : 0xffffd88e`75274420 Void
   +0x830 SecurityDomain   : 0
   +0x838 ParentSecurityDomain : 0
   +0x840 CoverageSamplerContext : (null)
   +0x848 MmHotPatchContext : (null)
 
3: kd> dt nt!_EPROCESS ffffd88e78cc6080 ImageFileName
   +0x450 ImageFileName : [15]  "WmiPrvSE.exe"

 

위에서 살펴본 ObjectType은 Object Namespace에 ObjectTypes Container로 존재하며, 해당 Container에 다양한 Object Type이 위치합니다.

 

!object \ObjectTypes

3: kd> !object \ObjectTypes
Object: ffffc68a80807ba0  Type: (ffffd88e75294640) Directory
    ObjectHeader: ffffc68a80807b70 (new version)
    HandleCount: 0  PointerCount: 67
    Directory Object: ffffc68a80808060  Name: ObjectTypes
 
    Hash Address          Type                      Name
    ---- -------          ----                      ----
     00  ffffd88e752f42a0 Type                      TmTm
     01  ffffd88e7529ec40 Type                      Desktop
         ffffd88e75294e80 Type                      Process
     02  ffffd88e752f37a0 Type                      RegistryTransaction
     03  ffffd88e7529da60 Type                      DebugObject
     04  ffffd88e75a26bc0 Type                      VRegConfigurationContext
         ffffd88e7529d4e0 Type                      TpWorkerFactory
     05  ffffd88e752f3a60 Type                      Adapter
         ffffd88e75294bc0 Type                      Token
     06  ffffd88e753fcc40 Type                      DxgkSharedResource
     07  ffffd88e7529e2a0 Type                      PsSiloContextPaged
     08  ffffd88e753fc400 Type                      NdisCmState
         ffffd88e7529e140 Type                      ActivityReference
     09  ffffd88e753fcae0 Type                      PcwObject
         ffffd88e752f4c40 Type                      WmiGuid
     11  ffffd88e753fbbc0 Type                      DmaAdapter
         ffffd88e753fba60 Type                      EtwRegistration
     12  ffffd88e75a27ae0 Type                      DxgkSharedBundleObject
         ffffd88e752f3640 Type                      Session
         ffffd88e7529eda0 Type                      RawInputManager
         ffffd88e7529e6c0 Type                      Timer
     13  ffffd88e7529d0c0 Type                      Mutant
     14  ffffd88e7529eae0 Type                      IRTimer
     16  ffffd88e75a27da0 Type                      DxgkCurrentDxgProcessObject
         ffffd88e752f4140 Type                      IoCompletion
     17  ffffd88e75a27c40 Type                      DxgkSharedProtectedSessionObject
         ffffd88e753fcf00 Type                      DxgkSharedSyncObject
         ffffd88e7529e820 Type                      WindowStation
         ffffd88e7529dd20 Type                      Profile
     18  ffffd88e752f3e80 Type                      File
     20  ffffd88e7529d640 Type                      Partition
     21  ffffd88e753fb4e0 Type                      DxgkSharedKeyedMutexObject
         ffffd88e7529d900 Type                      Semaphore
     22  ffffd88e7529e560 Type                      PsSiloContextNonPaged
     23  ffffd88e753fb380 Type                      EtwConsumer
         ffffd88e7529dbc0 Type                      Composition
     24  ffffd88e753fcda0 Type                      CoverageSampler
         ffffd88e753fc2a0 Type                      EtwSessionDemuxEntry
         ffffd88e7529ef00 Type                      CoreMessaging
     25  ffffd88e752f4820 Type                      TmTx
         ffffd88e752947a0 Type                      SymbolicLink
     26  ffffd88e753fb7a0 Type                      FilterConnectionPort
         ffffd88e752f4980 Type                      Key
         ffffd88e7529d380 Type                      KeyedEvent
         ffffd88e7529e400 Type                      Callback
     27  ffffd88e752f3220 Type                      WaitCompletionPacket
     28  ffffd88e7529d7a0 Type                      UserApcReserve
         ffffd88e752944e0 Type                      Job
     29  ffffd88e75a27140 Type                      DxgkDisplayManagerObject
         ffffd88e75a26e80 Type                      DxgkSharedSwapChainObject
         ffffd88e752f46c0 Type                      Controller
         ffffd88e7529d220 Type                      IoCompletionReserve
     30  ffffd88e752f3d20 Type                      Device
         ffffd88e75294640 Type                      Directory
     31  ffffd88e752f4560 Type                      Section
         ffffd88e752f4400 Type                      TmEn
         ffffd88e7529de80 Type                      Thread
     32  ffffd88e75a27f00 Type                      DxgkCompositionObject
         ffffd88e752940c0 Type                      Type
     33  ffffd88e753fb640 Type                      FilterCommunicationPort
         ffffd88e752f4ae0 Type                      PowerRequest
     35  ffffd88e752f4f00 Type                      TmRm
         ffffd88e7529e980 Type                      Event
     36  ffffd88e752f3bc0 Type                      ALPC Port
         ffffd88e752f4da0 Type                      Driver

 

Object Body

Object Body는 해당 Object를 사용하는 Component가 소유

주로 Object는 Object Body를 의미

Object Body의 크기와 Object Body 안에 들어가는 Field 값들은 Object Type에 따라 상이

 

Handle Table

Handle Table은 Handle을 참조하고 있는 Object로 변환하기 위해 사용

Handle Table은 Kernel mode 자료 구조

Handle Table은 프로세스별로 존재하며, 모든 프로세스는 자기 자신의 Handle Table을 이용하여, Handle을 Object로 변환

Handle Table은 HANDLE_TABLE_ENTRY 유형 Entry의 배열

따라서, Handle은 Handle Table의 Index

 

※ OS Version 별로 상이

Handle Table Entry에는 Object Header를 가리키는 Pointer와 Access Mask 그리고 몇 가지 추가 flag bit 위치

  • Audit on Close
  • Inheritable flag : 자식 프로세스에 상속 가능한 Handle 속성 설정을 위한 flag
  • Lock bit : Handle Entry 수정할 때 사용
  • Protect on close

 

!handle 0 3 <EPROCESS 주소> 를 이용하여 특정 프로세스의 전체 Handle 목록을 확인할 수 있습니다.

!handle 0 3 <EPROCESS>

7: kd> !process 0 1 notepad.exe
PROCESS ffffc503fd5cc080
    SessionId: 1  Cid: 1470    Peb: e17dcdc000  ParentCid: 13f0
    DirBase: 11ba9a000  ObjectTable: ffff990294373cc0  HandleCount: 257.
    Image: notepad.exe
    VadRoot ffffc503fd4d4220 Vads 114 Clone 0 Private 672. Modified 20. Locked 0.
    DeviceMap ffff99028cbb58a0
    Token                             ffff990295e71770
    ElapsedTime                       00:00:06.592
    UserTime                          00:00:00.000
    KernelTime                        00:00:00.000
    QuotaPoolUsage[PagedPool]         289248
    QuotaPoolUsage[NonPagedPool]      16024
    Working Set Sizes (now,min,max)  (4528, 50, 345) (18112KB, 200KB, 1380KB)
    PeakWorkingSetSize                4423
    VirtualSize                       2101430 Mb
    PeakVirtualSize                   2101430 Mb
    PageFaultCount                    4609
    MemoryPriority                    FOREGROUND
    BasePriority                      8
    CommitCharge                      856
 
7: kd> !handle 0 3 ffffc503fd5cc080
 
PROCESS ffffc503fd5cc080
    SessionId: 1  Cid: 1470    Peb: e17dcdc000  ParentCid: 13f0
    DirBase: 11ba9a000  ObjectTable: ffff990294373cc0  HandleCount: 255.
    Image: notepad.exe
 
Handle table at ffff990294373cc0 with 255 entries in use
 
0004: Object: ffffc503fd4a29e0  GrantedAccess: 001f0003 (Protected) (Inherit) Entry: ffff99029215b010
Object: ffffc503fd4a29e0  Type: (ffffc503f809c4e0) Event
    ObjectHeader: ffffc503fd4a29b0 (new version)
        HandleCount: 1  PointerCount: 32764
 
0008: Object: ffffc503fd4a2a60  GrantedAccess: 001f0003 (Protected) (Inherit) Entry: ffff99029215b020
Object: ffffc503fd4a2a60  Type: (ffffc503f809c4e0) Event
    ObjectHeader: ffffc503fd4a2a30 (new version)
        HandleCount: 1  PointerCount: 32765
 
<snip>
 
00c0: Object: ffffc503fd4457e0  GrantedAccess: 00100001 (Protected) (Inherit) Entry: ffff99029215b300
Object: ffffc503fd4457e0  Type: (ffffc503f80f4560) File
    ObjectHeader: ffffc503fd4457b0 (new version)
        HandleCount: 1  PointerCount: 32764

 

Process Explorer를 통해서도 동일한 내용을 확인할 수 있습니다.

Process Explorer에서 Handle을 보기 위해서는 View > Show Lower Pane 옵션을 Check 해줘야 특정 프로세스 선택 시, Lower Pane에 Handle / DLL / Thread를 확인할 수 있습니다.

 

Windbg와 Process Explorer에서 확인한 Handle 하나를 예를 들어, 좀 더 자세히 살펴 보도록 하겠습니다.

  • 00c0는 Handle Number
  • ffff99029215b300는 Handle Table Entry의 주소
  • ffff990294373cc0는 Handle Table 주소
  • ffffc503fd4457e0는 Object 주소

 

Handle Table Entry

Handle table at ffff990294373cc0 with 255 entries in use
 
00c0: Object: ffffc503fd4457e0  GrantedAccess: 00100001 (Protected) (Inherit) Entry: ffff99029215b300
Object: ffffc503fd4457e0  Type: (ffffc503f80f4560) File
    ObjectHeader: ffffc503fd4457b0 (new version)
        HandleCount: 1  PointerCount: 32764
 
7: kd> dt nt!_HANDLE_TABLE_ENTRY ffff99029215b300
   +0x000 VolatileLowValue : 0n-4250275153336795145
   +0x000 LowValue         : 0n-4250275153336795145
   +0x000 InfoTable        : 0xc503fd44`57b0fff7 _HANDLE_TABLE_ENTRY_INFO
   +0x008 HighValue        : 0n1048577
   +0x008 NextFreeHandleEntry : 0x00000000`00100001 _HANDLE_TABLE_ENTRY
   +0x008 LeafHandleValue  : _EXHANDLE
   +0x000 RefCountField    : 0n-4250275153336795145
   +0x000 Unlocked         : 0y1
   +0x000 RefCnt           : 0y0111111111111011 (0x7ffb)
   +0x000 Attributes       : 0y000
   +0x000 ObjectPointerBits : 0y11000101000000111111110101000100010101111011 (0xc503fd4457b)
   +0x008 GrantedAccessBits : 0y0000100000000000000000001 (0x100001)
   +0x008 NoRightsUpgrade  : 0y0
   +0x008 Spare1           : 0y000000 (0)
   +0x00c Spare2           : 0
 
7: kd> !object ffffc503fd4457e0
Object: ffffc503fd4457e0  Type: (ffffc503f80f4560) File
    ObjectHeader: ffffc503fd4457b0 (new version)
    HandleCount: 1  PointerCount: 32763
 
ObjectHeader: ffffc503fd4457b0 + 0x30(size of nt!_OBJECT_HEADER in x64) = Object: ffffc503fd4457e0

 

추가로 Resource Monitor를 이용해서도 동일한 내용을 확인할 수 있습니다.

 

Handle Type

Handle에는 일반 Process Handle과 Kernel Handle로 구분할 수 있습니다.

Process Handle은 개별 Process마다 별도로 존재합니다. 즉, A 프로세스와 B 프로세스에서 확인되는 Handle의 값이 같더라도 서로 다른 Handle 입니다.

따라서, Process Handle은 해당 Process의 Context 내에서만 존재하게 됩니다.

 

Process Handle

7: kd> !process 0 0 lsass.exe
PROCESS ffffc503fa6e9140
    SessionId: 0  Cid: 02d4    Peb: bb7c7e8000  ParentCid: 022c
    DirBase: 40a82d000  ObjectTable: ffff9902900becc0  HandleCount: 1185.
    Image: lsass.exe
 
7: kd> !handle 00d0 3 ffffc503fa6e9140
 
PROCESS ffffc503fa6e9140
    SessionId: 0  Cid: 02d4    Peb: bb7c7e8000  ParentCid: 022c
    DirBase: 40a82d000  ObjectTable: ffff9902900becc0  HandleCount: 1185.
    Image: lsass.exe
 
Handle table at ffff9902900becc0 with 1185 entries in use
 
00d0: Object: ffffc503faeab8e0  GrantedAccess: 001f0003 (Protected) (Inherit) Entry: ffff9902900fb340
Object: ffffc503faeab8e0  Type: (ffffc503f809c4e0) Event
    ObjectHeader: ffffc503faeab8b0 (new version)
        HandleCount: 1  PointerCount: 1
 
7: kd> !process 0 0 notepad.exe
PROCESS ffffc503fd5cc080
    SessionId: 1  Cid: 1470    Peb: e17dcdc000  ParentCid: 13f0
    DirBase: 11ba9a000  ObjectTable: ffff990294373cc0  HandleCount: 254.
    Image: notepad.exe
 
7: kd> !handle 00d0 3 ffffc503fd5cc080
 
PROCESS ffffc503fd5cc080
    SessionId: 1  Cid: 1470    Peb: e17dcdc000  ParentCid: 13f0
    DirBase: 11ba9a000  ObjectTable: ffff990294373cc0  HandleCount: 254.
    Image: notepad.exe
 
Handle table at ffff990294373cc0 with 254 entries in use
 
00d0: Object: ffffc503fd4a2e60  GrantedAccess: 001f0003 (Protected) (Inherit) Entry: ffff99029215b340
Object: ffffc503fd4a2e60  Type: (ffffc503f809c4e0) Event
    ObjectHeader: ffffc503fd4a2e30 (new version)
        HandleCount: 1  PointerCount: 32759

 

일반 Process와 달리 Kernel Component들은 특정 Process Context 에서만 실행되지 않습니다.

만약 한 Process Context에서 생성된 Handle이 있다면, 다른 Process Context에서 실행되던 Kernel Mode Component는 그 Handle을 참조할 수가 없게 됩니다.

이러한 이유 때문에, 모든 Process Context에서 접근 가능한 Handle의 필요성이 생기게 되고, 이로 인해 Windows는 Kernel Handle이라는 것을 제공합니다 

Object Manager는 Kernel Mode Component가 생성 요청한 Handle을 System Process와 연관된 Global Handle Table에 Reference를 위치시키게 됩니다.

 

Kernel Handle Table

7: kd> !process 4 0
Searching for Process with Cid == 4
PROCESS ffffc503f8075600
    SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 001ad000  ObjectTable: ffff99028c604ac0  HandleCount: 2510.
    Image: System
 
7: kd> dt nt!_EPROCESS ffffc503f8075600 ObjectTable
   +0x418 ObjectTable : 0xffff9902`8c604ac0 _HANDLE_TABLE ### <--
 
7: kd> dx -id 0,0,ffffc503f8075600 -r1 ((ntkrnlmp!_HANDLE_TABLE *)0xffff99028c604ac0)
((ntkrnlmp!_HANDLE_TABLE *)0xffff99028c604ac0)                 : 0xffff99028c604ac0 [Type: _HANDLE_TABLE *]
    [+0x000] NextHandleNeedingPool : 0x3000 [Type: unsigned long]
    [+0x004] ExtraInfoPages   : 0 [Type: long]
    [+0x008] TableCode        : 0xffff99028ff53001 [Type: unsigned __int64]
    [+0x010] QuotaProcess     : 0x0 [Type: _EPROCESS *]
    [+0x018] HandleTableList  [Type: _LIST_ENTRY] ### <--
    [+0x028] UniqueProcessId  : 0x4 [Type: unsigned long]
    [+0x02c] Flags            : 0x0 [Type: unsigned long]
    [+0x02c ( 0: 0)] StrictFIFO       : 0x0 [Type: unsigned char]
    [+0x02c ( 1: 1)] EnableHandleExceptions : 0x0 [Type: unsigned char]
    [+0x02c ( 2: 2)] Rundown          : 0x0 [Type: unsigned char]
    [+0x02c ( 3: 3)] Duplicated       : 0x0 [Type: unsigned char]
    [+0x02c ( 4: 4)] RaiseUMExceptionOnInvalidHandleClose : 0x0 [Type: unsigned char]
    [+0x030] HandleContentionEvent [Type: _EX_PUSH_LOCK]
    [+0x038] HandleTableLock  [Type: _EX_PUSH_LOCK]
    [+0x040] FreeLists        [Type: _HANDLE_TABLE_FREE_LIST [1]]
    [+0x040] ActualEntry      [Type: unsigned char [32]]
    [+0x060] DebugInfo        : 0x0 [Type: _HANDLE_TRACE_DEBUG_INFO *]
 
7: kd> x nt!ObpKernelHandleTable
fffff807`38e27020 nt!ObpKernelHandleTable = <no type information>
 
7: kd> ? poi(ObpKernelHandleTable)
Evaluate expression: -113238752605504 = ffff9902`8c604ac0
 
7: kd> dq fffff807`38e27020 L1
fffff807`38e27020  ffff9902`8c604ac0
 
7: kd> dt nt!_HANDLE_TABLE poi(ObpKernelHandleTable)
   +0x000 NextHandleNeedingPool : 0x3000
   +0x004 ExtraInfoPages   : 0n0
   +0x008 TableCode        : 0xffff9902`8ff53001
   +0x010 QuotaProcess     : (null)
   +0x018 HandleTableList  : _LIST_ENTRY [ 0xffff9902`8c60ecd8 - 0xfffff807`3937ba88 ]  ### <--
   +0x028 UniqueProcessId  : 4
   +0x02c Flags            : 0
   +0x02c StrictFIFO       : 0y0
   +0x02c EnableHandleExceptions : 0y0
   +0x02c Rundown          : 0y0
   +0x02c Duplicated       : 0y0
   +0x02c RaiseUMExceptionOnInvalidHandleClose : 0y0
   +0x030 HandleContentionEvent : _EX_PUSH_LOCK
   +0x038 HandleTableLock  : _EX_PUSH_LOCK
   +0x040 FreeLists        : [1] _HANDLE_TABLE_FREE_LIST
   +0x040 ActualEntry      : [32]  ""
   +0x060 DebugInfo        : (null)
 
7: kd> dt nt!_HANDLE_TABLE ffff9902`8c604ac0
   +0x000 NextHandleNeedingPool : 0x3000
   +0x004 ExtraInfoPages   : 0n0
   +0x008 TableCode        : 0xffff9902`8ff53001
   +0x010 QuotaProcess     : (null)
   +0x018 HandleTableList  : _LIST_ENTRY [ 0xffff9902`8c60ecd8 - 0xfffff807`3937ba88 ]  ### <--
   +0x028 UniqueProcessId  : 4
   +0x02c Flags            : 0
   +0x02c StrictFIFO       : 0y0
   +0x02c EnableHandleExceptions : 0y0
   +0x02c Rundown          : 0y0
   +0x02c Duplicated       : 0y0
   +0x02c RaiseUMExceptionOnInvalidHandleClose : 0y0
   +0x030 HandleContentionEvent : _EX_PUSH_LOCK
   +0x038 HandleTableLock  : _EX_PUSH_LOCK
   +0x040 FreeLists        : [1] _HANDLE_TABLE_FREE_LIST
   +0x040 ActualEntry      : [32]  ""
   +0x060 DebugInfo        : (null)
 
7: kd> dt nt!_HANDLE_TABLE 0xffff9902`8c60ecd8-0x18
   +0x000 NextHandleNeedingPool : 0x400
   +0x004 ExtraInfoPages   : 0n0
   +0x008 TableCode        : 0xffff9902`8c64d000
   +0x010 QuotaProcess     : 0xffffc503`f80c9080 _EPROCESS
   +0x018 HandleTableList  : _LIST_ENTRY [ 0xffff9902`8cd0dd18 - 0xffff9902`8c604ad8 ]
   +0x028 UniqueProcessId  : 0x88
   +0x02c Flags            : 0x10
   +0x02c StrictFIFO       : 0y0
   +0x02c EnableHandleExceptions : 0y0
   +0x02c Rundown          : 0y0
   +0x02c Duplicated       : 0y0
   +0x02c RaiseUMExceptionOnInvalidHandleClose : 0y1
   +0x030 HandleContentionEvent : _EX_PUSH_LOCK
   +0x038 HandleTableLock  : _EX_PUSH_LOCK
   +0x040 FreeLists        : [1] _HANDLE_TABLE_FREE_LIST
   +0x040 ActualEntry      : [32]  ""
   +0x060 DebugInfo        : (null)
 
7: kd> dt nt!_EPROCESS 0xffffc503`f80c9080 ImageFileName
   +0x450 ImageFileName : [15]  "Registry"

 

System 프로세스의 Handle Table에 있는 Handle Table Entry를 이용하여, 관련된 Object의 주소를 획득할 수 있습니다.

 

Handle Table Entry

7: kd> !process 4 0
Searching for Process with Cid == 4
PROCESS ffffc503f8075600
    SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 001ad000  ObjectTable: ffff99028c604ac0  HandleCount: 2510.
    Image: System
 
7: kd> !handle 0 3 ffffc503f8075600
 
PROCESS ffffc503f8075600
    SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 001ad000  ObjectTable: ffff99028c604ac0  HandleCount: 2510.
    Image: System
 
Kernel handle table at ffff99028c604ac0 with 2510 entries in use
 
0004: Object: ffffc503f8075600  GrantedAccess: 001fffff (Protected) (Audit) Entry: ffff99028c625010  ### <--
Object: ffffc503f8075600  Type: (ffffc503f8093220) Process
    ObjectHeader: ffffc503f80755d0 (new version)
        HandleCount: 5  PointerCount: 180602
 
0008: Object: ffffc503f81c1140  GrantedAccess: 001fffff (Protected) Entry: ffff99028c625020  ### <--
Object: ffffc503f81c1140  Type: (ffffc503f809dda0) Thread
    ObjectHeader: ffffc503f81c1110 (new version)
        HandleCount: 1  PointerCount: 2
 
000c: Object: ffffc503fa668dc0  GrantedAccess: 0012019f (Protected) Entry: ffff99028c625030  ### <--
Object: ffffc503fa668dc0  Type: (ffffc503f80f4560) File
    ObjectHeader: ffffc503fa668d90 (new version)
        HandleCount: 1  PointerCount: 32638
        Directory Object: 00000000  Name: \Windows\bootstat.dat {HarddiskVolume4}
 
<snip>
 
7: kd> dp poi(0xffff9902`8ff53001&0xfffffffffffffffc)  ### <-- 0xc == 1100
ffff9902`8c625000  00000000`00000000 00000000`00000000
ffff9902`8c625010  c503f807`55d0fd89 00000000`001fffff  ### <--
ffff9902`8c625020  c503f81c`11100001 00000000`001fffff  ### <--
ffff9902`8c625030  c503fa66`8d90fefb 00000000`0012019f  ### <--
ffff9902`8c625040  c503f809`1070fe85 00000000`001f0001
ffff9902`8c625050  99028c60`89900001 00000000`000f000f
ffff9902`8c625060  99028c63`1510fbf3 00000000`000f000f
ffff9902`8c625070  c503f809`9e700001 00000000`001f0003
 
7: kd> dt _HANDLE_TABLE_ENTRY ffff9902`8c625010
nt!_HANDLE_TABLE_ENTRY
   +0x000 VolatileLowValue : 0n-4250280912919396983
   +0x000 LowValue         : 0n-4250280912919396983
   +0x000 InfoTable        : 0xc503f807`55d0fd89 _HANDLE_TABLE_ENTRY_INFO  ### <--
   +0x008 HighValue        : 0n2097151
   +0x008 NextFreeHandleEntry : 0x00000000`001fffff _HANDLE_TABLE_ENTRY
   +0x008 LeafHandleValue  : _EXHANDLE
   +0x000 RefCountField    : 0n-4250280912919396983
   +0x000 Unlocked         : 0y1
   +0x000 RefCnt           : 0y0111111011000100 (0x7ec4)
   +0x000 Attributes       : 0y000
   +0x000 ObjectPointerBits : 0y11000101000000111111100000000111010101011101 (0xc503f80755d)
   +0x008 GrantedAccessBits : 0y0000111111111111111111111 (0x1fffff)
   +0x008 NoRightsUpgrade  : 0y0
   +0x008 Spare1           : 0y000000 (0)
   +0x00c Spare2           : 0
 
7: kd> ? (0xc503f807`55d0fd89>>>10)&fffffffffffffff0
Evaluate expression: -64854139906608 = ffffc503`f80755d0  ### <--
 
7: kd> dt _OBJECT_HEADER ffffc503`f80755d0
nt!_OBJECT_HEADER
   +0x000 PointerCount     : 0n180602
   +0x008 HandleCount      : 0n5
   +0x008 NextToFree       : 0x00000000`00000005 Void
   +0x010 Lock             : _EX_PUSH_LOCK
   +0x018 TypeIndex        : 0x66 'f'
   +0x019 TraceFlags       : 0 ''
   +0x019 DbgRefTrace      : 0y0
   +0x019 DbgTracePermanent : 0y0
   +0x01a InfoMask         : 0x80 ''
   +0x01b Flags            : 0x2 ''
   +0x01b NewObject        : 0y0
   +0x01b KernelObject     : 0y1
   +0x01b KernelOnlyAccess : 0y0
   +0x01b ExclusiveObject  : 0y0
   +0x01b PermanentObject  : 0y0
   +0x01b DefaultSecurityQuota : 0y0
   +0x01b SingleHandleEntry : 0y0
   +0x01b DeletedInline    : 0y0
   +0x01c Reserved         : 0x1aff
   +0x020 ObjectCreateInfo : 0xfffff807`38e4c7c0 _OBJECT_CREATE_INFORMATION
   +0x020 QuotaBlockCharged : 0xfffff807`38e4c7c0 Void
   +0x028 SecurityDescriptor : 0xffff9902`8c60706f Void
   +0x030 Body             : _QUAD
 
7: kd> !object ffffc503`f80755d0+0x30  ### <--
Object: ffffc503f8075600  Type: (ffffc503f8093220) Process
    ObjectHeader: ffffc503f80755d0 (new version)
    HandleCount: 5  PointerCount: 180602
 
7: kd> dt nt!_EPROCESS ffffc503f8075600 ImageFileName
   +0x450 ImageFileName : [15]  "System"
 
7: kd> dt _HANDLE_TABLE_ENTRY ffff9902`8c625030  ### <--
nt!_HANDLE_TABLE_ENTRY
   +0x000 VolatileLowValue : 0n-4250278304938918149
   +0x000 LowValue         : 0n-4250278304938918149
   +0x000 InfoTable        : 0xc503fa66`8d90fefb _HANDLE_TABLE_ENTRY_INFO
   +0x008 HighValue        : 0n1180063
   +0x008 NextFreeHandleEntry : 0x00000000`0012019f _HANDLE_TABLE_ENTRY
   +0x008 LeafHandleValue  : _EXHANDLE
   +0x000 RefCountField    : 0n-4250278304938918149
   +0x000 Unlocked         : 0y1
   +0x000 RefCnt           : 0y0111111101111101 (0x7f7d)
   +0x000 Attributes       : 0y000
   +0x000 ObjectPointerBits : 0y11000101000000111111101001100110100011011001 (0xc503fa668d9)
   +0x008 GrantedAccessBits : 0y0000100100000000110011111 (0x12019f)
   +0x008 NoRightsUpgrade  : 0y0
   +0x008 Spare1           : 0y000000 (0)
   +0x00c Spare2           : 0
 
7: kd> ? (0xc503fa66`8d90fefb>>>10)&fffffffffffffff0
Evaluate expression: -64854100111984 = ffffc503`fa668d90
 
7: kd> dt _OBJECT_HEADER ffffc503`fa668d90
nt!_OBJECT_HEADER
   +0x000 PointerCount     : 0n32638
   +0x008 HandleCount      : 0n1
   +0x008 NextToFree       : 0x00000000`00000001 Void
   +0x010 Lock             : _EX_PUSH_LOCK
   +0x018 TypeIndex        : 0x9d ''
   +0x019 TraceFlags       : 0 ''
   +0x019 DbgRefTrace      : 0y0
   +0x019 DbgTracePermanent : 0y0
   +0x01a InfoMask         : 0x4c 'L'
   +0x01b Flags            : 0x42 'B'
   +0x01b NewObject        : 0y0
   +0x01b KernelObject     : 0y1
   +0x01b KernelOnlyAccess : 0y0
   +0x01b ExclusiveObject  : 0y0
   +0x01b PermanentObject  : 0y0
   +0x01b DefaultSecurityQuota : 0y0
   +0x01b SingleHandleEntry : 0y1
   +0x01b DeletedInline    : 0y0
   +0x01c Reserved         : 0x2b4d85
   +0x020 ObjectCreateInfo : 0x00000000`00000001 _OBJECT_CREATE_INFORMATION
   +0x020 QuotaBlockCharged : 0x00000000`00000001 Void
   +0x028 SecurityDescriptor : (null)
   +0x030 Body             : _QUAD
 
7: kd> !object ffffc503`fa668d90+0x30
Object: ffffc503fa668dc0  Type: (ffffc503f80f4560) File
    ObjectHeader: ffffc503fa668d90 (new version)
    HandleCount: 1  PointerCount: 32638
    Directory Object: 00000000  Name: \Windows\bootstat.dat {HarddiskVolume4}
 
7: kd> dt nt!_FILE_OBJECT ffffc503fa668dc0
   +0x000 Type             : 0n5
   +0x002 Size             : 0n216
   +0x008 DeviceObject     : 0xffffc503`f8c33b70 _DEVICE_OBJECT
   +0x010 Vpb              : 0xffffc503`f8c9a220 _VPB
   +0x018 FsContext        : 0xffff9902`8cc81b80 Void
   +0x020 FsContext2       : 0xffff9902`8ccd3640 Void
   +0x028 SectionObjectPointer : 0xffffc503`f8e86c08 _SECTION_OBJECT_POINTERS
   +0x030 PrivateCacheMap  : 0xffffc503`f8e54c98 Void
   +0x038 FinalStatus      : 0n0
   +0x040 RelatedFileObject : (null)
   +0x048 LockOperation    : 0 ''
   +0x049 DeletePending    : 0 ''
   +0x04a ReadAccess       : 0x1 ''
   +0x04b WriteAccess      : 0x1 ''
   +0x04c DeleteAccess     : 0 ''
   +0x04d SharedRead       : 0x1 ''
   +0x04e SharedWrite      : 0 ''
   +0x04f SharedDelete     : 0 ''
   +0x050 Flags            : 0x40042
   +0x058 FileName         : _UNICODE_STRING "\Windows\bootstat.dat"
   +0x068 CurrentByteOffset : _LARGE_INTEGER 0x33
   +0x070 Waiters          : 0
   +0x074 Busy             : 0
   +0x078 LastLock         : (null)
   +0x080 Lock             : _KEVENT
   +0x098 Event            : _KEVENT
   +0x0b0 CompletionContext : (null)
   +0x0b8 IrpListLock      : 0
   +0x0c0 IrpList          : _LIST_ENTRY [ 0xffffc503`fa668e80 - 0xffffc503`fa668e80 ]
   +0x0d0 FileObjectExtension : (null)
 
7: kd> !fileobj ffffc503fa668dc0
 
\Windows\bootstat.dat
 
Device Object: 0xffffc503f8c33b70   \Driver\volmgr
Vpb: 0xffffc503f8c9a220
Event signalled
Access: Read Write SharedRead
 
Flags:  0x40042
    Synchronous IO
    Cache Supported
    Handle Created
 
FsContext: 0xffff99028cc81b80   FsContext2: 0xffff99028ccd3640
Private Cache Map: 0xffffc503f8e54c98
CurrentByteOffset: 33
Cache Data:
  Section Object Pointers: ffffc503f8e86c08
  Shared Cache Map: ffffc503f8e54b20         File Offset: 33 in VACB number 0
  Vacb: ffffc503f825d180
  Your data is at: ffffb30269780033

 

Object Retention

Object Manager는 Reference Counting 이라는 개념을 이용하여, Object를 얼마나 많은 Client가 사용하고 있는지를 관리하여, 그 값이 0이 되었을 때 Object Manager가 Object를 정리할 수 있게 됩니다.

이 값은 Object Header에 PointerCount와 HandleCount field로 제공됩니다.

Object에 대한 접근 방법은 두 가지가 있는데, 하나는 Object의 Pointer(Memory Address)를 이용하는 방법과 Object의 Handle을 이용하는 방법이 있습니다.

첫 번째 방법을 PointerCount로 관리하고 두 번째를 HandleCount로 관리합니다.

또한, Object에 대한 모든 Reference는(방법에 상관없이) Object Manager가 Pointer Reference로 관리하기 때문에 PointerCount 값은 아래와 같이 계산될 수 있습니다.

Pointer Count = Handle Count + Actual number of Object References by Pointers

따라서 Handle Count가 0이 되었지만 Kernel Mode에서 해당 Object를 참조하고 있다면 Pointer Count는 0이 되지 않는 경우가 발생할 수 있습니다.

7: kd> dt nt!_OBJECT_HEADER
   +0x000 PointerCount     : Int8B   ### <--
   +0x008 HandleCount      : Int8B   ### <--
   +0x008 NextToFree       : Ptr64 Void
   +0x010 Lock             : _EX_PUSH_LOCK
   +0x018 TypeIndex        : UChar
   +0x019 TraceFlags       : UChar
   +0x019 DbgRefTrace      : Pos 0, 1 Bit
   +0x019 DbgTracePermanent : Pos 1, 1 Bit
   +0x01a InfoMask         : UChar
   +0x01b Flags            : UChar
   +0x01b NewObject        : Pos 0, 1 Bit
   +0x01b KernelObject     : Pos 1, 1 Bit
   +0x01b KernelOnlyAccess : Pos 2, 1 Bit
   +0x01b ExclusiveObject  : Pos 3, 1 Bit
   +0x01b PermanentObject  : Pos 4, 1 Bit
   +0x01b DefaultSecurityQuota : Pos 5, 1 Bit
   +0x01b SingleHandleEntry : Pos 6, 1 Bit
   +0x01b DeletedInline    : Pos 7, 1 Bit
   +0x01c Reserved         : Uint4B
   +0x020 ObjectCreateInfo : Ptr64 _OBJECT_CREATE_INFORMATION
   +0x020 QuotaBlockCharged : Ptr64 Void
   +0x028 SecurityDescriptor : Ptr64 Void
   +0x030 Body             : _QUAD
 
kd> !object 8b407c30
Object: 8b407c30  Type: (87e8a0a8) Directory
    ObjectHeader: 8b407c18 (old version)
    HandleCount: 0  PointerCount: 31   ### <--
    Directory Object: 8b407928  Name: ObjectTypes

 

 

Handle Tracing

이러한 Handle을 Windbg를 통해 Open/Close 과정을 Tracing 할 수 있습니다.

Windbg > File > Attach to a Process 를 선택한 후, 내가 Tracing 하고자 하는 프로세스를 선택합니다. 아래 예제에서는 테스트로 notepad.exe를 선택하였습니다.

Windbg에서 제공하는 "!htrace" 를 통해서 Handle이 Open되고 Close 되는 과정을 살펴볼 수 있습니다.

 

!htrace

0:030> .sympath c:\sym;srv*c:\sym\websym*https://msdl.microsoft.com/download/symbols
Symbol search path is: c:\sym;srv*c:\sym\websym*https://msdl.microsoft.com/download/symbols
Expanded Symbol search path is: c:\sym;srv*c:\sym\websym*https://msdl.microsoft.com/download/symbols
 
************* Path validation summary **************
Response                         Time (ms)     Location
OK                                             c:\sym
Deferred                                       srv*c:\sym\websym*https://msdl.microsoft.com/download/symbols
 
0:030> !htrace -h
!htrace [handle [max_traces]]
!htrace -enable [max_traces]
!htrace -disable
!htrace -snapshot
!htrace -diff
 
0:030> !htrace -enable   ### <--
Handle tracing enabled.
Handle tracing information snapshot successfully taken.
 
0:030> g   ### <--
(3fb0.996c): Break instruction exception - code 80000003 (first chance)
ntdll!DbgBreakPoint:
00007ffa`f8f27790 cc              int     3
 
0:031> !htrace   ### <--
--------------------------------------
Handle = 0x0000000000002180 - OPEN   ### <--
Thread ID = 0x000000000000b430, Process ID = 0x0000000000003fb0
 
0x00007ffaf64c1534: win32u!NtUserPostMessage+0x0000000000000014
0x00007ffaf7917164: USER32!PostMessageW+0x0000000000000054
0x00007ffaf8b4dfbf: combase!CComApartment::ClassicSTAPostMessage+0x00000000000000cb
0x00007ffaf8b4dd1f: combase!OXIDEntry::PostCall+0x0000000000000167
0x00007ffaf8b1b7c0: combase!ThreadInvokeWorker+0x0000000000001100
0x00007ffaf8b16681: combase!ThreadInvoke+0x0000000000000161
0x00007ffaf88169e2: RPCRT4!DispatchToStubInCNoAvrf+0x0000000000000022
--------------------------------------
Handle = 0x0000000000002174 - OPEN   ### <--
Thread ID = 0x000000000000b430, Process ID = 0x0000000000003fb0
 
0x00007ffaf64c1534: win32u!NtUserPostMessage+0x0000000000000014
0x00007ffaf7917164: USER32!PostMessageW+0x0000000000000054
0x00007ffaf8b4dfbf: combase!CComApartment::ClassicSTAPostMessage+0x00000000000000cb
0x00007ffaf8b4dd1f: combase!OXIDEntry::PostCall+0x0000000000000167
--------------------------------------
Handle = 0x000000000000218c - OPEN   ### <--
Thread ID = 0x000000000000b430, Process ID = 0x0000000000003fb0
 
0x00007ffaf8f24304: ntdll!NtDuplicateObject+0x0000000000000014
0x00007ffaf66ffa5c: KERNELBASE!DuplicateHandle+0x000000000000004c
0x00007ffaf87d1b13: RPCRT4!THREAD::THREAD+0x0000000000000087
0x00007ffaf87e75e4: RPCRT4!LrpcIoComplete+0x0000000000000164
0x00007ffaf8ea2160: ntdll!TppAlpcpExecuteCallback+0x0000000000000280
0x00007ffaf8e96e48: ntdll!TppWorkerThread+0x0000000000000448
0x00007ffaf77e55a0: KERNEL32!BaseThreadInitThunk+0x0000000000000010
0x00007ffaf8e8485b: ntdll!RtlUserThreadStart+0x000000000000002b
--------------------------------------
Handle = 0x0000000000001638 - OPEN   ### <--
Thread ID = 0x000000000000b430, Process ID = 0x0000000000003fb0
 
0x00007ffaf8f24484: ntdll!NtCreateEvent+0x0000000000000014
0x00007ffaf66d3e52: KERNELBASE!CreateEventW+0x0000000000000092
0x00007ffaf87d1c9d: RPCRT4!EVENT::EVENT+0x000000000000002d
0x00007ffaf87d1ab6: RPCRT4!THREAD::THREAD+0x000000000000002a
0x00007ffaf87e75e4: RPCRT4!LrpcIoComplete+0x0000000000000164
0x00007ffaf8ea2160: ntdll!TppAlpcpExecuteCallback+0x0000000000000280
0x00007ffaf8e96e48: ntdll!TppWorkerThread+0x0000000000000448
0x00007ffaf77e55a0: KERNEL32!BaseThreadInitThunk+0x0000000000000010
0x00007ffaf8e8485b: ntdll!RtlUserThreadStart+0x000000000000002b
--------------------------------------
Handle = 0x0000000000001638 - CLOSE   ### <--
Thread ID = 0x00000000000029d0, Process ID = 0x0000000000003fb0
 
0x00007ffaf8f23d64: ntdll!NtClose+0x0000000000000014
0x00007ffaf87d872a: RPCRT4!LRPC_CASSOCIATION::~LRPC_CASSOCIATION+0x0000000000000072
0x00007ffaf87d8694: RPCRT4!LRPC_CASSOCIATION::`vector deleting destructor'+0x0000000000000014
0x00007ffaf87c6e69: RPCRT4!LRPC_CASSOCIATION::RemoveAssociationDictionaryReference+0x0000000000000051
0x00007ffaf87c6da0: RPCRT4!LRPC_CASSOCIATION::LrpcDeleteLingeringAssociations+0x00000000000000f0
0x00007ffaf87c6aee: RPCRT4!PerformGarbageCollection+0x000000000000009e
0x00007ffaf8ea03e3: ntdll!TppTimerpExecuteCallback+0x00000000000000b3
0x00007ffaf8e97086: ntdll!TppWorkerThread+0x0000000000000686
0x00007ffaf77e55a0: KERNEL32!BaseThreadInitThunk+0x0000000000000010
0x00007ffaf8e8485b: ntdll!RtlUserThreadStart+0x000000000000002b
 
--------------------------------------
Parsed 0x5 stack traces.
Dumped 0x5 stack traces.
 
0:031> !htrace -diff   ### <--
Handle tracing information snapshot successfully taken.
0x5 new stack traces since the previous snapshot.
Ignoring handles that were already closed...
Outstanding handles opened since the previous snapshot:
--------------------------------------
Handle = 0x0000000000002180 - OPEN   ### <--
Thread ID = 0x000000000000b430, Process ID = 0x0000000000003fb0
 
0x00007ffaf64c1534: win32u!NtUserPostMessage+0x0000000000000014
0x00007ffaf7917164: USER32!PostMessageW+0x0000000000000054
0x00007ffaf8b4dfbf: combase!CComApartment::ClassicSTAPostMessage+0x00000000000000cb
0x00007ffaf8b4dd1f: combase!OXIDEntry::PostCall+0x0000000000000167
0x00007ffaf8b1b7c0: combase!ThreadInvokeWorker+0x0000000000001100
0x00007ffaf8b16681: combase!ThreadInvoke+0x0000000000000161
0x00007ffaf88169e2: RPCRT4!DispatchToStubInCNoAvrf+0x0000000000000022
--------------------------------------
Handle = 0x0000000000002174 - OPEN   ### <--
Thread ID = 0x000000000000b430, Process ID = 0x0000000000003fb0
 
0x00007ffaf64c1534: win32u!NtUserPostMessage+0x0000000000000014
0x00007ffaf7917164: USER32!PostMessageW+0x0000000000000054
0x00007ffaf8b4dfbf: combase!CComApartment::ClassicSTAPostMessage+0x00000000000000cb
0x00007ffaf8b4dd1f: combase!OXIDEntry::PostCall+0x0000000000000167
--------------------------------------
Handle = 0x000000000000218c - OPEN   ### <--
Thread ID = 0x000000000000b430, Process ID = 0x0000000000003fb0
 
0x00007ffaf8f24304: ntdll!NtDuplicateObject+0x0000000000000014
0x00007ffaf66ffa5c: KERNELBASE!DuplicateHandle+0x000000000000004c
0x00007ffaf87d1b13: RPCRT4!THREAD::THREAD+0x0000000000000087
0x00007ffaf87e75e4: RPCRT4!LrpcIoComplete+0x0000000000000164
0x00007ffaf8ea2160: ntdll!TppAlpcpExecuteCallback+0x0000000000000280
0x00007ffaf8e96e48: ntdll!TppWorkerThread+0x0000000000000448
0x00007ffaf77e55a0: KERNEL32!BaseThreadInitThunk+0x0000000000000010
0x00007ffaf8e8485b: ntdll!RtlUserThreadStart+0x000000000000002b
--------------------------------------
Handle = 0x0000000000001638 - OPEN   ### <--
Thread ID = 0x000000000000b430, Process ID = 0x0000000000003fb0
 
0x00007ffaf8f24484: ntdll!NtCreateEvent+0x0000000000000014
0x00007ffaf66d3e52: KERNELBASE!CreateEventW+0x0000000000000092
0x00007ffaf87d1c9d: RPCRT4!EVENT::EVENT+0x000000000000002d
0x00007ffaf87d1ab6: RPCRT4!THREAD::THREAD+0x000000000000002a
0x00007ffaf87e75e4: RPCRT4!LrpcIoComplete+0x0000000000000164
0x00007ffaf8ea2160: ntdll!TppAlpcpExecuteCallback+0x0000000000000280
0x00007ffaf8e96e48: ntdll!TppWorkerThread+0x0000000000000448
0x00007ffaf77e55a0: KERNEL32!BaseThreadInitThunk+0x0000000000000010
0x00007ffaf8e8485b: ntdll!RtlUserThreadStart+0x000000000000002b
--------------------------------------
Displayed 0x4 stack traces for outstanding handles opened since the previous snapshot.

 

Object Tracking

위에서 살펴본 Handle Tracing을 통해 Handle의 Open/Close 과정을 살펴볼 수 있지만, Obejct의 Pointer Reference는 Tracking 할 수 없습니다.

만약 gflags.exe 도구를 이용하여, Object Tracing을 enable 하면 Dump에서 "!obtrace" 명령어로 Object Tracing 정보를 추출할 수 있습니다.

문제가 되는 프로세스가 실행되는 시스템에서 C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\gflags.exe를 실행하고 설정을 합니다.

아래 예제는 notepad.exe 프로세스에 대해서 Event Object를 Tracing 하기 위한 설정이며, 설정 후 재부팅을 진행합니다.

 

재부팅 한 후에 notepad.exe 를 실행하고 Debugger에서 Break로 멈춘 후 "!obtrace" 명령을 이용하면 Reference/Dereference 과정을 살펴볼 수 있습니다.

 

!obtrace

1: kd> !process 0 0 notepad.exe
PROCESS ffffbd862e490080
    SessionId: 2  Cid: 17d4    Peb: fc1b228000  ParentCid: 1298
    DirBase: 13f7e9000  ObjectTable: ffff8002d81cbb40  HandleCount: 507.
    Image: notepad.exe
 
1: kd> !handle 0 f ffffbd862e490080
 
PROCESS ffffbd862e490080
    SessionId: 2  Cid: 17d4    Peb: fc1b228000  ParentCid: 1298
    DirBase: 13f7e9000  ObjectTable: ffff8002d81cbb40  HandleCount: 507.
    Image: notepad.exe
 
Handle table at ffff8002d81cbb40 with 507 entries in use
 
0004: Object: ffffbd862e42afe0  GrantedAccess: 001f0003 (Protected) (Inherit) Entry: ffff8002d85ff010
Object: ffffbd862e42afe0  Type: (ffffbd86294ff820) Event   ### <--
    ObjectHeader: ffffbd862e42afb0 (new version)
        HandleCount: 1  PointerCount: 32768
 
<snip>
 
1: kd> !obtrace ffffbd862e42afe0   ### <--
Object: ffffbd862e42afe0
 Image: notepad.exe
Sequence   (+/-)   Tag   Stack
--------   -----   ----  ---------------------------------------------------
       1    +1     Dflt      nt!ObCreateObjectEx+15421a
                             nt!NtCreateEvent+98
                             nt!KiSystemServiceCopyEnd+25
 
       2    +1     Dflt      nt!ObReferenceObjectExWithTag+1ac262
                             nt!ObpCreateHandle+88d
                             nt!ObInsertObjectEx+109
                             nt!NtCreateEvent+d9
                             nt!KiSystemServiceCopyEnd+25
 
       3    -1     Dflt      nt!ObfDereferenceObject+1322ab
                             nt!ObInsertObjectEx+149
                             nt!NtCreateEvent+d9
                             nt!KiSystemServiceCopyEnd+25
 
      5c    +1     Dflt      nt!ObpReferenceObjectByHandleWithTag+14ecf7
                             nt!ObReferenceObjectByHandle+2e
                             nt!NtSetEvent+77
                             nt!KiSystemServiceCopyEnd+25
 
      5d    -1     Dflt      nt!ObfDereferenceObject+1322ab
                             nt!NtSetEvent+9f
                             nt!KiSystemServiceCopyEnd+25
 
--------   -----   ---------------------------------------------------
References: 3, Dereferences 2
 
Tag: Dflt References: 3     Dereferences: 2     Over reference by:  1

 

Zombie Process와 Thread

Handle Count도 0으로 표시되고, Object Table의 주소도 없고, Process 하위에 Thread도 없는 상황에서 Process Object가 남아 있는 경우가 있습니다.

이러한 경우에 해당 Process를 Zombie Process라고 합니다.

아래는 Zombie Process의 예제입니다. 이러한 경우에는 남아있는 Process Object의 Handle을 누가 소유하고 있는지 확인해야 합니다.

 

Zombie Process

kd> !process 0 7 notepad.exe
PROCESS 89e34030  SessionId: 2  Cid: 00b4    Peb: 7ffdb000  ParentCid: 1244
    DirBase: 5e7da540  ObjectTable: 00000000  HandleCount:   0.   ### <--
    Image: notepad.exe
    VadRoot 00000000 Vads 0 Clone 0 Private 1. Modified 2. Locked 0.
    DeviceMap 9f72f6a8
    Token                             9fce4028
    ElapsedTime                       00:00:10.525
    UserTime                          00:00:00.000
    KernelTime                        00:00:00.030
    QuotaPoolUsage[PagedPool]         0
    QuotaPoolUsage[NonPagedPool]      0
    Working Set Sizes (now,min,max)  (6, 50, 345) (24KB, 200KB, 1380KB)
    PeakWorkingSetSize                872
    VirtualSize                       33 Mb
    PeakVirtualSize                   46 Mb
    PageFaultCount                    912
    MemoryPriority                    BACKGROUND
    BasePriority                      8
    CommitCharge                      0
 
No active threads   ### <--
 
kd> !object 89e34030
Object: 89e34030  Type: (8499d890) Process
    ObjectHeader: 89e34018 (new version)
    HandleCount: 1  PointerCount: 9   ### <--
 
1: kd> !object ffffbd862e490080
Object: ffffbd862e490080  Type: (ffffbd86294ed900) Process   ### <--
    ObjectHeader: ffffbd862e490050 (new version)
    HandleCount: 7  PointerCount: 228192
 
1: kd> !findhandle ffffbd862e490080
                                                               
                   [ffffbd8629484200 System]
  25b4: Entry ffff8002d81526d0 Granted Access 102a (Protected) (Audit)
  25c0: Entry ffff8002d8152700 Granted Access 1fffff (Protected) (Audit)
  25c4: Entry ffff8002d8152710 Granted Access 102a (Protected) (Audit)
                                                               
                   [ffffbd862b866080 lsass.exe]
  142c: Entry ffff8002d85120b0 Granted Access 1478 (Protected) (Audit)
                                                               
                   [ffffbd862ca04080 svchost.exe]
   fd4: Entry ffff8002d7c8cf50 Granted Access 100000 (Protected) (Audit)
                                                               
                   [ffffbd862cc1e240 svchost.exe]
   2bc: Entry ffff8002d6733af0 Granted Access 1478 (Protected) (Audit)
                                                               
                   [ffffbd862ccdc080 csrss.exe]
   2fc: Entry ffff8002d69f4bf0 Granted Access 1fffff (Protected) (Audit)   ### <--
 
1: kd> !handle 0 3 ffffbd862ccdc080 Process
 
Searching for handles of type Process
 
PROCESS ffffbd862ccdc080
    SessionId: 2  Cid: 0cfc    Peb: dfdee62000  ParentCid: 0d88
    DirBase: 10f7fe000  ObjectTable: ffff8002d7359b40  HandleCount: 295.
    Image: csrss.exe
 
Handle table at ffff8002d7359b40 with 295 entries in use
 
02fc: Object: ffffbd862e490080  GrantedAccess: 001fffff (Protected) (Audit) Entry: ffff8002d69f4bf0   ### <--
Object: ffffbd862e490080  Type: (ffffbd86294ed900) Process
    ObjectHeader: ffffbd862e490050 (new version)
        HandleCount: 7  PointerCount: 228192
 
1: kd> dt nt!_EPROCESS ffffbd862e490080 ImageFileName
   +0x450 ImageFileName : [15]  "notepad.exe"   ### <--