summaryrefslogtreecommitdiffhomepage
path: root/src/debug
diff options
context:
space:
mode:
Diffstat (limited to 'src/debug')
-rw-r--r--src/debug/ntapi_tt_debug_break_process.c126
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;
+}