逆向工程 Windows 内核例程

逆向工程 视窗 部件 x86
2021-07-07 00:47:09

问题

我正在尝试使用 kd 在 Windows 7 x86 (Home Basic) VM 上对一些 Windows 内核例程进行逆向工程。我已经通过反汇编来反转 KeInitializeDpc。问题KeReadyThread是我不知道第三个第四个 mov指向哪里,因为该函数似乎没有任何参数或任何可以帮助我的东西。

这是代码

lkd> uf KeReadyThread  
nt!KeReadyThread:
829080f6 8bff            mov     edi,edi  
829080f8 56              push    esi  
829080f9 8bf0            mov     esi,eax  
829080fb 8b4650          mov     eax,dword ptr [esi+50h]  
829080fe 8b4874          mov     ecx,dword ptr [eax+74h]  
82908101 f6c107          test    cl,7  
82908104 7409            je      nt!KeReadyThread+0x19 (8290810f)  

nt!KeReadyThread+0x10:  
82908106 e8e7cef6ff      call    nt!KiInSwapSingleProcess (82874ff2)  
8290810b 84c0            test    al,al  
8290810d 7505            jne     nt!KeReadyThread+0x1e (82908114)  

nt!KeReadyThread+0x19:  
8290810f e87c70feff      call    nt!KiFastReadyThread (828ef190)  

nt!KeReadyThread+0x1e:  
82908114 5e              pop     esi  
82908115 c3              ret

_KTHREAD 结构

lkd> dt _KTHREAD
nt!_KTHREAD
   +0x000 Header           : _DISPATCHER_HEADER
   +0x010 CycleTime        : Uint8B
   +0x018 HighCycleTime    : Uint4B
   +0x020 QuantumTarget    : Uint8B
   +0x028 InitialStack     : Ptr32 Void
   +0x02c StackLimit       : Ptr32 Void
   +0x030 KernelStack      : Ptr32 Void
   +0x034 ThreadLock       : Uint4B
   +0x038 WaitRegister     : _KWAIT_STATUS_REGISTER
   +0x039 Running          : UChar
   +0x03a Alerted          : [2] UChar
   +0x03c KernelStackResident : Pos 0, 1 Bit
   +0x03c ReadyTransition  : Pos 1, 1 Bit
   +0x03c ProcessReadyQueue : Pos 2, 1 Bit
   +0x03c WaitNext         : Pos 3, 1 Bit
   +0x03c SystemAffinityActive : Pos 4, 1 Bit
   +0x03c Alertable        : Pos 5, 1 Bit
   +0x03c GdiFlushActive   : Pos 6, 1 Bit
   +0x03c UserStackWalkActive : Pos 7, 1 Bit
   +0x03c ApcInterruptRequest : Pos 8, 1 Bit
   +0x03c ForceDeferSchedule : Pos 9, 1 Bit
   +0x03c QuantumEndMigrate : Pos 10, 1 Bit
   +0x03c UmsDirectedSwitchEnable : Pos 11, 1 Bit
   +0x03c TimerActive      : Pos 12, 1 Bit
   +0x03c Reserved         : Pos 13, 19 Bits
   +0x03c MiscFlags        : Int4B
   +0x040 ApcState         : _KAPC_STATE
   +0x040 ApcStateFill     : [23] UChar
   +0x057 Priority         : Char
   +0x058 NextProcessor    : Uint4B
   +0x05c DeferredProcessor : Uint4B
   +0x060 ApcQueueLock     : Uint4B
   +0x064 ContextSwitches  : Uint4B
   +0x068 State            : UChar
   +0x069 NpxState         : Char
   +0x06a WaitIrql         : UChar
   +0x06b WaitMode         : Char
   +0x06c WaitStatus       : Int4B
   +0x070 WaitBlockList    : Ptr32 _KWAIT_BLOCK
   +0x074 WaitListEntry    : _LIST_ENTRY
   +0x074 SwapListEntry    : _SINGLE_LIST_ENTRY
   +0x07c Queue            : Ptr32 _KQUEUE
   +0x080 WaitTime         : Uint4B
   +0x084 KernelApcDisable : Int2B
   +0x086 SpecialApcDisable : Int2B
   +0x084 CombinedApcDisable : Uint4B
   +0x088 Teb              : Ptr32 Void
   +0x090 Timer            : _KTIMER
   +0x0b8 AutoAlignment    : Pos 0, 1 Bit
   +0x0b8 DisableBoost     : Pos 1, 1 Bit
   +0x0b8 EtwStackTraceApc1Inserted : Pos 2, 1 Bit
   +0x0b8 EtwStackTraceApc2Inserted : Pos 3, 1 Bit
   +0x0b8 CalloutActive    : Pos 4, 1 Bit
   +0x0b8 ApcQueueable     : Pos 5, 1 Bit
   +0x0b8 EnableStackSwap  : Pos 6, 1 Bit
   +0x0b8 GuiThread        : Pos 7, 1 Bit
   +0x0b8 UmsPerformingSyscall : Pos 8, 1 Bit
   +0x0b8 ReservedFlags    : Pos 9, 23 Bits
   +0x0b8 ThreadFlags      : Int4B
   +0x0bc ServiceTable     : Ptr32 Void
   +0x0c0 WaitBlock        : [4] _KWAIT_BLOCK
   +0x120 QueueListEntry   : _LIST_ENTRY
   +0x128 TrapFrame        : Ptr32 _KTRAP_FRAME
   +0x12c FirstArgument    : Ptr32 Void
   +0x130 CallbackStack    : Ptr32 Void
   +0x130 CallbackDepth    : Uint4B
   +0x134 ApcStateIndex    : UChar
   +0x135 BasePriority     : Char
   +0x136 PriorityDecrement : Char
   +0x136 ForegroundBoost  : Pos 0, 4 Bits
   +0x136 UnusualBoost     : Pos 4, 4 Bits
   +0x137 Preempted        : UChar
   +0x138 AdjustReason     : UChar
   +0x139 AdjustIncrement  : Char
   +0x13a PreviousMode     : Char
   +0x13b Saturation       : Char
   +0x13c SystemCallNumber : Uint4B
   +0x140 FreezeCount      : Uint4B
   +0x144 UserAffinity     : _GROUP_AFFINITY
   +0x150 Process          : Ptr32 _KPROCESS
   +0x154 Affinity         : _GROUP_AFFINITY
   +0x160 IdealProcessor   : Uint4B
   +0x164 UserIdealProcessor : Uint4B
   +0x168 ApcStatePointer  : [2] Ptr32 _KAPC_STATE
   +0x170 SavedApcState    : _KAPC_STATE
   +0x170 SavedApcStateFill : [23] UChar
   +0x187 WaitReason       : UChar
   +0x188 SuspendCount     : Char
   +0x189 Spare1           : Char
   +0x18a OtherPlatformFill : UChar
   +0x18c Win32Thread      : Ptr32 Void
   +0x190 StackBase        : Ptr32 Void
   +0x194 SuspendApc       : _KAPC
   +0x194 SuspendApcFill0  : [1] UChar
   +0x195 ResourceIndex    : UChar
   +0x194 SuspendApcFill1  : [3] UChar
   +0x197 QuantumReset     : UChar
   +0x194 SuspendApcFill2  : [4] UChar
   +0x198 KernelTime       : Uint4B
   +0x194 SuspendApcFill3  : [36] UChar
   +0x1b8 WaitPrcb         : Ptr32 _KPRCB
   +0x194 SuspendApcFill4  : [40] UChar
   +0x1bc LegoData         : Ptr32 Void
   +0x194 SuspendApcFill5  : [47] UChar
   +0x1c3 LargeStack       : UChar
   +0x1c4 UserTime         : Uint4B
   +0x1c8 SuspendSemaphore : _KSEMAPHORE
   +0x1c8 SuspendSemaphorefill : [20] UChar
   +0x1dc SListFaultCount  : Uint4B
   +0x1e0 ThreadListEntry  : _LIST_ENTRY
   +0x1e8 MutantListHead   : _LIST_ENTRY
   +0x1f0 SListFaultAddress : Ptr32 Void
   +0x1f4 ThreadCounters   : Ptr32 _KTHREAD_COUNTERS
   +0x1f8 XStateSave       : Ptr32 _XSTATE_SAVE

