📄 cmd_trace.asm
字号:
VMMCall _FreeThreadDataSlot, dword [TDS]
call UnhookW32GetSetThreadContext
call UnhookGetSetThreadContext
call UnhookPMFaults
pop edi
pop ecx
pop ebx
clc
retn
;-------------------------------------------------------------------------------
; init TDS in new thread
; check if it belongs to a process one of whose threads is already being traced
; if so and multithread tracing is enabled, trace this guy as well
;
; EDI: R0TCB
;-------------------------------------------------------------------------------
TracerThreadInit:
push ebx
push ecx
push edx
push esi
push edi
push ebp
mov ecx,[TDS]
and dword [ecx+edi],byte 0
mov esi,edi ; save current R0TCB
mov ebp,[edi+TCB_ClientPtr]
call IsThreadWin32
jc near .ret
VMMCall Get_Sys_VM_Handle
VMMCall Get_Initial_Thread_Handle
mov ebx,edi
.loop:
mov ebp,[edi+TCB_ClientPtr] ; R0TCB.CRS
test byte [ebp+CRS.EFlags+2],2 ; is client in V86 mode?
jnz .next
call ShallTraceIt
jnc .trace
.next:
VMMCall Get_Next_Thread_Handle
cmp ebx,edi
jnz .loop
jmp short .ret
.trace:
xchg edi,esi
mov ebp,[edi+TCB_ClientPtr]
mov ebx,[edi+TCB_VMHandle]
cmp byte [OT.OBreaknew],'D'
jz @F
call BreakIn.ignore_range
jmp short .ret
@@
call TracerAlloc
jnc @F
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_TRACE
Trace_Out "ICEDUMP: ThreadInit: failed to allocate TraceInfo, R0TCB: #edi"
debug_end
jmp short .ret
@@
push edi
mov esi,[ecx+esi]
mov edi,[ecx+edi]
mov ecx,TraceInfo_size
rep movsb
pop edi
mov esi,[TDS]
mov esi,[esi+edi]
call TrReinforce
.ret:
pop ebp
pop edi
pop esi
pop edx
pop ecx
pop ebx
clc
retn
;-------------------------------------------------------------------------------
; decide if the new thread should be traced or not
;
; ESI: R0TCB of new thread, cannot be in V86 mode
; EDI: R0TCB of an already existing thread
;
; clc: trace it
;-------------------------------------------------------------------------------
ShallTraceIt:
push ebx
push ecx
push edx
cmp byte [OT.OTracethread],'D'
jz .check_parent
mov cx,[esi+TCB_PMPSPSelector]
cmp [edi+TCB_PMPSPSelector],cx ; same process?
jnz .check_parent
mov ecx,[TDS]
cmp dword [edi+ecx],byte 0 ; already tracing?
jz near .no_trace
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_TRACE
Trace_Out "ICEDUMP: detected new thread in process, R0TCB: #esi"
debug_end
jmp short .trace
.check_parent:
cmp byte [OT.OTraceprocess],'D'
jz .no_trace
mov ebx,[esi+TCB_VMHandle]
mov eax,[esi+TCB_ClientPtr]
movzx eax,word [eax+CRS.FS]
VMMCall _SelectorMapFlat, ebx, eax, byte 0
cmp eax,0x80000000
jb .no_trace
cmp eax,0xC0000000
jae .no_trace
mov eax,[eax+0x30] ; PDB
push dword [eax+0x48] ; parent PDB
mov ebx,[edi+TCB_VMHandle]
mov eax,[edi+TCB_ClientPtr]
movzx eax,word [eax+CRS.FS]
VMMCall _SelectorMapFlat, ebx, eax, byte 0
pop ecx
cmp eax,0x80000000
jb .no_trace
cmp eax,0xC0000000
jae .no_trace
mov eax,[eax+0x30] ; PDB
cmp eax,ecx ; child/parent?
jnz .no_trace
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_TRACE
Trace_Out "ICEDUMP: detected new thread in child process, R0TCB: #esi"
debug_end
.trace:
pop edx
pop ecx
pop ebx
clc
retn
.no_trace:
pop edx
pop ecx
pop ebx
stc
retn
;-------------------------------------------------------------------------------
; stop tracing thread
;
; EDI: R0TCB
;-------------------------------------------------------------------------------
TracerThreadNotExecuteable:
mov eax,[TDS]
mov eax,[edi+eax] ; TraceInfo
cmp eax,byte 0
jz @F
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_TRACE
push edx
mov edx,[eax+TraceInfo.TickCount+4]
mov eax,[eax+TraceInfo.TickCount]
Trace_Out "ICEDUMP: thread died, instruction count: #edx:#eax, R0TCB: #edi"
pop edx
debug_end
call TracerFree
@@
clc
retn
;-------------------------------------------------------------------------------
; alloc tracer's structure
;
; EDI: R0TCB
;
; stc on error
;-------------------------------------------------------------------------------
TracerAlloc:
mov eax,[TDS]
mov eax,[edi+eax]
or eax,eax
jz @F
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_TRACE
Trace_Out "ICEDUMP: thread is already being traced, R0TCB: #edi"
debug_end
stc
retn
@@
push ecx
push edx
VMMCall _HeapAllocate, dword TraceInfo_size, byte HEAPZEROINIT
pop edx
pop ecx
or eax,eax
jnz @F
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_TRACE
Trace_Out "ICEDUMP: failed to allocate TraceInfo for thread, R0TCB: #edi"
debug_end
stc
retn
@@
push eax
mov eax,[TDS]
add eax,edi
pop dword [eax]
; set up fake IDT: int32 gates to a simple iretd
push ebx
push ecx
push edx
mov ecx,0x60
mov eax,[eax] ; TraceInfo
lea edx,[eax+TraceInfo.IRETD]
mov ebx,0x00280000
mov bx,dx
mov dx,0x8E00 ; int32, dpl=0
@@
mov [eax+8*ecx-8+TraceInfo.IDT],ebx
mov [eax+8*ecx-8+TraceInfo.IDT+4],edx
loop @B
mov byte [eax+TraceInfo.IRETD],0xCF
and dword [eax+TraceInfo.TickCount],byte 0
pop edx
pop ecx
pop ebx
clc
retn
;-------------------------------------------------------------------------------
; free tracer's structure if thread was traced
;
; EDI: R0TCB
;-------------------------------------------------------------------------------
TracerFree:
push ecx
push edx
mov ecx,[TDS]
xor eax,eax
xchg eax,[edi+ecx]
or eax,eax
jz @F
VMMCall _HeapFree, eax, byte 0
@@
pop edx
pop ecx
clc
retn
;-------------------------------------------------------------------------------
; try to set EFLAGS.T in thread's context
;
; EDI: R0TCB
;-------------------------------------------------------------------------------
StartTracing:
push ebp
mov ebp,[edi+TCB_ClientPtr]
bts word [ebp+CRS.EFlags],8 ; set single step flag
jnc @F
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_TRACE
Trace_Out "ICEDUMP: StartTracing: EFLAGS.T was already set, R0TCB: #edi"
debug_end
@@
pop ebp
clc
retn
;-------------------------------------------------------------------------------
; try to reset EFLAGS.T in thread's context
;
; EDI: R0TCB
;-------------------------------------------------------------------------------
StopTracing:
push ebp
mov ebp,[edi+TCB_ClientPtr]
btr word [ebp+CRS.EFlags],8 ; reset single step flag
jc @F
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_TRACE
Trace_Out "ICEDUMP: StopTracing: EFLAGS.T was not set, R0TCB: #edi"
debug_end
@@
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_TRACE
Trace_Out "ICEDUMP: stopped tracing thread, R0TCB: #edi"
debug_end
pop ebp
clc
retn
;-------------------------------------------------------------------------------
; eax: client EIP, skip over known prefixes
;
; eax: first non-prefix byte (real opcode)
; ecx: max length for real opcode (considering the 15 byte limit)
;-------------------------------------------------------------------------------
SkipPrefixes:
push esi
mov esi,eax
mov ecx,15 ; max instruction length
.loop:
.protect_start:
movzx eax,byte [esi]
.protect_end:
bt [Prefixes],eax
jc @F
mov eax,esi
pop esi
clc
retn
@@
inc esi
loop .loop
.EH:
mov eax,esi
pop esi
stc
retn
;segment _LDATA
; prefixes: db 0x26,0x2E,0x36,0x3E,0x64,0x65,0x66,0x67,0xF0,0xF2,0xF3
align 4
Prefixes: ;11111111111111110000000000000000
;FEDCBA9876543210FEDCBA9876543210
dd 00000000000000000000000000000000b ; 1F-00
dd 01000000010000000100000001000000b ; 3F-20
dd 00000000000000000000000000000000b ; 5F-40
dd 00000000000000000000000011110000b ; 7F-60
dd 00000000000000000000000000000000b ; 9F-80
dd 00000000000000000000000000000000b ; BF-A0
dd 00000000000000000000000000000000b ; DF-C0
dd 00000000000011010000000000000000b ; FF-E0
dd 0
segment _LTEXT
;-------------------------------------------------------------------------------
; TRACEX <EIP low> [<EIP high>]
;-------------------------------------------------------------------------------
Parse_TraceX:
mov edi,Error_V86
mov ebp,[dClient_EFLAGS]
test byte [ebp+2],2 ; is client in V86 mode?
jnz near Parser.errorMsg
mov edi,Error_PM16
mov ebp,[dClient_CS]
lar eax,[ebp] ; is client 32 bit?
bt eax,22
jnc near Parser.errorMsg
mov edi,Error_BadEIPlow
call ParseExpression ; parse <EIP low>
jb near Parser.errorMsg
mov [.EIPlow],eax
call [pSkipWhiteSpace] ; skip to <EIP high>
mov eax,[.EIPlow]
jz @F
mov edi,Error_BadEIPhigh
call ParseExpression ; parse <EIP high>
jb near Parser.errorMsg
@@
mov [.EIPhigh],eax
; save client EAX/CS/EIP
mov ebp,[dClient_EAX]
push dword [ebp]
pop dword [.EAX]
mov ebp,[dClient_CS]
push dword [ebp]
pop dword [.CS]
mov ebp,[dClient_EIP]
push dword [ebp]
pop dword [.EIP]
; set up registers for service
push byte SERVICE_TRACEX
mov ebp,[dClient_EAX]
pop dword [ebp]
call SetCB
jc near Parser.error
mov ebp,[fExecuteMoreCommands] ; set internal Winice flag to 0
mov byte [ebp],0
popad
retn
segment _LDATA
align 4
.EAX: dd 0
.CS: dd 0
.EIP: dd 0
.EIPlow: dd 0
.EIPhigh: dd 0
segment _LTEXT
Service_TraceX:
VMMCall Get_Cur_VM_Handle
VMMCall Get_Cur_Thread_Handle
call TracerFree
call TracerAlloc
jnc @F
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_TRACE
Trace_Out "ICEDUMP: TRACEX failed to allocate TraceInfo"
debug_end
jmp short .ret
@@
mov esi,[TDS]
mov esi,[esi+edi] ; TraceInfo
push dword [Parse_TraceX.EIPlow]
pop dword [esi+TraceInfo.EIPlow]
push dword [Parse_TraceX.EIPhigh]
pop dword [esi+TraceInfo.EIPhigh]
push dword [Parse_TraceX.EAX]
pop dword [ebp+CRS.EAX]
push dword [Parse_TraceX.CS]
pop dword [ebp+CRS.CS]
push dword [Parse_TraceX.EIP]
pop dword [ebp+CRS.EIP]
call TrReinforce
.ret:
popfd
popad
retn
;-------------------------------------------------------------------------------
; TRACE [<R0TCB> [<EIP low> [<EIP high>]]]
;-------------------------------------------------------------------------------
Parse_Trace:
push byte SERVICE_TRACE
mov ebp,[dClient_EAX]
pop dword [ebp]
and dword [.R0TCB],byte 0
or dword [.EIPlow],byte -1
and dword [.EIPhigh],byte 0
call ParseExpression ; parse <R0TCB>
jc .setCB
mov [.R0TCB],eax
call [pSkipWhiteSpace] ; skip to <EIP low>
jz .setCB
mov edi,Error_BadEIPlow
call ParseExpression ; parse <EIP low>
jb near Parser.errorMsg
mov [.EIPlow],eax
call [pSkipWhiteSpace] ; skip to <EIP high>
mov eax,[.EIPlow]
jz @F
mov edi,Error_BadEIPhigh
call ParseExpression ; parse <EIP high>
jb near Parser.errorMsg
@@
mov [.EIPhigh],eax
.setCB:
call SetCB
jc near Parser.error
xor eax,eax
inc eax
mov ebp,[fPAGEIN_InProgress] ; set internal Winice flag to 1
mov [ebp],eax
mov ebp,[fExecuteMoreCommands] ; set internal Winice flag to 0
mov [ebp],ah
popad
retn
segment _LDATA
align 4
.R0TCB: dd 0
.EIPlow: dd 0
.EIPhigh: dd 0
segment _LDATA
Error_BadEIPlow: db 'invalid EIP low',0
Error_BadEIPhigh: db 'invalid EIP high',0
segment _LTEXT
;-------------------------------------------------------------------------------
; prepare for tracing the specified thread, take care of self-tracing guys too
;-------------------------------------------------------------------------------
Service_Trace:
cmp [Parse_Trace.R0TCB],byte 0 ; print trace info?
jnz .trace
Trace_Out "ICEDUMP: threads under trace:"
VMMCall Begin_Critical_Section
VMMCall Get_Sys_VM_Handle
VMMCall Get_Initial_Thread_Handle
mov ebx,edi
mov ecx,[TDS]
@@
cmp [edi+ecx],byte 0
Trace_OutNZ "#edi"
VMMCall Get_Next_Thread_Handle
cmp ebx,edi
jnz @B
VMMCall End_Critical_Section
.ret1:
popfd
popad
retn
.trace:
VMMCall Get_Cur_VM_Handle
VMMCall Get_Cur_Thread_Handle
cmp [Parse_Trace.R0TCB],edi ; trace current thread?
jnz near .trace_notcurrent
mov esi,[TDS]
mov esi,[esi+edi] ; TraceInfo
cmp esi,byte 0 ; tracing current thread?
jnz @F
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_TRACE
Trace_Out "ICEDUMP: use TRACEX to trace the current thread"
debug_end
jmp short .ret1
@@
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_TRACE
Trace_Out "ICEDUMP: you shot yourself in the foot, use TRACEX to reactivate tracing the current thread"
debug_end
call TracerFree
jmp short .ret1
.trace_notcurrent:
mov edi,[Parse_Trace.R0TCB]
VMMCall Validate_Thread_Handle
jnc @F
Trace_Out "ICEDUMP: invalid thread handle, R0TCB: #edi"
jmp .ret2
@@
mov esi,[TDS]
mov esi,[esi+edi]
mov ecx,[Parse_Trace.EIPlow]
mov edx,[Parse_Trace.EIPhigh]
cmp ecx,edx
jbe .start
cmp esi,byte 0
jnz @F
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_TRACE
Trace_Out "ICEDUMP: thread was not traced, R0TCB: #edi"
debug_end
jmp short .ret2
@@
cmp dword [esi+TraceInfo.State0],byte ST0_SELFTRACEON
jz @F
call StopTracing
@@
call TracerFree
jmp short .ret2
.start:
cmp esi,byte 0 ; already tracing?
jnz .update_range
mov ebp,[edi+TCB_ClientPtr]
test byte [ebp+CRS.EFlags+2],2 ; is client in V86 mode?
jz @F
; call IsThreadWin32
; jnc @F
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_TRACE
Trace_Out "ICEDUMP: thread is in V86 mode, R0TCB: #edi"
debug_end
jmp short .ret2
@@
call TracerAlloc
jnc @F
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_TRACE
Trace_Out "ICEDUMP: TRACE failed to allocate TraceInfo, R0TCB: #edi"
debug_end
jmp short .ret2
@@
mov esi,[TDS]
mov esi,[esi+edi]
call TrReinforce
.update_range:
mov dword [esi+TraceInfo.EIPlow],ecx
mov dword [esi+TraceInfo.EIPhigh],edx
.ret2:
popfd
popad
retn
%endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -