From 2a7f67d71f9d34c49de6a81e7deab10882bf930f Mon Sep 17 00:00:00 2001 From: midipix Date: May 28 2019 20:59:10 +0000 Subject: debug helpers: __ntapi_tt_debug_break_process(): initial implementation. --- diff --git a/include/ntapi/nt_debug.h b/include/ntapi/nt_debug.h index f555416..f5a1d40 100644 --- a/include/ntapi/nt_debug.h +++ b/include/ntapi/nt_debug.h @@ -350,4 +350,9 @@ typedef int32_t __stdcall ntapi_tt_debug_execution_flow( __in uint32_t evtmask, __in uint64_t * nevents); +typedef int32_t __stdcall ntapi_tt_debug_break_process( + __in void * hprocess, + __out void ** hthread, + __out nt_cid * cid); + #endif diff --git a/include/ntapi/ntapi.h b/include/ntapi/ntapi.h index 493edb2..96b0974 100644 --- a/include/ntapi/ntapi.h +++ b/include/ntapi/ntapi.h @@ -670,6 +670,7 @@ typedef struct _ntapi_vtbl { ntapi_tt_create_debug_object * tt_create_debug_object; ntapi_tt_create_attach_debug_object * tt_create_attach_debug_object; ntapi_tt_debug_execution_flow * tt_debug_execution_flow; + ntapi_tt_debug_break_process * tt_debug_break_process; } ntapi_vtbl; diff --git a/project/common.mk b/project/common.mk index 5009148..508cc13 100644 --- a/project/common.mk +++ b/project/common.mk @@ -16,6 +16,7 @@ COMMON_SRCS = \ src/daemon/ntapi_dsr_init.c \ src/daemon/ntapi_dsr_internal_connection.c \ src/debug/ntapi_tt_create_debug_object.c \ + src/debug/ntapi_tt_debug_break_process.c \ src/debug/ntapi_tt_debug_execution_flow.c \ src/fs/ntapi_tt_get_file_handle_type.c \ src/fs/ntapi_tt_istat.c \ diff --git a/src/debug/ntapi_tt_debug_break_process.c b/src/debug/ntapi_tt_debug_break_process.c new file mode 100644 index 0000000..3ad0daf --- /dev/null +++ b/src/debug/ntapi_tt_debug_break_process.c @@ -0,0 +1,126 @@ +/********************************************************/ +/* ntapi: Native API core library */ +/* Copyright (C) 2013--2019 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ +/********************************************************/ + +#include +#include +#include +#include "ntapi_impl.h" + +static int32_t __tt_debug_break_process_fail(void * hthread, int32_t status) +{ + __ntapi->zw_terminate_thread( + hthread,status); + + return status; +} + +struct __dbg_hoppla { + void * caller; + void * cx; + intptr_t dx; + intptr_t r9; + intptr_t r8; +}; + +int32_t __stdcall __ntapi_tt_debug_break_process( + __in void * hprocess, + __out void ** hthread, + __out nt_cid * cid) +{ + int32_t status; + nt_thread_params tparams; + nt_thread_context context; + nt_user_stack spinfo; + struct __dbg_hoppla hoppla; + uintptr_t sptop; + uintptr_t spreg; + int32_t (*dbg_break_point)(void *); + + /* interrupt & return */ + dbg_break_point = pe_get_procedure_address( + pe_get_ntdll_module_handle(), + "DbgBreakPoint"); + + /* thread params */ + __ntapi->tt_aligned_block_memset( + &tparams,0, + sizeof(tparams)); + + __ntapi->tt_aligned_block_memset( + &spinfo,0, + sizeof(spinfo)); + + tparams.start = dbg_break_point; + tparams.hprocess = hprocess; + tparams.stack_size_commit = 0x1000; + tparams.stack_size_reserve = 0x1000; + tparams.stack_info = &spinfo; + tparams.creation_flags = NT_CREATE_SUSPENDED; + + if ((status = __ntapi->tt_create_thread(&tparams))) + return status; + + /* context */ + __ntapi->tt_aligned_block_memset( + &context,0, + sizeof(context)); + + context.uc_context_flags = NT_CONTEXT_JUST_EVERYTHING; + + if ((status = __ntapi->zw_get_context_thread( + tparams.hthread, + &context))) + return __tt_debug_break_process_fail( + tparams.hthread, + status); + + /* return address:=) */ + hoppla.caller = __ntapi->zw_terminate_thread; + hoppla.cx = NT_CURRENT_THREAD_HANDLE; + hoppla.dx = NT_STATUS_BREAKPOINT; + hoppla.r8 = 0; + hoppla.r9 = 0; + + sptop = (uintptr_t)tparams.stack_info->expandable_stack_base; + spreg = context.STACK_POINTER_REGISTER; + + if (sptop - spreg < sizeof(hoppla)) + spreg -= sizeof(hoppla); + + if ((status = __ntapi->zw_write_virtual_memory( + hprocess, + (void *)spreg, + (char *)&hoppla, + sizeof(hoppla),0))) + return __tt_debug_break_process_fail( + tparams.hthread, + status); + + /* (fast call args not needed on x86) */ + context.STACK_POINTER_REGISTER = spreg; + context.FAST_CALL_ARG0 = (uintptr_t)hoppla.cx; + context.FAST_CALL_ARG1 = hoppla.dx; + + if ((status = __ntapi->zw_set_context_thread( + tparams.hthread, + &context))) + return __tt_debug_break_process_fail( + tparams.hthread, + status); + + /* at last... */ + if ((status = __ntapi->zw_resume_thread(tparams.hthread,0))) + return __tt_debug_break_process_fail( + tparams.hthread, + status); + + /* yay */ + *hthread = tparams.hthread; + cid->thread_id = tparams.cid.thread_id; + cid->process_id = tparams.cid.process_id; + + return NT_STATUS_SUCCESS; +} diff --git a/src/internal/ntapi.c b/src/internal/ntapi.c index 5122305..eff7eb1 100644 --- a/src/internal/ntapi.c +++ b/src/internal/ntapi.c @@ -447,6 +447,7 @@ static int32_t __fastcall __ntapi_init_once(ntapi_vtbl ** pvtbl) __ntapi->tt_create_debug_object = __ntapi_tt_create_debug_object; __ntapi->tt_create_attach_debug_object = __ntapi_tt_create_attach_debug_object; __ntapi->tt_debug_execution_flow = __ntapi_tt_debug_execution_flow; + __ntapi->tt_debug_break_process = __ntapi_tt_debug_break_process; /* OS version dependent functions */ diff --git a/src/internal/ntapi_fnapi.h b/src/internal/ntapi_fnapi.h index 6c20fbf..2f79a57 100644 --- a/src/internal/ntapi_fnapi.h +++ b/src/internal/ntapi_fnapi.h @@ -338,6 +338,7 @@ NTAPI_UFN(log_msg); NTAPI_UFN(tt_create_debug_object); NTAPI_UFN(tt_create_attach_debug_object); NTAPI_UFN(tt_debug_execution_flow); +NTAPI_UFN(tt_debug_break_process); /* csrss */ NTAPI_VFN(tt_get_csr_port_handle_addr_by_logic,i386);