|
|
2a7f67 |
/********************************************************/
|
|
|
2a7f67 |
/* ntapi: Native API core library */
|
|
|
2a7f67 |
/* Copyright (C) 2013--2019 Z. Gilboa */
|
|
|
2a7f67 |
/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
|
|
|
2a7f67 |
/********************************************************/
|
|
|
2a7f67 |
|
|
|
2a7f67 |
#include <psxtypes/psxtypes.h>
|
|
|
2a7f67 |
#include <ntapi/nt_object.h>
|
|
|
2a7f67 |
#include <ntapi/nt_debug.h>
|
|
|
2a7f67 |
#include "ntapi_impl.h"
|
|
|
2a7f67 |
|
|
|
2a7f67 |
static int32_t __tt_debug_break_process_fail(void * hthread, int32_t status)
|
|
|
2a7f67 |
{
|
|
|
2a7f67 |
__ntapi->zw_terminate_thread(
|
|
|
2a7f67 |
hthread,status);
|
|
|
2a7f67 |
|
|
|
2a7f67 |
return status;
|
|
|
2a7f67 |
}
|
|
|
2a7f67 |
|
|
|
2a7f67 |
struct __dbg_hoppla {
|
|
|
2a7f67 |
void * caller;
|
|
|
2a7f67 |
void * cx;
|
|
|
2a7f67 |
intptr_t dx;
|
|
|
2a7f67 |
intptr_t r9;
|
|
|
2a7f67 |
intptr_t r8;
|
|
|
2a7f67 |
};
|
|
|
2a7f67 |
|
|
|
2a7f67 |
int32_t __stdcall __ntapi_tt_debug_break_process(
|
|
|
2a7f67 |
__in void * hprocess,
|
|
|
2a7f67 |
__out void ** hthread,
|
|
|
2a7f67 |
__out nt_cid * cid)
|
|
|
2a7f67 |
{
|
|
|
2a7f67 |
int32_t status;
|
|
|
2a7f67 |
nt_thread_params tparams;
|
|
|
2a7f67 |
nt_thread_context context;
|
|
|
2a7f67 |
nt_user_stack spinfo;
|
|
|
2a7f67 |
struct __dbg_hoppla hoppla;
|
|
|
2a7f67 |
uintptr_t sptop;
|
|
|
2a7f67 |
uintptr_t spreg;
|
|
|
2a7f67 |
int32_t (*dbg_break_point)(void *);
|
|
|
2a7f67 |
|
|
|
2a7f67 |
/* interrupt & return */
|
|
|
2a7f67 |
dbg_break_point = pe_get_procedure_address(
|
|
|
2a7f67 |
pe_get_ntdll_module_handle(),
|
|
|
2a7f67 |
"DbgBreakPoint");
|
|
|
2a7f67 |
|
|
|
2a7f67 |
/* thread params */
|
|
|
2a7f67 |
__ntapi->tt_aligned_block_memset(
|
|
|
2a7f67 |
&tparams,0,
|
|
|
2a7f67 |
sizeof(tparams));
|
|
|
2a7f67 |
|
|
|
2a7f67 |
__ntapi->tt_aligned_block_memset(
|
|
|
2a7f67 |
&spinfo,0,
|
|
|
2a7f67 |
sizeof(spinfo));
|
|
|
2a7f67 |
|
|
|
2a7f67 |
tparams.start = dbg_break_point;
|
|
|
2a7f67 |
tparams.hprocess = hprocess;
|
|
|
2a7f67 |
tparams.stack_size_commit = 0x1000;
|
|
|
2a7f67 |
tparams.stack_size_reserve = 0x1000;
|
|
|
2a7f67 |
tparams.stack_info = &spinfo;
|
|
|
2a7f67 |
tparams.creation_flags = NT_CREATE_SUSPENDED;
|
|
|
2a7f67 |
|
|
|
2a7f67 |
if ((status = __ntapi->tt_create_thread(&tparams)))
|
|
|
2a7f67 |
return status;
|
|
|
2a7f67 |
|
|
|
2a7f67 |
/* context */
|
|
|
2a7f67 |
__ntapi->tt_aligned_block_memset(
|
|
|
2a7f67 |
&context,0,
|
|
|
2a7f67 |
sizeof(context));
|
|
|
2a7f67 |
|
|
|
2a7f67 |
context.uc_context_flags = NT_CONTEXT_JUST_EVERYTHING;
|
|
|
2a7f67 |
|
|
|
2a7f67 |
if ((status = __ntapi->zw_get_context_thread(
|
|
|
2a7f67 |
tparams.hthread,
|
|
|
2a7f67 |
&context)))
|
|
|
2a7f67 |
return __tt_debug_break_process_fail(
|
|
|
2a7f67 |
tparams.hthread,
|
|
|
2a7f67 |
status);
|
|
|
2a7f67 |
|
|
|
2a7f67 |
/* return address:=) */
|
|
|
2a7f67 |
hoppla.caller = __ntapi->zw_terminate_thread;
|
|
|
2a7f67 |
hoppla.cx = NT_CURRENT_THREAD_HANDLE;
|
|
|
2a7f67 |
hoppla.dx = NT_STATUS_BREAKPOINT;
|
|
|
2a7f67 |
hoppla.r8 = 0;
|
|
|
2a7f67 |
hoppla.r9 = 0;
|
|
|
2a7f67 |
|
|
|
2a7f67 |
sptop = (uintptr_t)tparams.stack_info->expandable_stack_base;
|
|
|
2a7f67 |
spreg = context.STACK_POINTER_REGISTER;
|
|
|
2a7f67 |
|
|
|
2a7f67 |
if (sptop - spreg < sizeof(hoppla))
|
|
|
2a7f67 |
spreg -= sizeof(hoppla);
|
|
|
2a7f67 |
|
|
|
2a7f67 |
if ((status = __ntapi->zw_write_virtual_memory(
|
|
|
2a7f67 |
hprocess,
|
|
|
2a7f67 |
(void *)spreg,
|
|
|
2a7f67 |
(char *)&hoppla,
|
|
|
2a7f67 |
sizeof(hoppla),0)))
|
|
|
2a7f67 |
return __tt_debug_break_process_fail(
|
|
|
2a7f67 |
tparams.hthread,
|
|
|
2a7f67 |
status);
|
|
|
2a7f67 |
|
|
|
2a7f67 |
/* (fast call args not needed on x86) */
|
|
|
2a7f67 |
context.STACK_POINTER_REGISTER = spreg;
|
|
|
2a7f67 |
context.FAST_CALL_ARG0 = (uintptr_t)hoppla.cx;
|
|
|
2a7f67 |
context.FAST_CALL_ARG1 = hoppla.dx;
|
|
|
2a7f67 |
|
|
|
2a7f67 |
if ((status = __ntapi->zw_set_context_thread(
|
|
|
2a7f67 |
tparams.hthread,
|
|
|
2a7f67 |
&context)))
|
|
|
2a7f67 |
return __tt_debug_break_process_fail(
|
|
|
2a7f67 |
tparams.hthread,
|
|
|
2a7f67 |
status);
|
|
|
2a7f67 |
|
|
|
2a7f67 |
/* at last... */
|
|
|
2a7f67 |
if ((status = __ntapi->zw_resume_thread(tparams.hthread,0)))
|
|
|
2a7f67 |
return __tt_debug_break_process_fail(
|
|
|
2a7f67 |
tparams.hthread,
|
|
|
2a7f67 |
status);
|
|
|
2a7f67 |
|
|
|
2a7f67 |
/* yay */
|
|
|
2a7f67 |
*hthread = tparams.hthread;
|
|
|
2a7f67 |
cid->thread_id = tparams.cid.thread_id;
|
|
|
2a7f67 |
cid->process_id = tparams.cid.process_id;
|
|
|
2a7f67 |
|
|
|
2a7f67 |
return NT_STATUS_SUCCESS;
|
|
|
2a7f67 |
}
|