0,0 → 1,344 |
; this code uses following additions to system structures: |
; in additional app info at 80000..8FFFF: |
; AC (dword) 0 or debugger slot |
; BC (dword) address of debug event memory |
; new process slot state: |
; 1 = suspended |
; 2 = suspended waiting for event |
; new event: 8 (and new possible bitflag for A8 in additional app info) |
; diamond, 2006 |
sys_debug_services: |
cmp eax, 8 |
ja @f |
jmp dword [sys_debug_services_table+eax*4] |
@@: ret |
sys_debug_services_table: |
dd debug_set_event_data |
dd debug_getcontext |
dd debug_setcontext |
dd debug_detach |
dd debug_suspend |
dd debug_resume |
dd debug_read_process_memory |
dd debug_write_process_memory |
dd debug_terminate |
|
debug_set_event_data: |
; in: ebx = pointer |
; destroys eax |
mov eax, [0x3000] |
shl eax, 8 |
mov [eax+0x80000+0xBC], ebx |
ret |
|
get_debuggee_slot: |
; in: ebx=PID |
; out: CF=1 if error |
; CF=0 and eax=slot*0x20 if ok |
; out: interrupts disabled |
cli |
mov eax, ebx |
call pid_to_slot |
test eax, eax |
jz .ret_bad |
shl eax, 5 |
push ebx |
mov ebx, [0x3000] |
cmp [0x80000+eax*8+0xAC], ebx |
pop ebx |
jnz .ret_bad |
; clc ; automatically |
ret |
.ret_bad: |
stc |
ret |
|
debug_detach: |
; in: ebx=pid |
; destroys eax,ebx |
call get_debuggee_slot |
jc .ret |
and dword [eax*8+0x80000+0xAC], 0 |
call do_resume |
.ret: |
sti |
ret |
|
debug_terminate: |
; in: ebx=pid |
call get_debuggee_slot |
jc debug_detach.ret |
mov ebx, eax |
shr ebx, 5 |
push 2 |
pop eax |
jmp sys_system |
|
debug_suspend: |
; in: ebx=pid |
; destroys eax,ebx |
call get_debuggee_slot |
jc .ret |
mov bl, [0x3000+eax+0xA] ; process state |
test bl, bl |
jz .1 |
cmp bl, 5 |
jnz .ret |
mov bl, 2 |
.2: mov [0x3000+eax+0xA], bl |
.ret: |
sti |
ret |
.1: |
inc ebx |
jmp .2 |
|
do_resume: |
mov bl, [0x3000+eax+0xA] |
cmp bl, 1 |
jz .1 |
cmp bl, 2 |
jnz .ret |
mov bl, 5 |
.2: mov [0x3000+eax+0xA], bl |
.ret: ret |
.1: dec ebx |
jmp .2 |
|
debug_resume: |
; in: ebx=pid |
; destroys eax,ebx |
call get_debuggee_slot |
jc .ret |
call do_resume |
.ret: sti |
ret |
|
debug_getcontext: |
; in: |
; ebx=pid |
; ecx=sizeof(CONTEXT) |
; edx->CONTEXT |
; destroys eax,ecx,edx,esi,edi |
cmp ecx, 28h |
jnz .ret |
add edx, std_application_base_address |
push ebx |
mov ebx, edx |
call check_region |
pop ebx |
dec eax |
jnz .ret |
call get_debuggee_slot |
jc .ret |
imul eax, tss_step/32 |
add eax, tss_data |
mov edi, edx |
cmp [l.cs - tss_sceleton + eax], app_code |
jnz .ring0 |
lea esi, [l.eip - tss_sceleton + eax] |
shr ecx, 2 |
rep movsd |
jmp .ret |
.ring0: |
; note that following code assumes that all interrupt/exception handlers |
; saves ring-3 context by push ds es, pushad in this order |
mov esi, [l.esp0 - tss_sceleton + eax] |
; top of ring0 stack: ring3 stack ptr (ss+esp), iret data (cs+eip+eflags), ds, es, pushad |
sub esi, 8+12+8+20h |
lodsd |
mov [edi+24h], eax |
lodsd |
mov [edi+20h], eax |
lodsd |
mov [edi+1Ch], eax |
lodsd |
lodsd |
mov [edi+14h], eax |
lodsd |
mov [edi+10h], eax |
lodsd |
mov [edi+0Ch], eax |
lodsd |
mov [edi+8], eax |
add esi, 8 |
lodsd |
mov [edi], eax |
lodsd |
lodsd |
mov [edi+4], eax |
lodsd |
mov [edi+18h], eax |
.ret: |
sti |
ret |
|
debug_setcontext: |
; in: |
; ebx=pid |
; ecx=sizeof(CONTEXT) |
; edx->CONTEXT |
; destroys eax,ecx,edx,esi,edi |
cmp ecx, 28h |
jnz .ret |
add edx, std_application_base_address |
push ebx |
mov ebx, edx |
call check_region |
pop ebx |
dec eax |
jnz .ret |
call get_debuggee_slot |
jc .stiret |
imul eax, tss_step/32 |
add eax, tss_data |
mov esi, edx |
cmp [l.cs - tss_sceleton + eax], app_code |
jnz .ring0 |
lea edi, [l.eip - tss_sceleton + eax] |
shr ecx, 2 |
rep movsd |
jmp .stiret |
.ring0: |
mov edi, [l.esp0 - tss_sceleton + eax] |
sub edi, 8+12+8+20h |
mov eax, [esi+24h] |
stosd |
mov eax, [esi+20h] |
stosd |
mov eax, [esi+1Ch] |
stosd |
scasd |
mov eax, [esi+14h] |
stosd |
mov eax, [esi+10h] |
stosd |
mov eax, [esi+0Ch] |
stosd |
mov eax, [esi+8] |
stosd |
add edi, 8 |
mov eax, [esi] |
stosd |
scasd |
mov eax, [esi+4] |
stosd |
mov eax, [esi+18h] |
stosd |
.stiret: |
sti |
.ret: |
ret |
|
debug_read_process_memory: |
; in: |
; ebx=pid |
; ecx=length |
; esi->buffer in debugger |
; edx=address in debuggee |
; out: [esp+36]=eax=sizeof(read) |
; destroys all |
add esi, std_application_base_address |
push ebx |
mov ebx, esi |
call check_region |
pop ebx |
dec eax |
jnz .ret |
call get_debuggee_slot |
jc .stiret |
mov ebx, esi |
call read_process_memory |
.stiret: |
sti |
.ret: |
ret |
|
debug_write_process_memory: |
; in: |
; ebx=pid |
; ecx=length |
; esi->buffer in debugger |
; edx=address in debuggee |
; out: [esp+36]=eax=sizeof(write) |
; destroys all |
add esi, std_application_base_address |
push ebx |
mov ebx, esi |
call check_region |
pop ebx |
dec eax |
jnz .ret |
call get_debuggee_slot |
jc .stiret |
mov ebx, esi |
call write_process_memory |
.stiret: |
sti |
.ret: |
ret |
|
debugger_notify: |
; in: eax=debugger slot |
; ecx=size of debug message |
; [esp+4]..[esp+4+ecx]=message |
; interrupts must be disabled! |
; destroys all general registers |
; interrupts remain disabled |
mov ebp, eax |
shl eax, 8 |
.1: |
mov edx, [0x80000+eax+0xBC] |
test edx, edx |
jz .ret |
; read buffer header |
push ecx |
push eax |
push eax |
mov eax, ebp |
mov ebx, esp |
mov ecx, 8 |
call read_process_memory |
cmp eax, ecx |
jz @f |
add esp, 12 |
jmp .ret |
@@: |
cmp dword [ebx], 0 |
jg @f |
.2: |
pop ecx |
pop ecx |
pop ecx |
sti |
call change_task |
cli |
jmp .1 |
@@: |
mov ecx, [ebx+8] |
add ecx, [ebx+4] |
cmp ecx, [ebx] |
ja .2 |
; advance buffer position |
push ecx |
mov ecx, 4 |
sub ebx, ecx |
mov eax, ebp |
add edx, ecx |
call write_process_memory |
pop eax |
; write message |
mov eax, ebp |
add edx, ecx |
add edx, [ebx+8] |
add ebx, 20 |
pop ecx |
pop ecx |
pop ecx |
call write_process_memory |
; new debug event |
mov eax, ebp |
shl eax, 8 |
or byte [0x80000+eax+0xA8+1], 1 ; set flag 100h |
.ret: |
ret |