KTHREAD的结构:
+0x16c SuspendApc : _KAPC
+0x19c SuspendSemaphore : _KSEMAPHORE
+0x1b0 ThreadListEntry : _LIST_ENTRY
+0x1b8 FreezeCount : Char
+0x1b9 SuspendCount : Char
在调用SuspendThread时,SuspendCount 自加1;如果大于0表示挂起了。调用ResumeThread时,SuspendCount 自减1;如果等于0,系统会恢复线程。
当挂起和恢复时,FreezeCount必须为0,否则挂起和恢复操作都直接pass了 .所以,可以修改 SuspendCount 和 FreezeCount来达到反挂起的目的。
证据:
应用层或内核调用ZwSuspendThread/Process
最后会执行到NtSuspendThread/Process
IDA:
以NtSuspendProcess为例子
NtSuspendProcess->PsSuspendProcess->PsSuspendThread->KeSuspendThread->
NtSuspendProcess
PAGE:006D5143 ; int __stdcall NtSuspendProcess(HANDLE Handle)
PAGE:006D5143 _NtSuspendProcess@4 proc near ; DATA XREF: .text:0045CCF4o
PAGE:006D5143
PAGE:006D5143 AccessMode = byte ptr -8
PAGE:006D5143 Object = dword ptr -4
PAGE:006D5143 Handle = dword ptr 8
PAGE:006D5143
PAGE:006D5143 mov edi, edi
PAGE:006D5145 push ebp
PAGE:006D5146 mov ebp, esp
PAGE:006D5148 push ecx
PAGE:006D5149 push ecx
PAGE:006D514A mov eax, large fs:124h
PAGE:006D5150 mov al, [eax+13Ah]
PAGE:006D5156 push esi
PAGE:006D5157 push 0 ; HandleInformation
PAGE:006D5159 mov [ebp+AccessMode], al
PAGE:006D515C lea eax, [ebp+Object]
PAGE:006D515F push eax ; Object
PAGE:006D5160 push dword ptr [ebp+AccessMode] ; AccessMode
PAGE:006D5163 push ds:_PsProcessType ; ObjectType
PAGE:006D5169 push 800h ; DesiredAccess
PAGE:006D516E push [ebp+Handle] ; Handle
PAGE:006D5171 call _ObReferenceObjectByHandle@24 ; 根据句柄获得Object
PAGE:006D5176 mov esi, eax ; mov esi pEprocess
PAGE:006D5178 test esi, esi
PAGE:006D517A jl short Exit ; 为NULL退出
PAGE:006D517C push [ebp+Object] ; pEprocess
PAGE:006D517F call _PsSuspendProcess@4 ; PsSuspendProcess(PERPCOESS pProcessObject)
PAGE:006D5184 mov ecx, [ebp+Object] ; Object
PAGE:006D5187 mov esi, eax
PAGE:006D5189 call @ObfDereferenceObject@4 ; ObfDereferenceObject(x)
PAGE:006D518E
PAGE:006D518E Exit: ; CODE XREF: NtSuspen