全局概览:
典型的用户态调试程序流程:
CreateProcess(…)
DEBUG_EVENT DebugEv;
DWORD dwContinueStatus = DBG_CONTINUE;
while(true)
{
WaitForDebugEvent(&DebugEv, INFINITE);
dwContinueStatus = DebugEventHandler(&DebugEv);
ContinueDebugEvent(DebugEv.dwProcessId,
DebugEv.dwThreadId, dwContinueStatus);
}
7C9720AE mov edi,edi
7C9720B0 push ebp
7C9720B1 mov ebp,esp
7C9720B3 mov eax,fs:[00000018];teb
7C9720B9 push dword ptr [ebp+8]
7C9720BC push dword ptr [ebp+0Ch]
7C9720BF push 1
7C9720C1 push dword ptr [eax+0F24h] ; teb.DbgSsReserved[1]保存调试对象句柄
7C819279 F645 20 03 test byte ptr ss:[ebp+20],3; DEBUG_PROCESS |DEBUG_ONLY_THIS_PROCESS
7C81927D 0F85 049C0200 jnz kernel32.7C842E87 ;标志不为0 则跳转
…
…
7C842E87 E8 36DB0300 call <jmp.&ntdll.DbgUiConnectToDbg>
7C972034 64:A1 18000000 mov eax,dword ptr fs:[18] ;取teb
7C97203A 3988 240F0000 cmp dword ptr ds:[eax+F24],ecx ; DbgSsReserved[1]
7C972040 75 34 jnz short ntdll.7C972076 ;不为空则不创建
7C972042 C745 E8 18000000 mov dword ptr ss:[ebp-18],18
7C972049 894D EC mov dword ptr ss:[ebp-14],ecx
7C97204C 894D F4 mov dword ptr ss:[ebp-C],ecx
7C97204F 894D F0 mov dword ptr ss:[ebp-10],ecx
7C972052 894D F8 mov dword ptr ss:[ebp-8],ecx
7C972055 894D FC mov dword ptr ss:[ebp-4],ecx
7C972058 64:A1 18000000 mov eax,dword ptr fs:[18]
7C97205E 6A 01 push 1 ;flag DEBUG_KILL_ON_CLOSE
7C972060 8D4D E8 lea ecx,dword ptr ss:[ebp-18]
7C972063 51 push ecx ; IN POBJECT_ATTRIBUTES ObjectAttributes
7C972064 68 0F001F00 push 1F000F ; IN ACCESS_MASK DesiredAccess
7C972069 05 240F0000 add eax,0F24 ;& teb.DbgSsReserved[1]
7C97206E 50 push eax ; OUT PHANDLE DebugObjectHandle
7C97206F E8 FAAFFBFF call ntdll.ZwCreateDebugObject;进入内核函数nt!NtCreateDebugObject
7C972074 8BC8 mov ecx,eax
7C972076 8BC1 mov eax,ecx
7C972078 C9 leave
7C972079 C3 retn
8063a701 8d45dc lea eax,[ebp-24h]
8063a704 50 push eax
8063a705 53 push ebx
8063a706 53 push ebx
8063a707 6a3c push 3Ch
8063a709 53 push ebx
8063a70a ff75e0 push dword ptr [ebp-20h]
8063a70d ff7510 push dword ptr [ebp+10h]
8063a710 ff35c0105580 push dword ptr [nt!DbgkDebugObjectType (805510c0)]
8063a716 ff75e0 push dword ptr [ebp-20h]
8063a719 e8c0d7f7ff call nt!ObCreateObject (805b7ede)
….
….
创建调试事件句柄:
8063a76c 8d4de4 lea ecx,[ebp-1Ch]
8063a76f 51 push ecx ; Handle
8063a770 53 push ebx ; NewObject
8063a771 53 push ebx ; ObjectPointerBias
8063a772 ff750c push dword ptr [ebp+0Ch] ; DesiredAccess
8063a775 53 push ebx ; AccessState
8063a776 50 push eax ; Object
8063a777 e8dcf4f7ff call nt!ObInsertObject (805b9c58)
8063a77c 3bc3 cmp eax,ebx
8063a77e 7c40 jl nt!NtCreateDebugObject+0x10e (8063a7c0)
8063a780 8975fc mov dword ptr [ebp-4],esi
8063a783 8b4de4 mov ecx,dword ptr [ebp-1Ch]
8063a786 890f mov dword ptr [edi],ecx ; 写入调试对象句柄
809317b9 ff7528 push dword ptr [ebp+28h]
809317bc ff7524 push dword ptr [ebp+24h]
809317bf ff7520 push dword ptr [ebp+20h]
809317c2 ff751c push dword ptr [ebp+1Ch]
809317c5 ff7518 push dword ptr [ebp+18h]
809317c8 ff7514 push dword ptr [ebp+14h]
809317cb ff7510 push dword ptr [ebp+10h]
809317ce ff750c push dword ptr [ebp+0Ch]
809317d1 51 push ecx
809317d2 e887eaffff call nt!PspCreateProcess (8093025e)
809303e8 6a00 push 0 ; __out_opt POBJECT_HANDLE_INFORMATION
809303ea 8d4580 lea eax,[ebp-80h]
809303ed 50 push eax ; out PVOID *Object 传出调试对象
809303ee ff75dd push dword ptr [ebp-23h] ; in KPROCESSOR_MODE AccessMode
809303f1 ff3558d18980 push dword ptr [nt!DbgkDebugObjectType (8089d158)]; in_opt POBJECT_TYPE ObjectType
809303f7 6a02 push 2 ; in ACCESS_MASK DesiredAccess
809303f9 ff7520 push dword ptr [ebp+20h] ; in HANDLE Handle 传入的handle DebugPort
809303fc e8a7fdfeff call nt!ObReferenceObjectByHandle (809201a8)
然后赋值给被调试进程eprocess结构的DebugPort
8093040b 8b4580 mov eax,dword ptr [ebp-80h] ;eprocess
8093040e 8983cc000000 mov dword ptr [ebx+0CCh],eax ; eprocess偏移0CCh为调试端口 不同操作系统不一样 我使用的是wrk
809307f6 8d83a0010000 lea eax,[ebx+1A0h] ;返回的peb
809307fc 50 push eax
809307fd 8d45c4 lea eax,[ebp-3Ch]
80930800 50 push eax
80930801 53 push ebx ;被调试进程的eprocess
80930802 e8c5d0fcff call nt!MmCreatePeb (808fd8cc)
808fd9af 33c0 xor eax,eax
808fd9b1 399ecc000000 cmp dword ptr [esi+0CCh],ebx ; 0CCh调试端口偏移,ebx为0
808fd9b7 0f95c0 setne al ;DebugPort != NULL al<-true
808fd9ba 8b4de4 mov ecx,dword ptr [ebp-1Ch] ;ecx<-peb
808fd9bd 884102 mov byte ptr [ecx+2],al ; BeingDebugged字段
8099071a 56 push esi
8099071b 8d45bc lea eax,[ebp-44h]
8099071e 50 push eax ; Out Object
8099071f ff75d8 push dword ptr [ebp-28h]
80990722 ff3558d18980 push dword ptr [nt!DbgkDebugObjectType (8089d158)]
80990728 6a01 push 1
8099072a ff7508 push dword ptr [ebp+8] ; In ObjectHandle
8099072d e876faf8ff call nt!ObReferenceObjectByHandle (809201a8)
…
8099073d 8975d0 mov dword ptr [ebp-30h],esi
80990740 8975d4 mov dword ptr [ebp-2Ch],esi
80990743 53 push ebx ;超时时间
80990744 ff750c push dword ptr [ebp+0Ch]
80990747 ff75d8 push dword ptr [ebp-28h]
8099074a 56 push esi
8099074b 57 push edi ; 调试对象的同步事件DebugObject.EventsPresent
8099074c e81967e9ff call nt!KeWaitForSingleObject (80826e6a)
80990751 8bd8 mov ebx,eax
80990753 3bde cmp ebx,esi
80990755 0f8c54010000 jl nt!NtWaitForDebugEvent+0x233 (809908af) ; NTSTATUS < 0 出错跳出返回
8099075b eb02 jmp nt!NtWaitForDebugEvent+0xe3 (8099075f)
8099075d 33f6 xor esi,esi
8099075f 81fb02010000 cmp ebx,102h ; STATUS_TIMEOUT
80990765 0f8444010000 je nt!NtWaitForDebugEvent+0x233 (809908af)
8099076b 81fb01010000 cmp ebx,101h ; STATUS_ALERTED
80990771 0f8438010000 je nt!NtWaitForDebugEvent+0x233 (809908af)
80990777 81fbc0000000 cmp ebx,0C0h STATUS_USER_APC
8099077d 0f842c010000 je nt!NtWaitForDebugEvent+0x233 (809908af)
80990783 c645e700 mov byte ptr [ebp-19h],0 ;标志是否查找到事件
80990787 8d4f10 lea ecx,[edi+10h]
8099078a e8e13ee8ff call nt!ExAcquireFastMutex (80814670)
8099078f f6473801 test byte ptr [edi+38h],1 ; DEBUG_OBJECT_DELETE_PENDING
80990793 7579 jne nt!NtWaitForDebugEvent+0x192 (8099080e) ;不是调试状态跳走
80990795 8d4730 lea eax,[edi+30h] ; DEBUG_OBJECT. EventList事件列表
80990798 8b08 mov ecx,dword ptr [eax] ; EventList.flink
8099079a eb35 jmp nt!NtWaitForDebugEvent+0x155 (809907d1)
8099079c 8bf1 mov esi,ecx
8099079e f6412c05 test byte ptr [ecx+2Ch],5 ;调试事件的状态 DEBUG_EVENT_READ|DEBUG_EVENT_INACTIVE
809907a2 7528 jne nt!NtWaitForDebugEvent+0x150 (809907cc);如果已读或者不活动的,则跳走遍历下个节点
809907a4 c645e701 mov byte ptr [ebp-19h],1 ;标志
809907a8 eb08 jmp nt!NtWaitForDebugEvent+0x136 (809907b2)
809907aa 8b5618 mov edx,dword ptr [esi+18h] ; UniqueProcess
809907ad 3b5018 cmp edx,dword ptr [eax+18h] ; UniqueProcess
809907b0 7408 je nt!NtWaitForDebugEvent+0x13e (809907ba)
809907b2 8b00 mov eax,dword ptr [eax] ;第二层循环 从链表头查找到当前的事件
809907b4 3bc1 cmp eax,ecx
809907b6 75f2 jne nt!NtWaitForDebugEvent+0x12e (809907aa)
809907b8 eb0c jmp nt!NtWaitForDebugEvent+0x14a (809907c6)
809907ba 834e2c04 or dword ptr [esi+2Ch],4 ;如果前面的事件和当前的事件的process一样 则置当前事件为不活动
809907be 83663000 and dword ptr [esi+30h],0
809907c2 c645e700 mov byte ptr [ebp-19h],0;标志
809907c6 807de700 cmp byte ptr [ebp-19h],0
809907ca 750f jne nt!NtWaitForDebugEvent+0x15f (809907db)没找到可处理的事件 继续查找
809907cc 8b09 mov ecx,dword ptr [ecx]
809907ce 8d4730 lea eax,[edi+30h]
809907d1 3bc8 cmp ecx,eax ;当前链表表不等于EventList链表头地址
809907d3 75c7 jne nt!NtWaitForDebugEvent+0x120 (8099079c) ;继续遍历
809907d5 807de700 cmp byte ptr [ebp-19h],0
809907d9 742b je nt!NtWaitForDebugEvent+0x18a (80990806)
809907db 8b5e20 mov ebx,dword ptr [esi+20h] ;eprocess
809907de 895dd0 mov dword ptr [ebp-30h],ebx
809907e1 8b4e24 mov ecx,dword ptr [esi+24h] ;ethread
809907e4 894dd4 mov dword ptr [ebp-2Ch],ecx
809907e7 e8be7fedff call nt!ObfReferenceObject (808687aa) ;解除ethread引用
809907ec 8bcb mov ecx,ebx
809907ee e8b77fedff call nt!ObfReferenceObject (808687aa) ;解除eprocess引用
809907f3 56 push esi
809907f4 8d8550ffffff lea eax,[ebp-0B0h] ;调试事件DEBUG_EVENT地址
809907fa 50 push eax
809907fb e8acfdffff call nt!DbgkpConvertKernelToUserStateChange (809905ac) ; DEBUG_EVENT转换为DBGUI_WAIT_STATE_CHANGE结构
80990800 834e2c01 or dword ptr [esi+2Ch],1 ;标志此调试对象为已读
80990804 eb04 jmp nt!NtWaitForDebugEvent+0x18e (8099080a) ;返回成功
80990806 83670400 and dword ptr [edi+4],0 ;清除调试对象
8099080a 33db xor ebx,ebx
8099080c eb05 jmp nt!NtWaitForDebugEvent+0x197 (80990813)
8099080e bb540300c0 mov ebx,0C0000354h ;不在调试状态 则返回STATUS_DEBUGGER_INACTIVE
…
…
nt!PspCreateThread:
809311a0 53 push ebx ;eprocess
809311a1 ff75e0 push dword ptr [ebp-20h] ; in_opt PVOID Teb
809311a4 50 push eax ; in_opt PCONTEXT ContextFrame
809311a5 ffb61c020000 push dword ptr [esi+21Ch] ; in_opt PVOID StartContext
809311ab 51 push ecx ; in_opt PKSTART_ROUTINE StartRoutine
809311ac 68640c9380 push offset nt!PspUserThreadStartup (80930c64) ; in PKSYSTEM_ROUTINE SystemRoutine
809311b1 51 push ecx ; in_opt PVOID KernelStack
809311b2 eb27 jmp nt!PspCreateThread+0x277 (809311db)
…
809311db 56 push esi ; __out PKTHREAD Thread
809311dc e8dbf6fbff call nt!KeInitThread (808f08bc)
80930cd6 f6864002000006 test byte ptr [esi+240h],6 //判断ethread.CrossThreadFlags
80930cdd 7509 jne nt!PspUserThreadStartup+0x84 (80930ce8)
80930cdf ff750c push dword ptr [ebp+0Ch]
80930ce2 56 push esi
80930ce3 e802070600 call nt!DbgkCreateThread (809913ea)
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课