欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]64位CreateProcess逆向:(五)创建线程的过程

[原创]64位CreateProcess逆向:(五)创建线程的过程

点击下面进入总目录:
64位Windows创建64位进程逆向分析(总目录)
    上一篇文章我们讨论了进程创建的过程。这篇文章会介绍线程创建的过程。
    64位Windows 7,在CreateProcess中,调用了PspAllocateThread来创建线程。它的原型如下:
PspAllocateThread

NTSTATUS
PspAllocateThread(PEPROCESS newProcess,
POBJECT_ATTRIBUTES   ObjectAttributes,
KPROCESSOR_MODE     AccessMode,
CreateProcessContext ProcessContext,
CONTEXT         context,
PINITIAL_TEB       pInitTeb,
PVOID           StartRoutine,
PVOID           StartContext,
PULONG         ptrProcessFlag,
PETHREAD *        pptrEthread,
DIYStruct*       unknownStruct,
ACCESS_STATE_EXPAND* pAccessStateExpand
)

它的主要参数的作用如下:
    newProcess里包含很多进程信息,根据进程信息如进程是32位或者64位,填充不一样的结构体,初始化_ETHREAD成员时,需要填充_ETHREAD部分成员。Context的成员Rip, Rcx用于初始化给ETHREAD.StartAddress, Win32StartAddress,调用KeInitThread初始化线程时,需要context,StartRoutine,StartContext来初始化线程上下文。
    PspAllocateThread内部的流程比较简单,对于熟悉线程结构体的人来说,可以概括成一句话,就是“创建线程结构体,并初始化”,然而,对于我们这些学习者而言,就有必要先了解下线程相关的结构体。
线程相关结构体
    Windows中,用ETHREAD结构体来承载线程信息,ETHREAD结构体保存在0环的内存空间,即归整个操作系统统一管理。此外,每一个线程还对应了TEB(Thread Environment Block),TEB是保存在各个进程的内存空间中的,即3环。
    在通过WinDbg详细看他们的成员组成前,我们可以自己通过线程、进程的基础知识,推断出ETHREAD中应该包含哪些信息:(核心成员都在kthread中,ethread与本篇分析关系较小,故略过)
?  因为一个进程可以拥有多个线程,所以对与每个线程,应该包含它所属的进程的相关信息
?  同一个进程的多个线程,要轮流占用cpu时间片,因此互相应该有彼此信息,即一个线程应该能够遍历与自己“相关”的其它线程
?  同一个进程的多个线程,虽然共用内存空间,但是不能共用栈空间(否则函数调用就乱了),因此每个线程应该记录自己栈对应的信息
?  每个APC都是在特定的线程环境中执行的,从而也一定在特定的进程环境中执行,因此每个线程都有自己特有的APC链表
  有了这些基本认识,我们再来具体看相关的结构体。
