Search code examples
cwindowskernel-moduledevice-driver

Which ETHREAD data member provides starting address (start of code) of the current executing thread?


Can someone tell me which data member of the ETHREAD structure that provides the starting address of the current executing thread ? Would it be the StartAddress data member as seen in the following dump ? I am looking for beginning address of the code for a given ETHREAD data object. I'm not certain that the _ETHREAD contains this detail.

    lkd> dt _ETHREAD
    nt!_ETHREAD
   +0x000 Tcb              : _KTHREAD
   +0x5d0 CreateTime       : _LARGE_INTEGER
   +0x5d8 ExitTime         : _LARGE_INTEGER
   +0x5d8 KeyedWaitChain   : _LIST_ENTRY
   +0x5e8 ChargeOnlySession : Ptr64 Void
   +0x5f0 PostBlockList    : _LIST_ENTRY
   +0x5f0 ForwardLinkShadow : Ptr64 Void
   +0x5f8 **StartAddress**     : Ptr64 Void
   +0x600 TerminationPort  : Ptr64 _TERMINATION_PORT
   +0x600 ReaperLink       : Ptr64 _ETHREAD
   ....

   +0x6bd SuppressSymbolLoad : Pos 3, 1 Bit
   +0x6bd Prefetching      : Pos 4, 1 Bit
   +0x6bd OwnsVadExclusive : Pos 5, 1 Bit
   +0x6bd OwnsChangeControlAreaExclusive : Pos 6, 1 Bit
   +0x6bd OwnsChangeControlAreaShared : Pos 7, 1 Bit
   +0x6be OwnsPagedPoolWorkingSetExclusive : Pos 0, 1 Bit
   +0x6be OwnsPagedPoolWorkingSetShared : Pos 1, 1 Bit
   +0x6be OwnsSystemPtesWorkingSetExclusive : Pos 2, 1 Bit
   +0x6be OwnsSystemPtesWorkingSetShared : Pos 3, 1 Bit
   +0x6be TrimTrigger      : Pos 4, 2 Bits
   +0x6be Spare2           : Pos 6, 2 Bits
   +0x6bf SystemPagePriorityActive : Pos 0, 1 Bit
   +0x6bf SystemPagePriority : Pos 1, 3 Bits
   +0x6bf Spare3           : Pos 4, 4 Bits
   +0x6c0 CacheManagerActive : UChar
   +0x6c1 DisablePageFaultClustering : UChar
   +0x6c2 ActiveFaultCount : UChar
   +0x6c3 LockOrderState   : UChar
   +0x6c8 AlpcMessageId    : Uint8B
   +0x6d0 AlpcMessage      : Ptr64 Void
   +0x6d0 AlpcReceiveAttributeSet : Uint4B
   +0x6d8 ExitStatus       : Int4B
   +0x6e0 AlpcWaitListEntry : _LIST_ENTRY
   +0x6f0 CacheManagerCount : Uint4B
   +0x6f4 IoBoostCount     : Uint4B
   +0x6f8 BoostList        : _LIST_ENTRY
   +0x708 DeboostList      : _LIST_ENTRY
   +0x718 BoostListLock    : Uint8B
   +0x720 IrpListLock      : Uint8B
   +0x728 ReservedForSynchTracking : Ptr64 Void
   +0x730 CmCallbackListHead : _SINGLE_LIST_ENTRY
   +0x738 ActivityId       : Ptr64 _GUID
   +0x740 SeLearningModeListHead : _SINGLE_LIST_ENTRY
   +0x748 VerifierContext  : Ptr64 Void
   +0x750 KernelStackReference : Uint4B
   +0x758 AdjustedClientToken : Ptr64 Void
   +0x760 UserFsBase       : Uint4B
   +0x768 UserGsBase       : Uint8B
   +0x770 PicoContext      : Ptr64 Void

Solution

  • From a debugging standpoint, yes the initial function is stored in StartAddress and the more useful "unique" user-mode address is in Win32StartAddress.

    There are however two things to keep in mind:

    1. StartAddress is in a union with another member and might not be valid after the tread has executed some of its code.
    2. StartAddress is part of a struct that changes a lot between versions and its offset is not stable so you should not be using it in a driver, only while debugging.

    A real product should use something like PsSetCreateThreadNotifyRoutine, not reading from unstable system structs.