解决方案

我想到的唯一可能解决方案是运行代码并查看寄存器指向什么,但除了不知道它是否正确之外,我不知道该怎么做。正如您可能已经猜到的那样,我非常缺乏经验。

3个回答

显然,KeReadyThreadeax寄存器中传递了一个参数

要真正反转该参数的结构/类型,您需要进行大量逆向工程。

对你来说幸运的是,ReactOS 的人已经为你做到了。如果您查看该链接,您将看到 ReactOSKeReadyThread接受结构的单个参数的实现PKTREAD

这是KeReadyThreadReactOS 的代码:

113 VOID
114 NTAPI
115 KeReadyThread(IN PKTHREAD Thread)
116 {
117     KIRQL OldIrql;
118     ASSERT_THREAD(Thread);
119     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
120 
121     /* Lock the Dispatcher Database */
122     OldIrql = KiAcquireDispatcherLock();
123 
124     /* Make the thread ready */
125     KiReadyThread(Thread);
126 
127     /* Unlock dispatcher database */
128     KiReleaseDispatcherLock(OldIrql);
129 }

具体来说,您在共享的程序集顶部看到的取消引用是以下代码的实现ASSERT_THREAD

#define ASSERT_THREAD (object) ASSERT((((object)->Header.Type & KOBJECT_TYPE_MASK) == ThreadObject))

由于最近的活动而弹出此线程

引用已接受的答案 An Answer By Nirlzr

具体来说,您在共享的程序集顶部看到的取消引用是 ASSERT_THREAD 的实现:

反汇编和解引用不属于 ASSERT_THREAD

取消引用检查 _KAPC_STATE.Process.StackCount 的 StackCount 成员

kd> dt nt!_ETHREAD Tcb.ApcState.Process->StackCount.StackCount
   +0x000 Tcb                                         : 
      +0x040 ApcState                                    : 
         +0x010 Process                                     : 
            +0x074 StackCount                                  : 
               +0x000 StackCount                                  : Pos 3, 29 Bits  

谷歌搜索geoffrey chappel _KTHREAD 将提供有关覆盖和优先级成员的更多信息,这是一个适合x86 的KAPC_STATE 内的字符

第三步是指 Thread 参数中的一个成员(显示在由 Nirlzr 链接的 ReactOS 源代码中),它位于偏移量 +0x50 处。正如在 _KTHREAD 结构中所见,偏移量 +0x50 处没有任何内容,并且我们在该偏移量处拥有的 2 个最接近的成员是 ApcState 和 ApcStateFill。进一步查看 ApcStateFill 是没有意义的,因为它只是一个字符串并且会使第四步变得毫无意义,但是 ApcState 很有趣,因为它是一个 _KAPC_STATE 结构。有趣的是,ApcState 在 +0x10 处有一个成员,称为 Process,它与第三次移动相应地工作,我们在偏移量 +[0x40 + 0x10] 处移动成员值。第四个移动是指向前面在 _KAPC_STATE 结构中讨论的 Process 成员处的另一个 _KPROCESS 结构的指针。这个指向 _KPROCESS + 0x70 的指针为我们提供了成员 StackCount。最后,