KTHREAD结构体
dt !_KTHREAD
ntdll!_KTHREAD
   +0x000 Header           : _DISPATCHER_HEADER
   +0x018 CycleTime        : Uint8B
   +0x020 QuantumTarget    : Uint8B
   +0x028 InitialStack     : Ptr64 Void
   +0x030 StackLimit       : Ptr64 Void
   +0x038 KernelStack      : Ptr64 Void
   +0x040 ThreadLock       : Uint8B
   +0x048 WaitRegister     : _KWAIT_STATUS_REGISTER
   +0x049 Running          : UChar
   +0x04a Alerted          : [2] UChar
   +0x04c KernelStackResident : Pos 0, 1 Bit
   +0x04c ReadyTransition  : Pos 1, 1 Bit
   +0x04c ProcessReadyQueue : Pos 2, 1 Bit
   +0x04c WaitNext         : Pos 3, 1 Bit
   +0x04c SystemAffinityActive : Pos 4, 1 Bit
   +0x04c Alertable        : Pos 5, 1 Bit
   +0x04c GdiFlushActive   : Pos 6, 1 Bit
   +0x04c UserStackWalkActive : Pos 7, 1 Bit
   +0x04c ApcInterruptRequest : Pos 8, 1 Bit
   +0x04c ForceDeferSchedule : Pos 9, 1 Bit
   +0x04c QuantumEndMigrate : Pos 10, 1 Bit
   +0x04c UmsDirectedSwitchEnable : Pos 11, 1 Bit
   +0x04c TimerActive      : Pos 12, 1 Bit
   +0x04c SystemThread     : Pos 13, 1 Bit
   +0x04c Reserved         : Pos 14, 18 Bits
   +0x04c MiscFlags        : Int4B
   +0x050 ApcState         : _KAPC_STATE
   +0x050 ApcStateFill     : [43] UChar
   +0x07b Priority         : Char
   +0x07c NextProcessor    : Uint4B
   +0x080 DeferredProcessor : Uint4B
   +0x088 ApcQueueLock     : Uint8B
   +0x090 WaitStatus       : Int8B
   +0x098 WaitBlockList    : Ptr64 _KWAIT_BLOCK
   +0x0a0 WaitListEntry    : _LIST_ENTRY
   +0x0a0 SwapListEntry    : _SINGLE_LIST_ENTRY
   +0x0b0 Queue            : Ptr64 _KQUEUE
   +0x0b8 Teb              : Ptr64 Void
   +0x0c0 Timer            : _KTIMER
   +0x100 AutoAlignment    : Pos 0, 1 Bit
   +0x100 DisableBoost     : Pos 1, 1 Bit
   +0x100 EtwStackTraceApc1Inserted : Pos 2, 1 Bit
   +0x100 EtwStackTraceApc2Inserted : Pos 3, 1 Bit
   +0x100 CalloutActive    : Pos 4, 1 Bit
   +0x100 ApcQueueable     : Pos 5, 1 Bit
   +0x100 EnableStackSwap  : Pos 6, 1 Bit
   +0x100 GuiThread        : Pos 7, 1 Bit
   +0x100 UmsPerformingSyscall : Pos 8, 1 Bit
   +0x100 VdmSafe          : Pos 9, 1 Bit
   +0x100 UmsDispatched    : Pos 10, 1 Bit
   +0x100 ReservedFlags    : Pos 11, 21 Bits
   +0x100 ThreadFlags      : Int4B
   +0x104 Spare0           : Uint4B
   +0x108 WaitBlock        : [4] _KWAIT_BLOCK
   +0x108 WaitBlockFill4   : [44] UChar
   +0x134 ContextSwitches  : Uint4B
   +0x108 WaitBlockFill5   : [92] UChar
   +0x164 State            : UChar
   +0x165 NpxState         : Char
   +0x166 WaitIrql         : UChar
   +0x167 WaitMode         : Char
   +0x108 WaitBlockFill6   : [140] UChar
   +0x194 WaitTime         : Uint4B
   +0x108 WaitBlockFill7   : [168] UChar
   +0x1b0 TebMappedLowVa   : Ptr64 Void
   +0x1b8 Ucb              : Ptr64 _UMS_CONTROL_BLOCK
   +0x108 WaitBlockFill8   : [188] UChar
   +0x1c4 KernelApcDisable : Int2B
   +0x1c6 SpecialApcDisable : Int2B
   +0x1c4 CombinedApcDisable : Uint4B
   +0x1c8 QueueListEntry   : _LIST_ENTRY
   +0x1d8 TrapFrame        : Ptr64 _KTRAP_FRAME
   +0x1e0 FirstArgument    : Ptr64 Void
   +0x1e8 CallbackStack    : Ptr64 Void
   +0x1e8 CallbackDepth    : Uint8B
   +0x1f0 ApcStateIndex    : UChar
   +0x1f1 BasePriority     : Char
   +0x1f2 PriorityDecrement : Char
   +0x1f2 ForegroundBoost  : Pos 0, 4 Bits
   +0x1f2 UnusualBoost     : Pos 4, 4 Bits
   +0x1f3 Preempted        : UChar
   +0x1f4 AdjustReason     : UChar
   +0x1f5 AdjustIncrement  : Char
   +0x1f6 PreviousMode     : Char
   +0x1f7 Saturation       : Char
   +0x1f8 SystemCallNumber : Uint4B
   +0x1fc FreezeCount      : Uint4B
   +0x200 UserAffinity     : _GROUP_AFFINITY
   +0x210 Process          : Ptr64 _KPROCESS
   +0x218 Affinity         : _GROUP_AFFINITY
   +0x228 IdealProcessor   : Uint4B
   +0x22c UserIdealProcessor : Uint4B
   +0x230 ApcStatePointer  : [2] Ptr64 _KAPC_STATE
   +0x240 SavedApcState    : _KAPC_STATE
   +0x240 SavedApcStateFill : [43] UChar
   +0x26b WaitReason       : UChar
   +0x26c SuspendCount     : Char
   +0x26d Spare1           : Char
   +0x26e CodePatchInProgress : UChar
   +0x270 Win32Thread      : Ptr64 Void
   +0x278 StackBase        : Ptr64 Void
   +0x280 SuspendApc       : _KAPC
   +0x280 SuspendApcFill0  : [1] UChar
   +0x281 ResourceIndex    : UChar
   +0x280 SuspendApcFill1  : [3] UChar
   +0x283 QuantumReset     : UChar
   +0x280 SuspendApcFill2  : [4] UChar
   +0x284 KernelTime       : Uint4B
   +0x280 SuspendApcFill3  : [64] UChar
   +0x2c0 WaitPrcb         : Ptr64 _KPRCB
   +0x280 SuspendApcFill4  : [72] UChar
   +0x2c8 LegoData         : Ptr64 Void
   +0x280 SuspendApcFill5  : [83] UChar
   +0x2d3 LargeStack       : UChar
   +0x2d4 UserTime         : Uint4B
   +0x2d8 SuspendSemaphore : _KSEMAPHORE
   +0x2d8 SuspendSemaphorefill : [28] UChar
   +0x2f4 SListFaultCount  : Uint4B
   +0x2f8 ThreadListEntry  : _LIST_ENTRY
   +0x308 MutantListHead   : _LIST_ENTRY
   +0x318 SListFaultAddress : Ptr64 Void
   +0x320 ReadOperationCount : Int8B
   +0x328 WriteOperationCount : Int8B
   +0x330 OtherOperationCount : Int8B
   +0x338 ReadTransferCount : Int8B
   +0x340 WriteTransferCount : Int8B
   +0x348 OtherTransferCount : Int8B
   +0x350 ThreadCounters   : Ptr64 _KTHREAD_COUNTERS
   +0x358 XStateSave       : Ptr64 _XSTATE_SAVE

    正如我们之前所推测的,在实际ETHREAD结构体中,Tcb.Process成员,就是负责保存线程所属进程信息的;而Tcb.ThreadListEntry,可以遍历进程下的所有线程;Tcb.StackBase、Tcb.InitialStack、Tcb.InitialStack、Tcb.KernelStack Tcb.IdealProcessor等保存了线程的栈信息和CPU信息;Tcb.ApcState包含APC链表信息。
    通过以下对函数的详细分析,我们可以看出PspAllocateThread内部,对各个结构体创建、初始化的时机和流程。
