/********************************************************/ /* 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 (__stdcall *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; }