内核[一] X64 HideFromDebugger分析 & 对抗

ThreadHideFromDebugger

Baklib
狐白 最后一次编辑 3 年多前
484
当调试器出现以上这种情况时,说明程序调用NtSetInformationThread-ThreadHideFromDebugger
NTSTATUSNTAPINtSetInformationThread(_In_ HANDLEThreadHandle,
_In_ THREADINFOCLASS ThreadInformationClass,
_In_reads_bytes_(ThreadInformationLength) PVOIDThreadInformation,
_In_ ULONGThreadInformationLength);
这个函数可以让调试器接受不到异常信息
内核代码的实现:
PS_SET_BITS (&Thread->CrossThreadFlags, PS_CROSS_THREAD_FLAGS_HIDEFROMDBG);
内核对PS_CROSS_THREAD_FLAGS_HIDEFROMDBG的处理:
if(DebugException) {
if(PsGetCurrentThread()->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_HIDEFROMDBG) {
DebugPort = NULL;
else{
DebugPort = Process->DebugPort;
}
在ETHREAD的结构中
kd> dt _ETHREAD ntdll!_ETHREAD +0x000 Tcb : _KTHREAD +0x360 CreateTime : _LARGE_INTEGER +0x368 ExitTime : _LARGE_INTEGER +0x368 KeyedWaitChain : _LIST_ENTRY +0x378 ExitStatus : Int4B +0x380 PostBlockList : _LIST_ENTRY +0x380 ForwardLinkShadow : Ptr64 Void +0x388 StartAddress : Ptr64 Void +0x390 TerminationPort : Ptr64 _TERMINATION_PORT +0x390 ReaperLink : Ptr64 _ETHREAD +0x390 KeyedWaitValue : Ptr64 Void +0x398 ActiveTimerListLock : Uint8B +0x3a0 ActiveTimerListHead : _LIST_ENTRY +0x3b0 Cid : _CLIENT_ID +0x3c0 KeyedWaitSemaphore : _KSEMAPHORE +0x3c0 AlpcWaitSemaphore : _KSEMAPHORE +0x3e0 ClientSecurity : _PS_CLIENT_SECURITY_CONTEXT +0x3e8 IrpList : _LIST_ENTRY +0x3f8 TopLevelIrp : Uint8B +0x400 DeviceToVerify : Ptr64 _DEVICE_OBJECT +0x408 CpuQuotaApc : Ptr64 _PSP_CPU_QUOTA_APC +0x410 Win32StartAddress : Ptr64 Void +0x418 LegacyPowerObject : Ptr64 Void +0x420 ThreadListEntry : _LIST_ENTRY +0x430 RundownProtect : _EX_RUNDOWN_REF +0x438 ThreadLock : _EX_PUSH_LOCK +0x440 ReadClusterSize : Uint4B +0x444 MmLockOrdering : Int4B +0x448 CrossThreadFlags : Uint4B +0x448 Terminated : Pos 0, 1 Bit +0x448 ThreadInserted : Pos 1, 1 Bit +0x448 HideFromDebugger : Pos 2, 1 Bit +0x448 ActiveImpersonationInfo : Pos 3, 1 Bit +0x448 Reserved : Pos 4, 1 Bit +0x448 HardErrorsAreDisabled : Pos 5, 1 Bit +0x448 BreakOnTermination : Pos 6, 1 Bit +0x448 SkipCreationMsg : Pos 7, 1 Bit +0x448 SkipTerminationMsg : Pos 8, 1 Bit +0x448 CopyTokenOnOpen : Pos 9, 1 Bit +0x448 ThreadIoPriority : Pos 10, 3 Bits +0x448 ThreadPagePriority : Pos 13, 3 Bits +0x448 RundownFail : Pos 16, 1 Bit +0x448 NeedsWorkingSetAging : Pos 17, 1 Bit +0x44c SameThreadPassiveFlags : Uint4B +0x44c ActiveExWorker : Pos 0, 1 Bit +0x44c ExWorkerCanWaitUser : Pos 1, 1 Bit +0x44c MemoryMaker : Pos 2, 1 Bit +0x44c ClonedThread : Pos 3, 1 Bit +0x44c KeyedEventInUse : Pos 4, 1 Bit +0x44c RateApcState : Pos 5, 2 Bits +0x44c SelfTerminate : Pos 7, 1 Bit +0x450 SameThreadApcFlags : Uint4B +0x450 Spare : Pos 0, 1 Bit +0x450 StartAddressInvalid : Pos 1, 1 Bit +0x450 EtwPageFaultCalloutActive : Pos 2, 1 Bit +0x450 OwnsProcessWorkingSetExclusive : Pos 3, 1 Bit +0x450 OwnsProcessWorkingSetShared : Pos 4, 1 Bit +0x450 OwnsSystemCacheWorkingSetExclusive : Pos 5, 1 Bit +0x450 OwnsSystemCacheWorkingSetShared : Pos 6, 1 Bit +0x450 OwnsSessionWorkingSetExclusive : Pos 7, 1 Bit +0x451 OwnsSessionWorkingSetShared : Pos 0, 1 Bit +0x451 OwnsProcessAddressSpaceExclusive : Pos 1, 1 Bit +0x451 OwnsProcessAddressSpaceShared : Pos 2, 1 Bit +0x451 SuppressSymbolLoad : Pos 3, 1 Bit +0x451 Prefetching : Pos 4, 1 Bit +0x451 OwnsDynamicMemoryShared : Pos 5, 1 Bit +0x451 OwnsChangeControlAreaExclusive : Pos 6, 1 Bit +0x451 OwnsChangeControlAreaShared : Pos 7, 1 Bit +0x452 OwnsPagedPoolWorkingSetExclusive : Pos 0, 1 Bit +0x452 OwnsPagedPoolWorkingSetShared : Pos 1, 1 Bit +0x452 OwnsSystemPtesWorkingSetExclusive : Pos 2, 1 Bit +0x452 OwnsSystemPtesWorkingSetShared : Pos 3, 1 Bit +0x452 TrimTrigger : Pos 4, 2 Bits +0x452 Spare1 : Pos 6, 2 Bits +0x453 PriorityRegionActive : UChar +0x454 CacheManagerActive : UChar +0x455 DisablePageFaultClustering : UChar +0x456 ActiveFaultCount : UChar +0x457 LockOrderState : UChar +0x458 AlpcMessageId : Uint8B +0x460 AlpcMessage : Ptr64 Void +0x460 AlpcReceiveAttributeSet : Uint4B +0x468 AlpcWaitListEntry : _LIST_ENTRY +0x478 CacheManagerCount : Uint4B +0x47c IoBoostCount : Uint4B +0x480 IrpListLock : Uint8B +0x488 ReservedForSynchTracking : Ptr64 Void +0x490 CmCallbackListHead : _SINGLE_LIST_ENTRY
HideFromDebugger可以说是主要判断目标
那么现在就很简单了 我们可以对目标线程的HideFromDebugger中的值设置为0
这样调试器就会正常工作了
But 如果驱动检测ETHREAD HideFromDebugger中的值那么还是会gg的
我们可以从内核调试函数入手
if(PsGetCurrentThread()->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_HIDEFROMDBG)
PATCH这个跳转
如:DbgkForwardException
kd> uf DbgkForwardException nt!DbgkForwardException: fffff800`04764678 488bc4 mov rax,rsp fffff800`0476467b 48895808 mov qword ptr [rax+8],rbx fffff800`0476467f 48896810 mov qword ptr [rax+10h],rbp fffff800`04764683 48897018 mov qword ptr [rax+18h],rsi fffff800`04764687 48897820 mov qword ptr [rax+20h],rdi fffff800`0476468b 4154 push r12 fffff800`0476468d 4881ec30010000 sub rsp,130h fffff800`04764694 8364244800 and dword ptr [rsp+48h],0 fffff800`04764699 c7442420a800d000 mov dword ptr [rsp+20h],0D000A8h fffff800`047646a1 c744242408000000 mov dword ptr [rsp+24h],8 fffff800`047646a9 65488b042588010000 mov rax,qword ptr gs:[188h] fffff800`047646b2 4c8be1 mov r12,rcx fffff800`047646b5 418ae8 mov bpl,r8b fffff800`047646b8 488b4870 mov rcx,qword ptr [rax+70h] fffff800`047646bc 408afa mov dil,dl fffff800`047646bf 80fa01 cmp dl,1 fffff800`047646c2 0f85d8c60700 jne nt! ?? ::NNGAKEGL::`string'+0x35d67 (fffff800`047e0da0) Branch nt!DbgkForwardException+0x50: fffff800`047646c8 65488b042588010000 mov rax,qword ptr gs:[188h] fffff800`047646d1 f6804804000004 test byte ptr [rax+448h],4 fffff800`047646d8 0f85bbc60700 jne nt! ?? ::NNGAKEGL::`string'+0x35d60 (fffff800`047e0d99) Branch nt!DbgkForwardException+0x66: fffff800`047646de 488b99f0010000 mov rbx,qword ptr [rcx+1F0h] nt!DbgkForwardException+0x6d: fffff800`047646e5 4032f6 xor sil,sil nt!DbgkForwardException+0x70: fffff800`047646e8 4885db test rbx,rbx fffff800`047646eb 0f85c7c60700 jne nt! ?? ::NNGAKEGL::`string'+0x35d7f (fffff800`047e0db8) Branch nt!DbgkForwardException+0x79: fffff800`047646f1 4080ff01 cmp dil,1 fffff800`047646f5 0f85bdc60700 jne nt! ?? ::NNGAKEGL::`string'+0x35d7f (fffff800`047e0db8) Branch nt!DbgkForwardException+0x83: fffff800`047646fb 32c0 xor al,al nt!DbgkForwardException+0x85: fffff800`047646fd 4c8d9c2430010000 lea r11,[rsp+130h] fffff800`04764705 498b5b10 mov rbx,qword ptr [r11+10h] fffff800`04764709 498b6b18 mov rbp,qword ptr [r11+18h] fffff800`0476470d 498b7320 mov rsi,qword ptr [r11+20h] fffff800`04764711 498b7b28 mov rdi,qword ptr [r11+28h] fffff800`04764715 498be3 mov rsp,r11 fffff800`04764718 415c pop r12 fffff800`0476471a c3 ret nt! ?? ::NNGAKEGL::`string'+0x35d60: fffff800`047e0d99 33db xor ebx,ebx fffff800`047e0d9b e94539f8ff jmp nt!DbgkForwardException+0x6d (fffff800`047646e5) Branch nt! ?? ::NNGAKEGL::`string'+0x35d67: fffff800`047e0da0 e8df39f9ff call nt!PsCaptureExceptionPort (fffff800`04774784) fffff800`047e0da5 c744242407000000 mov dword ptr [rsp+24h],7 fffff800`047e0dad 40b601 mov sil,1 fffff800`047e0db0 488bd8 mov rbx,rax fffff800`047e0db3 e93039f8ff jmp nt!DbgkForwardException+0x70 (fffff800`047646e8) Branch nt! ?? ::NNGAKEGL::`string'+0x35d7f: fffff800`047e0db8 488d4c2450 lea rcx,[rsp+50h] fffff800`047e0dbd 498bd4 mov rdx,r12 fffff800`047e0dc0 41b898000000 mov r8d,98h fffff800`047e0dc6 e82552cbff call nt!memmove (fffff800`04495ff0) fffff800`047e0dcb 4533db xor r11d,r11d fffff800`047e0dce 4084ed test bpl,bpl fffff800`047e0dd1 410f94c3 sete r11b fffff800`047e0dd5 bd01000180 mov ebp,80010001h fffff800`047e0dda 44899c24e8000000 mov dword ptr [rsp+0E8h],r11d fffff800`047e0de2 4080fe01 cmp sil,1 fffff800`047e0de6 752b jne nt! ?? ::NNGAKEGL::`string'+0x35dda (fffff800`047e0e13) Branch nt! ?? ::NNGAKEGL::`string'+0x35daf: fffff800`047e0de8 4885db test rbx,rbx fffff800`047e0deb 741c je nt! ?? ::NNGAKEGL::`string'+0x35dd0 (fffff800`047e0e09) Branch nt! ?? ::NNGAKEGL::`string'+0x35db4: fffff800`047e0ded 488d4c2420 lea rcx,[rsp+20h] fffff800`047e0df2 448ac7 mov r8b,dil fffff800`047e0df5 488bd3 mov rdx,rbx fffff800`047e0df8 e883cf0a00 call nt!DbgkpSendApiMessageLpc (fffff800`0488dd80) fffff800`047e0dfd 488bcb mov rcx,rbx fffff800`047e0e00 8bf0 mov esi,eax fffff800`047e0e02 e83986ccff call nt!ObfDereferenceObject (fffff800`044a9440) fffff800`047e0e07 eb1f jmp nt! ?? ::NNGAKEGL::`string'+0x35def (fffff800`047e0e28) Branch nt! ?? ::NNGAKEGL::`string'+0x35dd0: fffff800`047e0e09 8bc5 mov eax,ebp fffff800`047e0e0b 33f6 xor esi,esi fffff800`047e0e0d 8944244c mov dword ptr [rsp+4Ch],eax fffff800`047e0e11 eb19 jmp nt! ?? ::NNGAKEGL::`string'+0x35df3 (fffff800`047e0e2c) Branch nt! ?? ::NNGAKEGL::`string'+0x35dda: fffff800`047e0e13 33c9 xor ecx,ecx fffff800`047e0e15 4080ff01 cmp dil,1 fffff800`047e0e19 488d542420 lea rdx,[rsp+20h] fffff800`047e0e1e 0f94c1 sete cl fffff800`047e0e21 e8dad90500 call nt!DbgkpSendApiMessage (fffff800`0483e800) fffff800`047e0e26 8bf0 mov esi,eax nt! ?? ::NNGAKEGL::`string'+0x35def: fffff800`047e0e28 8b44244c mov eax,dword ptr [rsp+4Ch] nt! ?? ::NNGAKEGL::`string'+0x35df3: fffff800`047e0e2c 85f6 test esi,esi fffff800`047e0e2e 0f88c738f8ff js nt!DbgkForwardException+0x83 (fffff800`047646fb) Branch nt! ?? ::NNGAKEGL::`string'+0x35dfb: fffff800`047e0e34 3bc5 cmp eax,ebp fffff800`047e0e36 7519 jne nt! ?? ::NNGAKEGL::`string'+0x35e18 (fffff800`047e0e51) Branch nt! ?? ::NNGAKEGL::`string'+0x35dff: fffff800`047e0e38 4080ff01 cmp dil,1 fffff800`047e0e3c 0f84b938f8ff je nt!DbgkForwardException+0x83 (fffff800`047646fb) Branch nt! ?? ::NNGAKEGL::`string'+0x35e09: fffff800`047e0e42 4c8d442420 lea r8,[rsp+20h] fffff800`047e0e47 33d2 xor edx,edx fffff800`047e0e49 498bcc mov rcx,r12 fffff800`047e0e4c e81fc90a00 call nt!DbgkpSendErrorMessage (fffff800`0488d770) nt! ?? ::NNGAKEGL::`string'+0x35e18: fffff800`047e0e51 85c0 test eax,eax fffff800`047e0e53 0f99c0 setns al fffff800`047e0e56 e9a238f8ff jmp nt!DbgkForwardException+0x85 (fffff800`047646fd) Branch
fffff800`047646d1 f6804804000004 test byte ptr [rax+448h],4(rax为ETHREAD)
fffff800`047646d8 0f85bbc60700 jne nt! ?? ::NNGAKEGL::`string'+0x35d60 (fffff800`047e0d99) Branch
这里就是判断了
我们可以直接nop fffff800`047646d8 这样就可以不修改HideFromDebugger的情况下让调试器正常工作