diff options
Diffstat (limited to 'src/debug')
-rw-r--r-- | src/debug/ntapi_tt_debug_break_process.c | 126 |
1 files changed, 126 insertions, 0 deletions
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 <psxtypes/psxtypes.h> +#include <ntapi/nt_object.h> +#include <ntapi/nt_debug.h> +#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; +} |