函数流程详细实现:

    首先对参数context进行判断,如果不为空,并且参数ProcessContext中的标志位与0x8000后成立,再看当前eprocess中的Wow64Process,如果是32位程序,则直接返回STATUS_INVALID_PARAMETER错误。


    填充输出参数pAccessStateExpand的成员

    将当前EPROCESS和PsInitialSystemProcess作比较,若相等,直接返回STATUS_INVALID_PARAMETER

    调用obCreateObject,指定对象类型为PsThreadType,创建ETHREAD对象,创建的对象类型是在系统初始时通过ObCreateObjectType创建的。

    初始化ETHREAD中的ClientID成员

    初始化ETHREAD中的信号量,以及IrpList(包含了当前线程所有正在处理但尚未完成的I/O请求(Irp对象))和ActiveTimerListHead(ActiveTimerListHead域是一个双链表的头,链表中包含了当前线程的所有定时器)。

    调用ExCreateHandle创建句柄,说是创建句柄,更准确的说法应该是为句柄分配索引号,上一篇创建进程的文章中,通过调用ExCreateHandleTable创建了一个句柄表,通过句柄表内相关信息来分配可用的空间,并设置句柄值。
    最后将创建句柄并且写入到ETHREAD.Cid.UniqueThread中。


    再一次判断Context,如果为NULL,进入系统线程初始化

    系统线程初始化流程如下,之后不管成功与否,都退出函数,如果失败,做一些收尾工作,比如删除对象等。


    回到用户线程初始化部分,判断参数unknownStruct是否为空,如果为空,调用MmSecureVirtualMemory申请一个TEB大小的空间。

    紧接着初始化TEB, 根据wow64的值,来选择TEB32还是TEB64

    如果之前unknownStruct不为空,附加到本进程,创建堆栈空间,写入到initTEB参数的成员中

    调用MmCreateTeb创建TEB对象,传入Client_Id以及InitialTeb对其赋值。

    现在线程结构已经建立,可以调用KeInitThread初始化线程,KeInitThread函数主要是初始化线程结构的内核部分ETHREAD.Tcb(主要填充用于同步的成员或者结构,系统服务描述符表等)。

    写入创建的ETHREAD到输出参数

总流程图

上传的附件 1.png
2.png
3.png
4.png
5.png
6.png
7.png
8.png
9.png
10.png
11.png
12.png
13.png
14.png
15.png
16.png
17.png
18.png
19.png
PspAllocateThread.png
PspAllocateThread.doc
PspAllocateThread.pdf

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功