📄 cmd_trace.asm
字号:
%include "util.mac"
%include "vxdn.inc"
%include "icedump.inc"
%include "wiat.inc"
%include "win32n.inc"
%ifndef MAKEDEP
global TracerSysDynamicDeviceInit
global TracerSysDynamicDeviceExit
global TracerThreadInit
global TracerThreadNotExecuteable
global BreakIn.ignore_range
global Parse_Trace
global Parse_TraceX
global Service_Trace
global Service_TraceX
global VWIN32W32ServiceTable
global VWIN32_W32_ResumeThread
global VWIN32_W32_SuspendThread
extern SetCB
extern sdata
extern Parser.error
extern Parser.errorMsg
extern Error_V86
extern Error_PM16
extern Error_PMR0
extern ParseExpression
extern API.oGetTickCount
extern OT.OLastbutone
extern OT.OBranch
extern OT.OAll
extern OT.OTracethread
extern OT.OTraceprocess
extern OT.OBreaknew
extern OT.OBreakr0
extern IsThreadWin32
bits 32
; shamelessly ripped from sandpile.org ;-)
DR6_BT_MASK equ 00008000h ; break due to TSS.T=1
DR6_BT_BIT equ 15
DR6_BS_MASK equ 00004000h ; break due to EFLAGS.TF=1
DR6_BS_BIT equ 14
DR6_BD_MASK equ 00002000h ; break due to DR7.GD=1
DR6_BD_BIT equ 13
DR6_SMM_MASK equ 00001000h ; (indicated SMM on some CPUs)
DR6_SMM_BIT equ 12
DR6_B3_MASK equ 00000008h ; break due to DR3 match
DR6_B3_BIT equ 3
DR6_B2_MASK equ 00000004h ; break due to DR2 match
DR6_B2_BIT equ 2
DR6_B1_MASK equ 00000002h ; break due to DR1 match
DR6_B1_BIT equ 1
DR6_B0_MASK equ 00000001h ; break due to DR0 match
DR6_B0_BIT equ 0
; state information for the tracer on a per thread basis
;
; the theory goes like this: we attach a simple state machine to each thread
; we trace which tries to take care of thread's awareness of its being traced.
; in other words, we try to trick the thread into beleiving that it's not
; traced and has full control over the single stepping mechanism should it
; wish to use it.
;
; the state set is two dimensional in the first approach, one dimension tells
; whether the thread is trying to trace itself or not, and the second dimension
; maintains emulation related information (all instructions able to read/write
; EFLAGS.T and DR6.BS must be properly emulated).
;
; the inputs to the state machine allow monitoring context inquiries/changes
; and reacting on exceptions (most importantly on the single step trap).
;
; the state transition functions will simply modify the state information
; and the thread's context if necessary.
IDT_SIZE EQU 0x60
struc TraceInfo
.State0: resd 1 ; 00
.State1: resd 1 ; 04
.EIPlow: resd 1 ; 08
.EIPhigh: resd 1 ; 0C
.TickCount: resd 2 ; 10
.lastCS: resd 1 ; 18
.lastEIP: resd 1 ; 1C
.lastSS: resd 1 ; 20
.lastESP: resd 1 ; 24
.IDTR: resd 1 ; 28
.IRETD: resb 16 ; 2C
.IDT: resb 8*IDT_SIZE ; 3C
endstruc
ABORT EQU 0
PASSDOWN EQU 1
DONTPASS EQU 2
ST0_SELFTRACEOFF EQU 0
ST0_SELFTRACEON EQU 1
ST0_SIZE EQU 2
ST1_NOOP EQU 0
ST1_PUSHF EQU 1
ST1_POPF EQU 2
ST1_IRET EQU 3
ST1_SIDT EQU 4
ST1_GETTICKCOUNT EQU 5
ST1_SIZE EQU 6
;ST1_INTxx EQU 5
;ST1_INTO EQU 6
;ST1_ICEBP EQU 7
;ST1_SIZE EQU 8
IN_DEBUG_BS EQU 0
IN_EXCEPTION_IN EQU 1
IN_EXCEPTION_OUT EQU 2
IN_SIZE EQU 3
;IN_DEBUG_BT EQU 1
;IN_DEBUG_BD EQU 2
;IN_DEBUG_DRx EQU 3
;IN_DEBUG_Unknown EQU 4
;IN_SIZE EQU 5
segment _LDATA
align 4
Transitions:
ST0_SelfTraceOff:
; IN_DEBUG_BS IN_EXCEPTION_IN IN_EXCEPTION_OUT
.NONE: dd TrRet, TrPassLie, TrReinforce.no_selftrace
.PUSHF: dd TrRetEmuPushf, TrPassLie, TrReinforce.no_selftrace
.POPF: dd TrRetEmuPopf, TrPassLie, TrReinforce.no_selftrace
.IRET: dd TrRetEmuIret, TrPassLie, TrReinforce.no_selftrace
.SIDT: dd TrRetEmuSidt, TrPassLie, TrReinforce.no_selftrace
.GETTC: dd TrRetEmuGetTC, TrPassLie, TrReinforce.no_selftrace
ST0_SelfTraceOn:
.NONE: dd TrPass, TrPass, TrReinforce
.PUSHF: dd TrPassEmuPushf, TrPass, TrReinforce
.POPF: dd TrPassEmuPopf, TrPass, TrReinforce
.IRET: dd TrPassEmuIret, TrPass, TrReinforce
.SIDT: dd TrPassEmuSidt, TrPass, TrReinforce
.GETTC: dd TrPassEmuGetTC, TrPass, TrReinforce
Context:
istruc CONTEXT
iend
segment _LTEXT
;-------------------------------------------------------------------------------
; state transition functions
;
; EBX: VMCB
; EDI: R0TCB
; ESI: R0TCB->TDS (TranceInfo)
; EBP: Client Registers
;
; each function must preserve registers except for EAX which holds the return
; value (where used, currently in response to IN_DEBUG_BS only)
;
; only the thread's context and the statemachine is allowed to be changed
;-------------------------------------------------------------------------------
TrRet:
mov eax,DONTPASS
retn
;-------------------------------------------------------------------------------
TrRetEmuPushf:
call GetLinearSSESP
jc @F
btr word [eax],8
@@
mov eax,DONTPASS
retn
;-------------------------------------------------------------------------------
TrRetEmuPopf:
bts word [ebp+CRS.EFlags],8
jnc @F
mov dword [esi+TraceInfo.State0],ST0_SELFTRACEON
@@
mov eax,DONTPASS
retn
;-------------------------------------------------------------------------------
TrRetEmuIret:
bts word [ebp+CRS.EFlags],8
jnc @F
mov dword [esi+TraceInfo.State0],ST0_SELFTRACEON
@@
mov eax,DONTPASS
retn
;-------------------------------------------------------------------------------
TrRetEmuSidt:
lea eax,[esi+TraceInfo.IDT]
push eax
mov eax,[esi+TraceInfo.IDTR]
pop dword [eax+2]
mov eax,DONTPASS
retn
;-------------------------------------------------------------------------------
TrRetEmuGetTC:
call TrEmuGetTC
mov eax,DONTPASS
retn
;-------------------------------------------------------------------------------
TrPass:
mov eax,PASSDOWN
retn
;-------------------------------------------------------------------------------
TrPassEmuPushf:
mov eax,PASSDOWN
retn
;-------------------------------------------------------------------------------
TrPassEmuPopf:
bts word [ebp+CRS.EFlags],8
jc @F
mov dword [esi+TraceInfo.State0],ST0_SELFTRACEOFF
@@
mov eax,PASSDOWN
retn
;-------------------------------------------------------------------------------
TrPassEmuIret:
bts word [ebp+CRS.EFlags],8
jc @F
mov dword [esi+TraceInfo.State0],ST0_SELFTRACEOFF
@@
mov eax,PASSDOWN
retn
;-------------------------------------------------------------------------------
TrPassEmuSidt:
lea eax,[esi+TraceInfo.IDT]
push eax
mov eax,[esi+TraceInfo.IDTR]
pop dword [eax+2]
mov eax,PASSDOWN
retn
;-------------------------------------------------------------------------------
TrPassEmuGetTC:
call TrEmuGetTC
mov eax,PASSDOWN
retn
;-------------------------------------------------------------------------------
TrPassLie:
btr word [ebp+CRS.EFlags],8
mov eax,PASSDOWN
retn
;-------------------------------------------------------------------------------
TrReinforce:
call BreakIn
jc @F
retn
@@
mov dword [esi+TraceInfo.State0],ST0_SELFTRACEON
bts word [ebp+CRS.EFlags],8
jc .eval_opcode
mov dword [esi+TraceInfo.State0],ST0_SELFTRACEOFF
jmp short .eval_opcode
.no_selftrace:
call BreakIn
jc @F
retn
@@
bts word [ebp+CRS.EFlags],8
.eval_opcode:
add dword [esi+TraceInfo.TickCount],byte 1
adc dword [esi+TraceInfo.TickCount+4],byte 0
call GetLinearCSEIP
jnc .find_opcode
cmp dword [esi+TraceInfo.State0],byte ST0_SELFTRACEON
jz @F
btr word [ebp+CRS.EFlags],8
@@
call TracerFree
push ebx
debug_start sdata+DebugFlags, ICEDUMP_DEBUG_TRACE
movzx eax,word [ebp+CRS.CS]
mov ebx,[ebp+CRS.EIP]
Trace_Out "ICEDUMP: TrReinforce: GetLinearCSEIP failed, CS:EIP: #ax:#ebx"
debug_end
pop ebx
retn
.find_opcode:
push ecx
push edx
call SkipPrefixes
jb .noop
.protect_start:
cmp byte [eax],0x9C
jnz @F
mov dword [esi+TraceInfo.State1],ST1_PUSHF
jmp short .ret
@@
cmp byte [eax],0x9D
jnz @F
mov dword [esi+TraceInfo.State1],ST1_POPF
jmp short .ret
@@
cmp byte [eax],0xCF
jnz @F
mov dword [esi+TraceInfo.State1],ST1_IRET
jmp short .ret
@@
cmp ecx,byte 3
jbe @F
cmp word [eax],0x010F ; SIDT and similar
jnz @F
mov dl,[eax+2]
and dl,00111000b
cmp dl,00001000b ; SIDT
jnz @F
add eax,byte 2
sub ecx,byte 2
call GetLenAndAddr
jc @F
mov dword [esi+TraceInfo.IDTR],eax
mov dword [esi+TraceInfo.State1],ST1_SIDT
jmp short .ret
@@
cmp word [eax+ecx-15],0xA165 ; mov eax,[gs:0]
jnz @F
cmp dword [eax+ecx-15+2],byte 0
jnz @F
cmp eax,[API.oGetTickCount] ; best would be a check for GS
jb @F
mov dword [esi+TraceInfo.State1],ST1_GETTICKCOUNT
jmp short .ret
@@
.protect_end:
.noop:
.EH:
mov dword [esi+TraceInfo.State1],ST1_NOOP
.ret:
pop edx
pop ecx
retn
;-------------------------------------------------------------------------------
; EBX: VMCB
; EDI: R0TCB
; ESI: R0TCB->TDS (TranceInfo)
; EBP: Client Registers
;-------------------------------------------------------------------------------
TrEmuGetTC:
push eax
push edx
mov eax,[esi+TraceInfo.TickCount]
mov edx,[esi+TraceInfo.TickCount+4]
shrd eax,edx,17 ; simulate a 128 mips machine
mov [ebp+CRS.EAX],eax
pop edx
pop eax
retn
;-------------------------------------------------------------------------------
; EBX: VMCB
; EBP: Client Registers
;
; EAX: linear SS:ESP
; stc on error
;-------------------------------------------------------------------------------
GetLinearSSESP:
push ecx
push edx
movzx eax,word [ebp+CRS.SS]
test byte [ebp+CRS.EFlags+2],2 ; is client in V86 mode?
jz .PM
movzx edx,word [ebp+CRS.ESP]
shl eax,4
add eax,edx
pop edx
pop ecx
clc
retn
.PM:
VMMCall _SelectorMapFlat, ebx, eax, byte 0
cmp eax,byte -1
jnz @F
pop edx
pop ecx
stc
retn
@@
mov edx,[ebp+CRS.ESP]
lar ecx,[ebp+CRS.SS] ; is client stack 32 bit?
bt ecx,22
jc @F
movzx edx,dx
@@
add eax,edx
pop edx
pop ecx
clc
retn
;-------------------------------------------------------------------------------
; EBX: VMCB
; EBP: Client Registers
;
; EAX: linear SS:ESP
; stc on error
;-------------------------------------------------------------------------------
GetLinearCSEIP:
push ecx
push edx
movzx eax,word [ebp+CRS.CS]
test byte [ebp+CRS.EFlags+2],2 ; is client in V86 mode?
jz .PM
movzx edx,word [ebp+CRS.EIP]
shl eax,4
add eax,edx
pop edx
pop ecx
clc
retn
.PM:
VMMCall _SelectorMapFlat, ebx, eax, byte 0
cmp eax,byte -1
jnz @F
pop edx
pop ecx
stc
retn
@@
mov edx,[ebp+CRS.EIP]
lar ecx,[ebp+CRS.CS] ; is client 32 bit?
bt ecx,22
jc @F
movzx edx,dx
@@
add eax,edx
pop edx
pop ecx
clc
retn
;-------------------------------------------------------------------------------
; G-RoM's stuff
;
; EAX: address
; ECX: max length
; EBP: Client Registers
;
; EAX: linear address (operand)
; stc on error (length exceeded)
;-------------------------------------------------------------------------------
GetLenAndAddr:
push ebx
push ecx
push edx
push edi
mov edi,esp ; needed 'cos of EH
.protect_start:
movzx edx,byte [eax]
ror edx,3
shr dl,3
rol edx,3
inc eax
jmp dword [edx*4+.Jumptable]
.ill:
.EH:
stc
.ret:
mov esp,edi
pop edi
pop edx
pop ecx
pop ebx
retn
.ga32AX:
mov eax,[ebp+CRS.EAX]
sub ecx,byte 1
jmp short .ret
.ga32BX:
mov eax,[ebp+CRS.EBX]
sub ecx,byte 1
jmp short .ret
.ga32CX:
mov eax,[ebp+CRS.ECX]
sub ecx,byte 1
jmp short .ret
.ga32DX:
mov eax,[ebp+CRS.EDX]
sub ecx,byte 1
jmp short .ret
.ga32DD:
mov eax,[eax]
sub ecx,byte 5 ;new size
jmp short .ret
.ga32SI:
mov eax,[ebp+CRS.ESI]
sub ecx,byte 1
jmp short .ret
.ga32DI:
mov eax,[ebp+CRS.EDI]
sub ecx,byte 1
jmp short .ret
.ga32AXD:
mov eax,[eax]
add eax,[ebp+CRS.EAX]
sub ecx,byte 5
jmp short .ret
.ga32BXD:
mov eax,[eax]
add eax,[ebp+CRS.EBX]
sub ecx,byte 5
jmp short .ret
.ga32CXD:
mov eax,[eax]
add eax,[ebp+CRS.ECX]
sub ecx,byte 5
jmp short .ret
.ga32DXD:
mov eax,[eax]
add eax,[ebp+CRS.EDX]
sub ecx,byte 5
jmp short .ret
.ga32BPD:
mov eax,[eax]
add eax,[ebp+CRS.EBP]
sub ecx,byte 5
jmp short .ret
.ga32SID:
mov eax,[eax]
add eax,[ebp+CRS.ESI]
sub ecx,byte 5
jmp short .ret
.ga32DID:
mov eax,[eax]
add eax,[ebp+CRS.EDI]
sub ecx,byte 5
jmp .ret
.ga32AXB:
movsx eax,byte [eax]
add eax,[ebp+CRS.EAX]
sub ecx,byte 2
jmp .ret
.ga32BXB:
movsx eax,byte [eax]
add eax,[ebp+CRS.EBX]
sub ecx,byte 2
jmp .ret
.ga32CXB:
movsx eax,byte [eax]
add eax,[ebp+CRS.ECX]
sub ecx,byte 2
jmp .ret
.ga32DXB:
movsx eax,byte [eax]
add eax,[ebp+CRS.EDX]
sub ecx,byte 2
jmp .ret
.ga32SIB:
movsx eax,byte [eax]
add eax,[ebp+CRS.ESI]
sub ecx,byte 2
jmp .ret
.ga32DIB:
movsx eax,byte [eax]
add eax,[ebp+CRS.EDI]
sub ecx,byte 2
jmp .ret
.ga32BPB:
movsx eax,byte [eax]
add eax,[ebp+CRS.EBP]
sub ecx,byte 2
jmp .ret
.ga32S:
movzx edx,byte [eax]
and dl,111b ; implied clc
call [.getBaseS+4*edx]
.ga32Scommon:
jc near .ret
mov ebx,edx
movzx edx,byte [eax]
shr dl,3
and dl,111b
call [.getIndex+4*edx]
push edx
movzx edx,byte [eax]
shr dl,6
call [.scaleIndex+4*edx] ; stdcall
lea eax,[edx+ebx]
sub ecx,byte 1
jmp .ret
.ga32SB:
movzx edx,byte [eax]
and dl,111b ; implied clc
call [.getBaseSB+4*edx]
jmp short .ga32Scommon
.ga32SD:
movzx edx,byte [eax]
and dl,111b ; implied clc
call [.getBaseSD+4*edx]
jmp short .ga32Scommon
.gbAX:
.giAX:
mov edx,[ebp+CRS.EAX]
retn
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -