进程线程篇——进程线程基础
写在前面
此系列是本人一个字一个字码出来的,包括示例和实验截图。由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新。 如有好的建议,欢迎反馈。码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作。如想转载,请把我的转载信息附在文章后面,并声明我的个人信息和本人博客地址即可,但必须事先通知我。
你如果是从中间插过来看的,请仔细阅读 羽夏看Win系统内核——简述 ,方便学习本教程。
看此教程之前,问几个问题,基础知识储备好了吗?保护模式篇学会了吗?系统调用篇学会了吗?练习做完了吗?没有的话就不要继续了。
🔒 华丽的分割线 🔒
为了更好的学习进程与线程,我们需要充分了解3个结构体:
EPROCESS、
EHTREAD、
KPCR,下面将会进行详细介绍。
EPROCESS
每个
windows进程在0环都有一个对应的结构体:
EPROCESS,这个结构体包含了进程所有重要的信息。我们先看看里面的成员有哪些:
kd> dt _EPROCESS ntdll!_EPROCESS +0x000 Pcb : _KPROCESS +0x06c ProcessLock : _EX_PUSH_LOCK +0x070 CreateTime : _LARGE_INTEGER +0x078 ExitTime : _LARGE_INTEGER +0x080 RundownProtect : _EX_RUNDOWN_REF +0x084 UniqueProcessId : Ptr32 Void +0x088 ActiveProcessLinks : _LIST_ENTRY +0x090 QuotaUsage : [3] Uint4B +0x09c QuotaPeak : [3] Uint4B +0x0a8 CommitCharge : Uint4B +0x0ac PeakVirtualSize : Uint4B +0x0b0 VirtualSize : Uint4B +0x0b4 SessionProcessLinks : _LIST_ENTRY +0x0bc DebugPort : Ptr32 Void +0x0c0 ExceptionPort : Ptr32 Void +0x0c4 ObjectTable : Ptr32 _HANDLE_TABLE +0x0c8 Token : _EX_FAST_REF +0x0cc WorkingSetLock : _FAST_MUTEX +0x0ec WorkingSetPage : Uint4B +0x0f0 AddressCreationLock : _FAST_MUTEX +0x110 HyperSpaceLock : Uint4B +0x114 ForkInProgress : Ptr32 _ETHREAD +0x118 HardwareTrigger : Uint4B +0x11c VadRoot : Ptr32 Void +0x120 VadHint : Ptr32 Void +0x124 CloneRoot : Ptr32 Void +0x128 NumberOfPrivatePages : Uint4B +0x12c NumberOfLockedPages : Uint4B +0x130 Win32Process : Ptr32 Void +0x134 Job : Ptr32 _EJOB +0x138 SectionObject : Ptr32 Void +0x13c SectionBaseAddress : Ptr32 Void +0x140 QuotaBlock : Ptr32 _EPROCESS_QUOTA_BLOCK +0x144 WorkingSetWatch : Ptr32 _PAGEFAULT_HISTORY +0x148 Win32WindowStation : Ptr32 Void +0x14c InheritedFr ad8 omUniqueProcessId : Ptr32 Void +0x150 LdtInformation : Ptr32 Void +0x154 VadFreeHint : Ptr32 Void +0x158 VdmObjects : Ptr32 Void +0x15c DeviceMap : Ptr32 Void +0x160 PhysicalVadList : _LIST_ENTRY +0x168 PageDirectoryPte : _HARDWARE_PTE_X86 +0x168 Filler : Uint8B +0x170 Session : Ptr32 Void +0x174 ImageFileName : [16] UChar +0x184 JobLinks : _LIST_ENTRY +0x18c LockedPagesList : Ptr32 Void +0x190 ThreadListHead : _LIST_ENTRY +0x198 SecurityPort : Ptr32 Void +0x19c PaeTop : Ptr32 Void +0x1a0 ActiveThreads : Uint4B +0x1a4 GrantedAccess : Uint4B +0x1a8 DefaultHardErrorProcessing : Uint4B +0x1ac LastThreadExitStatus : Int4B +0x1b0 Peb : Ptr32 _PEB +0x1b4 PrefetchTrace : _EX_FAST_REF +0x1b8 ReadOperationCount : _LARGE_INTEGER +0x1c0 WriteOperationCount : _LARGE_INTEGER +0x1c8 OtherOperationCount : _LARGE_INTEGER +0x1d0 ReadTransferCount : _LARGE_INTEGER +0x1d8 WriteTransferCount : _LARGE_INTEGER +0x1e0 OtherTransferCount : _LARGE_INTEGER +0x1e8 CommitChargeLimit : Uint4B +0x1ec CommitChargePeak : Uint4B +0x1f0 AweInfo : Ptr32 Void +0x1f4 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO +0x1f8 Vm : _MMSUPPORT +0x238 LastFaultCount : Uint4B +0x23c ModifiedPageCount : Uint4B +0x240 NumberOfVads : Uint4B +0x244 JobStatus : Uint4B +0x248 Flags : Uint4B +0x248 CreateReported : Pos 0, 1 Bit +0x248 NoDebugInherit : Pos 1, 1 Bit +0x248 ProcessExiting : Pos 2, 1 Bit +0x248 ProcessDelete : Pos 3, 1 Bit +0x248 Wow64SplitPages : Pos 4, 1 Bit +0x248 VmDeleted : Pos 5, 1 Bit +0x248 OutswapEnabled : Pos 6, 1 Bit +0x248 Outswapped : Pos 7, 1 Bit +0x248 ForkFailed : Pos 8, 1 Bit +0x248 HasPhysicalVad : Pos 9, 1 Bit +0x248 AddressSpaceInitialized : Pos 10, 2 Bits +0x248 SetTimerResolution : Pos 12, 1 Bit +0x248 BreakOnTermination : Pos 13, 1 Bit +0x248 SessionCreationUnderway : Pos 14, 1 Bit +0x248 WriteWatch : Pos 15, 1 Bit +0x248 ProcessInSession : Pos 16, 1 Bit +0x248 OverrideAddressSpace : Pos 17, 1 Bit +0x248 HasAddressSpace : Pos 18, 1 Bit +0x248 LaunchPrefetched : Pos 19, 1 Bit +0x248 InjectInpageErrors : Pos 20, 1 Bit +0x248 VmTopDown : Pos 21, 1 Bit +0x248 Unused3 : Pos 22, 1 Bit +0x248 Unused4 : Pos 23, 1 Bit +0x248 VdmAllowed : Pos 24, 1 Bit +0x248 Unused : Pos 25, 5 Bits +0x248 Unused1 : Pos 30, 1 Bit +0x248 Unused2 : Pos 31, 1 Bit +0x24c ExitStatus : Int4B +0x250 NextPageColor : Uint2B +0x252 ad0 SubSystemMinorVersion : UChar +0x253 SubSystemMajorVersion : UChar +0x252 SubSystemVersion : Uint2B +0x254 PriorityClass : UChar +0x255 WorkingSetAcquiredUnsafe : UChar +0x258 Cookie : Uint4B
虽然有很多成员,我们只要知道几个重要的成员即可,由于
Windows是闭源的,如果需要详细了解就必须花费大量的时间进行逆向分析才能明白。这个结构体还嵌套了一个结构体
_KPROCESS,我们看一下:
kd> dt _KPROCESS ntdll!_KPROCESS +0x000 Header : _DISPATCHER_HEADER +0x010 ProfileListHead : _LIST_ENTRY +0x018 DirectoryTableBase : [2] Uint4B +0x020 LdtDescriptor : _KGDTENTRY +0x028 Int21Descriptor : _KIDTENTRY +0x030 IopmOffset : Uint2B +0x032 Iopl : UChar +0x033 Unused : UChar +0x034 ActiveProcessors : Uint4B +0x038 KernelTime : Uint4B +0x03c UserTime : Uint4B +0x040 ReadyListHead : _LIST_ENTRY +0x048 SwapListEntry : _SINGLE_LIST_ENTRY +0x04c VdmTrapcHandler : Ptr32 Void +0x050 ThreadListHead : _LIST_ENTRY +0x058 ProcessLock : Uint4B +0x05c Affinity : Uint4B +0x060 StackCount : Uint2B +0x062 BasePriority : Char +0x063 ThreadQuantum : Char +0x064 AutoAlignment : UChar +0x065 State : UChar +0x066 ThreadSeed : UChar +0x067 DisableBoost : UChar +0x068 PowerState : UChar +0x069 DisableQuantum : UChar +0x06a IdealNode : UChar +0x06b Flags : _KEXECUTE_OPTIONS +0x06b ExecuteOptions : UChar
Header
在3环使用
API的时候,我们都用过等待对象的函数,为什么有的内核对象是可以等待的?是因为它有
_DISPATCHER_HEADER这个结构。
DirectoryTableBase
页目录表的基址,也就是所谓的
CR3。
LdtDescriptor / Int21Descriptor
历史遗留问题,16位
Windows段选择子不够,每个进程都有一个
LDT表,
Int21Descriptor是
DOS下要用的。
KernelTime / UserTime
统计信息,记录了一个进程在内核模式/用户模式下所花的时间,没什么太大的用处。
Affinity
这个成员十分重要,它有4个字节,每一个二进制位控制进程里面的所有线程能在哪个
CPU上跑,如果值为1,那这个进程的所以线程只能在0号
CPU上跑;如果值为3,那这个进程的所以线程能在0、1号CPU
上跑;如果值为4,那这个进程的所以线程能在2号CPU上跑;如果值为5,那这个进程的所以线程能在0,2号
CPU上跑。如果只有一个
CPU,把这个设置为4,那么这个进程就死了。
由于4个字节共32位,所以最多支持32核。64位的
Windows这个成员就是8个字节了,最多支持64核。
BasePriority
基础优先级或最低优先级,该进程中的所有线程最起码的优先级。
CreateTime / ExitTime
统计信息,记录了一个进程的创建/退出时间。
UniqueProcessId
进程的编号,也就是任务管理器中显示的
PID。
ActiveProcessLinks
所有的活动进程都连接在一起,构成的双向链表。全局变量
PsActiveProcessHead指向这个全局链的表头。如下是示意图:
QuotaUsage / QuotaPeak
物理页相关的统计信息。
CommitCharge / PeakVirtualSize / VirtualSize
虚拟内存相关的统计信息。
VadRoot
这东西我们之前介绍过,是一个二叉树,指示了进程的线性地址的使用情况和记录。
DebugPort / ExceptionPort
调试相关,经常有人使用
DebugPort清零实现反调试。
ObjectTable
句柄表,装着内核对象句柄,是用来标识某个内核对象的一个
id,同一个对象的该
id对于每个进程是不同的。后面的教程将会对句柄表进行讲解。
ImageFileName
进程镜像文件名,最多16个字节。
ActiveThreads
活动线程的数量。
Peb
英文全称为
Process Environment Block,意为进程环境块,是进程在3环的一个结构体,里面包含了进程的模块列表、是否处于调试状态等信息。
ETHREAD
每个
Windows线程在0环都有一个对应的结构体
ETHREAD,这个结构体我们曾在前面对某一部分进行简略的讲解,本篇将会详细介绍重要成员,它的结构体如下所示:
kd> dt _ETHREAD ntdll!_ETHREAD +0x000 Tcb : _KTHREAD +0x1c0 CreateTime : _LARGE_INTEGER +0x1c0 NestedFaultCount : Pos 0, 2 Bits +0x1c0 ApcNeeded : Pos 2, 1 Bit +0x1c8 ExitTime : _LARGE_INTEGER +0x1c8 LpcReplyChain : _LIST_ENTRY +0x1c8 KeyedWaitChain : _LIST_ENTRY +0x1d0 ExitStatus : Int4B +0x1d0 OfsChain : Ptr32 Void +0x1d4 PostBlockList : _LIST_ENTRY +0x1dc TerminationPort : Ptr32 _TERMINATION_PORT +0x1dc ReaperLink : Ptr32 _ETHREAD +0x1dc KeyedWaitValue : Ptr32 Void +0x1e0 ActiveTimerListLock : Uint4B +0x1e4 ActiveTimerListHead : _LIST_ENTRY +0x1ec Cid : _CLIENT_ID +0x1f4 LpcReplySemaphore : _KSEMAPHORE +0x1f4 KeyedWaitSemaphore : _KSEMAPHORE +0x208 LpcReplyMessage : Ptr32 Void +0x208 LpcWaitingOnPort : Ptr32 Void +0x20c ImpersonationInfo : Ptr32 _PS_IMPERSONATION_INFORMATION +0x210 IrpList : _LIST_ENTRY +0x218 TopLevelIrp : Uint4B +0x21c DeviceToVerify : Ptr32 _DEVICE_OBJECT +0x220 ThreadsProcess : Ptr32 _EPROCESS +0x224 StartAddress : Ptr32 Void +0x228 Win32StartAddress : Ptr32 Void +0x228 LpcReceivedMessageId : Uint4B +0x22c ThreadListEntry : _LIST_ENTRY +0x234 RundownProtect : _EX_RUNDOWN_REF +0x238 ThreadLock : _EX_PUSH_LOCK +0x23c LpcReplyMessageId : Uint4B +0x240 ReadClusterSize : Uint4B +0x244 GrantedAccess : Uint4B +0x248 CrossThreadFlags : Uint4B +0x248 Terminated : Pos 0, 1 Bit +0x248 DeadThread : Pos 1, 1 Bit +0x248 HideFromDebugger : Pos 2, 1 Bit +0x248 ActiveImpersonationInfo : Pos 3, 1 Bit +0x248 SystemThread : Pos 4, 1 Bit +0x248 HardErrorsAreDisabled : Pos 5, 1 Bit +0x248 BreakOnTermination : Pos 6, 1 Bit +0x248 SkipCreationMsg : Pos 7, 1 Bit +0x248 SkipTerminationMsg : Pos 8, 1 Bit +0x24c SameThreadPassiveFlags : Uint4B +0x24c ActiveExWorker : Pos 0, 1 Bit +0x24c ExWorkerCanWaitUser : Pos 1, 1 Bit +0x24c MemoryMaker : Pos 2, 1 Bit +0x250 SameThreadApcFlags : Uint4B +0x250 LpcReceivedMsgIdValid : Pos 0, 1 Bit +0x250 LpcExitThreadCalled : Pos 1, 1 Bit +0x250 AddressSpaceOwner : Pos 2, 1 Bit +0x254 ForwardClusterOnly : UChar +0x255 DisablePageFaultClustering : UChar
第一个成员还嵌套了一个结构体,我们查看一下:
kd> dt _KTHREAD ntdll!_KTHREAD +0x000 Header : _DISPATCHER_HEADER +0x010 MutantListHead : _LIST_ENTRY +0x018 InitialStack : Ptr32 Void +0x01c StackLimit : Ptr32 Void +0x020 Teb : Ptr32 Void +0x024 TlsArray : Ptr32 Void +0x028 KernelStack : Ptr32 Void +0x02c DebugActive : UChar +0x02d State : UChar +0x02e Alerted : [2] UChar +0x030 Iopl : UChar +0x031 NpxState : UChar +0x032 Saturation : Char +0x033 Priority : Char +0x034 ApcState : _KAPC_STATE +0x04c ContextSwitches : Uint4B +0x050 IdleSwapBlock : UChar +0x051 Spare0 : [3] UChar +0x054 WaitStatus : Int4B +0x058 WaitIrql : UChar +0x059 WaitMode : Char +0x05a WaitNext : UChar +0x05b WaitReason : UChar +0x05c WaitBlockList : Ptr32 _KWAIT_BLOCK +0x060 WaitListEntry : _LIST_ENTRY +0x060 SwapListEntry : _SINGLE_LIST_ENTRY +0x068 WaitTime : Uint4B +0x06c BasePriority : Char +0x06d DecrementCount : UChar +0x06e PriorityDecrement : Char +0x06f Quantum : Char +0x070 WaitBlock : [4] _KWAIT_BLOCK +0x0d0 LegoData : Ptr32 Void +0x0d4 KernelApcDisable : Uint4B +0x0d8 UserAffinity : Uint4B +0x0dc SystemAffinityActive : UChar +0x0dd PowerState : UChar +0x0de NpxIrql : UChar +0x0df InitialNode : UChar +0x0e0 ServiceTable : Ptr32 Void +0x0e4 Queue : Ptr32 _KQUEUE +0x0e8 ApcQueueLock : Uint4B +0x0f0 Timer : _KTIMER +0x118 QueueListEntry : _LIST_ENTRY +0x120 SoftAffinity : Uint4B +0x124 Affinity : Uint4B +0x128 Preempted : UChar +0x129 ProcessReadyQueue : UChar +0x12a KernelStackResident : UChar +0x12b NextProcessor : UChar +0x12c CallbackStack : Ptr32 Void +0x130 Win32Thread : Ptr32 Void +0x134 TrapFrame : Ptr32 _KTRAP_FRAME +0x138 ApcStatePointer : [2] Ptr32 _KAPC_STATE +0x140 PreviousMode : Char +0x141 EnableStackSwap : UChar +0x142 LargeStack : UChar +0x143 ResourceIndex : UChar +0x144 KernelTime : Uint4B +0x148 UserTime : Uint4B +0x14c SavedApcState : _KAPC_STATE +0x164 Alertable : UChar +0x165 ApcStateIndex : UChar +0x166 ApcQueueable : UChar +0x167 AutoAlignment : UChar +0x168 StackBase : Ptr32 Void +0x16c SuspendApc : _KAPC +0x19c SuspendSemaphore : _KSEMAPHORE +0x1b0 ThreadListEntry : _LIST_ENTRY +0x1b8 FreezeCount : Char +0x1b9 SuspendCount : Char +0x1ba IdealProcessor : UChar +0x1bb DisableBoost : UChar
Header
和
EPROCESS一样的,就不赘述了。
InitialStack / StackLimit / KernelStack
这三个成员十分重要,与线程切换相关。
KernelStack为当前切换线程的
esp,它们的细节将会在后面的随笔介绍。
Teb
英文全称为
Thread Environment Block,意为线程环境块,大小4KB,位于用户地址空间。在3环时,
fs寄存器中存储该结构。
DebugActive
如果值为-1,则不能使用调试寄存器
Dr0-
Dr7。
ApcState / ApcQueueLock / ApcStatePointer / SavedApcState
APC相关,具体细节将会在后面的一个篇章进行讲解。
State
指示线程状态:
waiting/
ready/
running。
BasePriority
其初始值是所属进程的
BasePriority值,以后可以通过
KeSetBasePriorityThread函数重新设定。
WaitBlock
里面存储了等待哪个对象,比如调用
WaitForSingleObject。
ServiceTable
指向系统服务表基址。
TrapFrame
存储着进0环时保存环境。
PreviousMode
先前模式,指示程序是0环调用还是3环调用的。
ThreadListEntry
一个进程所有的线程,都挂在一个双向链表中,一共有两个这样的链表,
KTHREAD一个,
ETHREAD外面一个,示意图如下:
Cid
存储着进程ID和线程ID,它的结构体如下:
kd> dt _CLIENT_ID ntdll!_CLIENT_ID +0x000 UniqueProcess : Ptr32 Void +0x004 UniqueThread : Ptr32 Void
ThreadsProcess
指向自己所属进程。
KPCR
KPCR中存储了
CPU本身要用的一些重要数据:
GDT、
IDT以及线程相关的一些信息。当线程进入0环时,
FS:[0]指向
KPCR,3环时
FS:[0]指向
TEB。每个
CPU都有一个
KPCR结构体,即一个核一个。之前也略有介绍,它的结构如下:
kd> dt _KPCR nt!_KPCR +0x000 NtTib : _NT_TIB +0x01c SelfPcr : Ptr32 _KPCR +0x020 Prcb : Ptr32 _KPRCB +0x024 Irql : UChar +0x028 IRR : Uint4B +0x02c IrrActive : Uint4B +0x030 IDR : Uint4B +0x034 KdVersionBlock : Ptr32 Void +0x038 IDT : Ptr32 _KIDTENTRY +0x03c GDT : Ptr32 _KGDTENTRY +0x040 TSS : Ptr32 _KTSS +0x044 MajorVersion : Uint2B +0x046 MinorVersion : Uint2B +0x048 SetMember : Uint4B +0x04c StallScaleFactor : Uint4B +0x050 DebugActive : UChar +0x051 Number : UChar +0x052 Spare0 : UChar +0x053 SecondLevelCacheAssociativity : UChar +0x054 VdmAlert : Uint4B +0x058 KernelReserved : [14] Uint4B +0x090 SecondLevelCacheSize : Uint4B +0x094 HalReserved : [16] Uint4B +0x0d4 InterruptMode : Uint4B +0x0d8 Spare1 : UChar +0x0dc KernelReserved2 : [17] Uint4B +0x120 PrcbData : _KPRCB
NtTib
我们先看第一个成员,它的结构体如下:
kd> dt _NT_TIB ntdll!_NT_TIB +0x000 ExceptionList : Ptr32 _EXCEPTION_REGISTRATION_RECORD +0x004 StackBase : Ptr32 Void +0x008 StackLimit : Ptr32 Void +0x00c SubSystemTib : Ptr32 Void +0x010 FiberData : Ptr32 Void +0x010 Version : Uint4B +0x014 ArbitraryUserPointer : Ptr32 Void +0x018 Self : Ptr32 _NT_TIB
ExceptionList
存储当前线程内核异常链表,简称
SEH。
StackBase / StackLimit
存储当前线程内核栈的基址和大小。
Self
指向自己的指针,也就是指向
KPCR结构,这样设计的目的是为了查找方便,只需要一个偏移就能知道自己的地址。
SelfPcr
指向自己,方便寻址。
Prcb
指向拓展结构体
PRCB的地址。
IDT
指向
IDT表基址。
GDT
指向
GDT表基址。
TSS
指向
TSS的指针,每个
CPU都有一个
TSS。
Number
CPU编号,从0开始索引。
PrcbData
拓展结构体,它是结构体如下所示:
kd> dt _KPRCB ntdll!_KPRCB +0x000 MinorVersion : Uint2B +0x002 MajorVersion : Uint2B +0x004 CurrentThread : Ptr32 _KTHREAD +0x008 NextThread : Ptr32 _KTHREAD +0x00c IdleThread : Ptr32 _KTHREAD +0x010 Number : Char +0x011 Reserved : Char +0 ad8 x012 BuildType : Uint2B +0x014 SetMember : Uint4B +0x018 CpuType : Char +0x019 CpuID : Char +0x01a CpuStep : Uint2B +0x01c ProcessorState : _KPROCESSOR_STATE +0x33c KernelReserved : [16] Uint4B +0x37c HalReserved : [16] Uint4B +0x3bc PrcbPad0 : [92] UChar +0x418 LockQueue : [16] _KSPIN_LOCK_QUEUE +0x498 PrcbPad1 : [8] UChar +0x4a0 NpxThread : Ptr32 _KTHREAD +0x4a4 InterruptCount : Uint4B +0x4a8 KernelTime : Uint4B +0x4ac UserTime : Uint4B +0x4b0 DpcTime : Uint4B +0x4b4 DebugDpcTime : Uint4B +0x4b8 InterruptTime : Uint4B +0x4bc AdjustDpcThreshold : Uint4B +0x4c0 PageColor : Uint4B +0x4c4 SkipTick : Uint4B +0x4c8 MultiThreadSetBusy : UChar +0x4c9 Spare2 : [3] UChar +0x4cc ParentNode : Ptr32 _KNODE +0x4d0 MultiThreadProcessorSet : Uint4B +0x4d4 MultiThreadSetMaster : Ptr32 _KPRCB +0x4d8 ThreadStartCount : [2] Uint4B +0x4e0 CcFastReadNoWait : Uint4B +0x4e4 CcFastReadWait : Uint4B +0x4e8 CcFastReadNotPossible : Uint4B +0x4ec CcCopyReadNoWait : Uint4B +0x4f0 CcCopyReadWait : Uint4B +0x4f4 CcCopyReadNoWaitMiss : Uint4B +0x4f8 KeAlignmentFixupCount : Uint4B +0x4fc KeContextSwitches : Uint4B +0x500 KeDcacheFlushCount : Uint4B +0x504 KeExceptionDispatchCount : Uint4B +0x508 KeFirstLevelTbFills : Uint4B +0x50c KeFloatingEmulationCount : Uint4B +0x510 KeIcacheFlushCount : Uint4B +0x514 KeSecondLevelTbFills : Uint4B +0x518 KeSystemCalls : Uint4B +0x51c SpareCounter0 : [1] Uint4B +0x520 PPLookasideList : [16] _PP_LOOKASIDE_LIST +0x5a0 PPNPagedLookasideList : [32] _PP_LOOKASIDE_LIST +0x6a0 PPPagedLookasideList : [32] _PP_LOOKASIDE_LIST +0x7a0 PacketBarrier : Uint4B +0x7a4 ReverseStall : Uint4B +0x7a8 IpiFrame : Ptr32 Void +0x7ac PrcbPad2 : [52] UChar +0x7e0 CurrentPacket : [3] Ptr32 Void +0x7ec TargetSet : Uint4B +0x7f0 WorkerRoutine : Ptr32 void +0x7f4 IpiFrozen : Uint4B +0x7f8 PrcbPad3 : [40] UChar +0x820 RequestSummary : Uint4B +0x824 SignalDone : Ptr32 _KPRCB +0x828 PrcbPad4 : [56] UChar +0x860 DpcListHead : _LIST_ENTRY +0x868 DpcStack : Ptr32 Void +0x86c DpcCount : Uint4B +0x870 DpcQueueDepth : Uint4B +0x874 DpcRoutineActive : Uint4B +0x878 DpcInterruptRequested : Uint4B +0x87c DpcLastCount : Uint4B +0x880 DpcRequestRate : Uint4B +0x884 MaximumDpcQueueDepth : Uint4B +0x888 MinimumDpcRate : Uint4B +0x88c QuantumEnd : Uint4B +0x890 PrcbPad5 : [16] UChar +0x8a0 Dpc 2080 Lock : Uint4B +0x8a4 PrcbPad6 : [28] UChar +0x8c0 CallDpc : _KDPC +0x8e0 ChainedInterruptList : Ptr32 Void +0x8e4 LookasideIrpFloat : Int4B +0x8e8 SpareFields0 : [6] Uint4B +0x900 VendorString : [13] UChar +0x90d InitialApicId : UChar +0x90e LogicalProcessorsPerPhysicalProcessor : UChar +0x910 MHz : Uint4B +0x914 FeatureBits : Uint4B +0x918 UpdateSignature : _LARGE_INTEGER +0x920 NpxSaveArea : _FX_SAVE_AREA +0xb30 PowerState : _PROCESSOR_POWER_STATE
CurrentThread
指向当前线程结构体指针。
NextThread
指向即将切换的下一个线程结构体指针。
CurrentThread
指向空闲线程的指针。
本节练习
本节的答案将会在下一节进行讲解,务必把本节练习做完后看下一个讲解内容。不要偷懒,实验是学习本教程的捷径。
俗话说得好,光说不练假把式,如下是本节相关的练习。如果练习没做好,就不要看下一节教程了,越到后面,不做练习的话容易夹生了,开始还明白,后来就真的一点都不明白了。本节练习较多,请保质保量的完成。
1️⃣ 断链进程结构体,实现隐藏,并思考为什么断链进程为什么还能够执行。
2️⃣ 使用
DebugPort清零实现反调试。
3️⃣ 如何判断一个进程是否为
GUI线程。
4️⃣ 断链线程结构体,实现隐藏,并思考为什么断链线程为什么还能够执行。
下一篇
进程线程篇——线程切换(上)
- linux进程、线程常用的几个基础知识点
- java基础——进程和线程
- 【Java基础_(线程篇_第一篇)】继承Thread;实现runnable;sleep、wait用法和区别;Thread和Runnable区别;线程停止
- 遗忘的基础概念——并发、并行、进程、线程
- 30 张图带你分分钟看懂进程和线程基础知识全家桶
- 【java基础】Java 中的进程与线程
- Java多线程基础:进程和线程之由来
- python基础语法补充:线程、进程与窗口编程
- Python基础—线程、进程和协程
- 编程基础(一):进程,线程和协程
- Java多线程基础:进程和线程之由来
- 易语言关于程序进程和线程的基础知识
- python基础--进程,线程,协程对比
- 001-线程基础-进程线程、线程状态、优先级、用户线程和守护线程
- Python基础进程和线程
- java基础(六)之java进程与线程最全总结
- 【幻化万千戏红尘】qianfengDay21-java基础学习:进程、线程、Timer
- C# WinForm基础二 控件、对话框类、容器、进程、线程
- python基础-线程和进程
- 【Java基础】线程和进程