- 注册时间
- 2011-3-6
- 最后登录
- 1970-1-1
该用户从未签到
|
- 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->sSuspendProcess->sSuspendThread->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: NtSuspendProcess(x)+37j
- PAGE:006D518E mov eax, esi
- PAGE:006D5190 pop esi
- PAGE:006D5191 leave
- PAGE:006D5192 retn 4
- PAGE:006D5192 _NtSuspendProcess@4 endp
复制代码
调用ObreferenceObjectByHandle获取EPROCESS
然后调用PsSuspendProcess- NTSTATUS __stdcall NtSuspendProcess(HANDLE Handle)
- {
- NTSTATUS v1; // esi@1
- PVOID Object; // [sp+8h] [bp-4h]@1
- v1 = ObReferenceObjectByHandle(Handle, 0x800u, PsProcessType, KeGetCurrentThread()->PreviousMode, &Object, 0);
- if ( v1 >= 0 )
- {
- v1 = PsSuspendProcess((PEPROCESS)Object);
- ObfDereferenceObject(Object);
- }
- return v1;
- }
复制代码
PsSuspendProcess 先看看RundownProtect是否有效
据我所知,这个结构是为了防止windows在操作过程中防止进程/线程退出 从返回0xC0000010A可以很明显的知道
如果将此结构置1 有保护进程的作用
然后通过PsGetNextProcessThread获得进程的全部线程 然后分别调用PsSuspendThread暂停- // PsSuspendProcess(PERPCOESS pProcessObject)
- int __stdcall PsSuspendProcess(PEPROCESS pEprocess)
- {
- _KTHREAD *v1; // esi@1
- volatile signed __int32 *v2; // edi@1
- signed __int32 v3; // ecx@1
- int i; // eax@3
- void *v5; // ebx@5
- signed __int32 v6; // ecx@6
- int v7; // edi@8
- v1 = KeGetCurrentThread();
- --v1->KernelApcDisable;
- v2 = (volatile signed __int32 *)&pEprocess->RundownProtect;
- v3 = pEprocess->RundownProtect.Count & 0xFFFFFFFE;
- if ( _InterlockedCompareExchange((volatile signed __int32 *)&pEprocess->RundownProtect, v3 + 2, v3) != v3
- && ExfAcquireRundownProtection(v2) != 1 )
- {
- v7 = 0xC000010A;//进程已退出
- }
- else
- {
- for ( i = PsGetNextProcessThread((int)pEprocess, 0); ; i = PsGetNextProcessThread((int)pEprocess, v5) )
- {
- v5 = (void *)i;
- if ( !i )
- break;
- PsSuspendThread((_ETHREAD *)i, 0);
- }
- v6 = *v2 & 0xFFFFFFFE;
- if ( _InterlockedCompareExchange(v2, v6 - 2, v6) != v6 )
- ExfReleaseRundownProtection(v2);
- v7 = 0;
- }
- ++v1->KernelApcDisable;
- if ( !v1->KernelApcDisable
- && ($0453357706F129727BD247106FA17C54 *)v1->ApcState.ApcListHead[0].Flink != &v1->64
- && !v1->SpecialApcDisable )
- KiCheckForKernelApcDelivery();
- return v7;
- }
复制代码 PsSuspendThread
跟Process的操作差不多
这里可以发现如果我们将pEthead->CrossThreadFlags置0 也可以防止挂起
不过这不是主题...- // PsSuspendThread(PETHREAD,OUT orgCount)
- unsigned int __stdcall PsSuspendThread(_ETHREAD *ThreadObject, int a2)
- {
- _KTHREAD *v2; // esi@1
- signed __int32 v3; // edx@1
- signed __int32 v4; // edx@7
- int v6; // [sp+18h] [bp-20h]@1
- unsigned int v7; // [sp+1Ch] [bp-1Ch]@4
- v6 = 0;
- v2 = KeGetCurrentThread();
- --v2->KernelApcDisable;
- v3 = (unsigned int)ThreadObject->RundownProtect & 0xFFFFFFFE;
- if ( _InterlockedCompareExchange((volatile signed __int32 *)&ThreadObject->RundownProtect, v3 + 2, v3) != v3
- && !ExfAcquireRundownProtection((volatile signed __int32 *)&ThreadObject->RundownProtect) )
- {
- v7 = 0xC000004B;//线程退出
- goto LABEL_10;
- }
- if ( !(ThreadObject->CrossThreadFlags & 1) )
- {
- v6 = KeSuspendThread(ThreadObject);
- v7 = 0;
- if ( !(ThreadObject->CrossThreadFlags & 1) )
- goto LABEL_7;
- KeForceResumeThread((int)ThreadObject);
- v6 = 0;
- }
- v7 = 0xC000004B;//线程退出
- LABEL_7:
- v4 = (unsigned int)ThreadObject->RundownProtect & 0xFFFFFFFE;
- if ( _InterlockedCompareExchange((volatile signed __int32 *)&ThreadObject->RundownProtect, v4 - 2, v4) != v4 )
- ExfReleaseRundownProtection(&ThreadObject->RundownProtect);
- LABEL_10:
- ++v2->KernelApcDisable;
- if ( !v2->KernelApcDisable
- && ($0453357706F129727BD247106FA17C54 *)v2->ApcState.ApcListHead[0].Flink != &v2->64
- && !v2->SpecialApcDisable )
- KiCheckForKernelApcDelivery();
- if ( a2 )
- *(_DWORD *)a2 = v6;
- return v7;
- }
复制代码
KeSuspendThread:
这下面大部分操作都在KTHREAD结构下
这里又发现可以保护线程的ThreadFlags~20 andFreezeCount >1 andSuspendApc.Inserted != 1
这不是主题...
++m_ThreadObject->SuspendCount;//这句才是重点
暂停一次这个+1- int __usercall KeSuspendThread@<eax>(_KTHREAD *ThreadObject@<eax>)
- {
- _KTHREAD *m_ThreadObject; // esi@1
- char *v2; // ebx@1
- volatile signed __int32 *v3; // edi@1
- int v4; // eax@8
- int v5; // esi@15
- unsigned __int32 v7; // [sp+Ch] [bp-Ch]@1
- KIRQL NewIrql; // [sp+10h] [bp-8h]@1
- int v9; // [sp+14h] [bp-4h]@1
- int v10; // [sp+14h] [bp-4h]@8
- m_ThreadObject = ThreadObject;
- v2 = (char *)&ThreadObject->SuspendSemaphore.SuspendSemaphore.Header.0;
- v9 = 0;
- NewIrql = KeRaiseIrqlToDpcLevel();
- v7 = __readfsdword(32);
- v3 = (volatile signed __int32 *)&m_ThreadObject->ApcQueueLock;
- while ( _InterlockedExchange(v3, 1) )
- {
- do
- {
- ++v9;
- if ( v9 & HvlLongSpinCountMask || !(HvlEnlightenments & 0x40) )
- _mm_pause();
- else
- HvlNotifyLongSpinWait(v9);
- }
- while ( *v3 );
- }
- v4 = m_ThreadObject->SuspendCount;
- v10 = v4;
- if ( v4 == 0x7F )
- {
- _InterlockedAnd(v3, 0);
- KfLowerIrql(NewIrql);
- RtlRaiseStatus(0xC000004A);
- }
- if ( m_ThreadObject->ThreadFlags & 0x20 )
- {
- ++m_ThreadObject->SuspendCount;//这句很重要
- if ( !v4 && !m_ThreadObject->FreezeCount )
- {
- if ( m_ThreadObject->SuspendApc.Inserted == 1 )
- {
- v5 = 0;
- while ( _interlockedbittestandset((volatile signed __int32 *)v2, 7u) )
- {
- do
- {
- ++v5;
- if ( v5 & HvlLongSpinCountMask || !(HvlEnlightenments & 0x40) )
- _mm_pause();
- else
- HvlNotifyLongSpinWait(v5);
- }
- while ( (char)*(_DWORD *)v2 < 0 );
- }
- --*((_DWORD *)v2 + 1);
- _InterlockedAnd((volatile signed __int32 *)v2, 0xFFFFFF7F);
- }
- else
- {
- m_ThreadObject->SuspendApc.Inserted = 1;
- KiInsertQueueApc(NewIrql);
- }
- }
- }
- _InterlockedAnd(v3, 0);
- KiExitDispatcher(v7, 0, 1, 0, NewIrql);
- return v10;
- }
复制代码 来看下恢复的
直接看KeResumeThread
重点看这句
if ( m_pThreadObject->SuspendCount ) // 如果暂停数大于0
暂停数大于0就准备下一步操作
这里我们用来判断这个线程/进程有没有被挂起- int __usercall KeResumeThread@<eax>(_ETHREAD *pThreadObject@<eax>)
- {
- _KTHREAD *m_pThreadObject; // esi@1
- char *v2; // edi@1
- volatile signed __int32 *v3; // ebx@1
- char m_last_count; // cl@9
- int v5; // esi@11
- KIRQL NewIrql; // [sp+Ch] [bp-Ch]@1
- unsigned __int32 v8; // [sp+10h] [bp-8h]@1
- int v9; // [sp+14h] [bp-4h]@1
- int ret_OrgSuspendCount; // [sp+14h] [bp-4h]@8
- m_pThreadObject = (_KTHREAD *)pThreadObject;
- v2 = &pThreadObject->gap_0[offsetof(_KTHREAD, SuspendSemaphore)];
- v9 = 0;
- NewIrql = KeRaiseIrqlToDpcLevel();
- v8 = __readfsdword(32);
- v3 = (volatile signed __int32 *)&m_pThreadObject->ApcQueueLock;
- while ( _InterlockedExchange(v3, 1) )
- {
- do
- {
- ++v9;
- if ( v9 & HvlLongSpinCountMask || !(HvlEnlightenments & 0x40) )
- _mm_pause();
- else
- HvlNotifyLongSpinWait(v9);
- }
- while ( *v3 );
- }
- ret_OrgSuspendCount = m_pThreadObject->SuspendCount;
- if ( m_pThreadObject->SuspendCount ) // 如果暂停数大于0
- {
- m_last_count = m_pThreadObject->SuspendCount - 1;// -1
- m_pThreadObject->SuspendCount = m_last_count;
- if ( !m_last_count && !m_pThreadObject->FreezeCount )
- {
- v5 = 0;
- while ( _interlockedbittestandset((volatile signed __int32 *)v2, 7u) )
- {
- do
- {
- ++v5;
- if ( v5 & HvlLongSpinCountMask || !(HvlEnlightenments & 0x40) )
- _mm_pause();
- else
- HvlNotifyLongSpinWait(v5);
- }
- while ( (char)*(_DWORD *)v2 < 0 );
- }
- ++*((_DWORD *)v2 + 1);
- KiSignalSynchronizationObject(v8, v2);
- _InterlockedAnd((volatile signed __int32 *)v2, 0xFFFFFF7F);
- }
- }
- _InterlockedAnd(v3, 0);
- KiExitDispatcher(v8, 0, 1, 0, NewIrql);
- return ret_OrgSuspendCount;
- }
复制代码 这也是Pchunter判断的方法,别问我怎么知道的.... |
|