diff --git a/.github/labeler.yml b/.github/labeler.yml index d0dd8d121c..89414d215b 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -138,8 +138,8 @@ java: - shlr/java/**/* WinDbg: - - shlr/windbg/**/* - - libr/io/p/io_windbg.c + - shlr/winkd/**/* + - libr/io/p/io_winkd.c webui: - shlr/www/**/* diff --git a/CODEOWNERS b/CODEOWNERS index bb0aaa2da2..67c94ecaff 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -33,5 +33,5 @@ shlr/ptrace-wrap/ @thestr4ng3r shlr/radare2-shell-parser/ @ret2libc shlr/tcc/ @XVilka @trufae shlr/w32dbg_wrap/ @yossizap -shlr/windbg/ @yossizap +shlr/winkd/ @yossizap doc/fortunes.nsfw @thestr4ng3r diff --git a/doc/debug-internals.md b/doc/debug-internals.md index 0fc43c741d..131471ae22 100644 --- a/doc/debug-internals.md +++ b/doc/debug-internals.md @@ -208,11 +208,11 @@ See doc/qnx See doc/rap -### libr/debug/p/debug_windbg.c +### libr/debug/p/debug_winkd.c A debugger plugin that enables debugging code remotely via WinDbg protocol. WinDbg protocol -parser is located in shlr/windbg. Corresponding IO plugin located in libr/io/p/io_windbg.c -See doc/windbg +parser is located in shlr/winkd. Corresponding IO plugin located in libr/io/p/io_winkd.c +See doc/winkd ## Conclusion diff --git a/doc/windbg.md b/doc/windbg.md index 081f93edd3..366625c85c 100644 --- a/doc/windbg.md +++ b/doc/windbg.md @@ -34,24 +34,24 @@ Configure the VirtualBox Machine like this: Port Number: [_COM1_______[v]] Port Mode: [_Host_Pipe__[v]] [v] Create Pipe - Port/File Path: [_/tmp/windbg.pipe____] + Port/File Path: [_/tmp/winkd.pipe____] Or just spawn the VM with qemu like this: $ qemu-system-x86_64 -chardev socket,id=serial0,\ - path=/tmp/windbg.pipe,nowait,server \ + path=/tmp/winkd.pipe,nowait,server \ -serial chardev:serial0 -hda Windows7-VM.vdi -Radare2 will use the 'windbg' io plugin to connect to a socket file -created by virtualbox or qemu. Also, the 'windbg' debugger plugin and +Radare2 will use the 'winkd' io plugin to connect to a socket file +created by virtualbox or qemu. Also, the 'winkd' debugger plugin and we should specify the x86-32 too. (32 and 64 bit debugging is supported) - $ r2 -a x86 -b 32 -D windbg windbg:///tmp/windbg.pipe + $ r2 -a x86 -b 32 -D winkd winkd:///tmp/winkd.pipe On Windows you should run the following line: - $ radare2 -D windbg windbg://\\.\pipe\com_1 + $ radare2 -D winkd winkd://\\.\pipe\com_1 At this point, we will get stuck here: diff --git a/libr/Makefile b/libr/Makefile index 139808bd47..361d217865 100644 --- a/libr/Makefile +++ b/libr/Makefile @@ -113,7 +113,7 @@ E+=../shlr/grub/libgrubfs.${EXT_AR} endif E+=../shlr/yxml/libyxml.${EXT_AR} E+=../shlr/ar/libr_ar.${EXT_AR} -E+=../shlr/windbg/libr_windbg.${EXT_AR} +E+=../shlr/winkd/libr_winkd.${EXT_AR} E+=../shlr/qnx/lib/libqnxr.${EXT_AR} E+=../shlr/bochs/lib/libbochs.${EXT_AR} E+=../shlr/radare2-shell-parser/libshell-parser.${EXT_AR} diff --git a/libr/core/p/Makefile b/libr/core/p/Makefile index cc866d80e5..1140a99a0d 100644 --- a/libr/core/p/Makefile +++ b/libr/core/p/Makefile @@ -18,7 +18,7 @@ LDFLAGS+=$(STOP)/sdb/src/libsdb.a include $(STOP)/java/deps.mk include $(STOP)/gdb/deps.mk -include $(STOP)/windbg/deps.mk +include $(STOP)/winkd/deps.mk LDFLAGS+=${LINK} diff --git a/libr/debug/meson.build b/libr/debug/meson.build index 4d6bb92dcf..9ca933ce62 100644 --- a/libr/debug/meson.build +++ b/libr/debug/meson.build @@ -21,7 +21,7 @@ r_debug_sources = [ 'p/debug_null.c', 'p/debug_qnx.c', 'p/debug_rap.c', - 'p/debug_windbg.c', + 'p/debug_winkd.c', #'p/native/arm.c', #'p/native/bt/fuzzy-all.c', #'p/native/bt/generic-x64.c', @@ -45,7 +45,7 @@ r_debug_deps = [ r_cons_dep, r_lang_dep, r_egg_dep, - windbg_dep, + winkd_dep, qnx_dep, gdb_dep, bochs_dep, @@ -61,6 +61,7 @@ endif if host_machine.system() == 'windows' r_debug_sources += [ + 'p/debug_windbg.c', 'p/native/maps/windows_maps.c', 'p/native/windows/windows_debug.c', 'p/native/windows/windows_message.c', diff --git a/libr/debug/p/Makefile b/libr/debug/p/Makefile index ab5cbddc08..7878142ae8 100644 --- a/libr/debug/p/Makefile +++ b/libr/debug/p/Makefile @@ -6,7 +6,7 @@ CFLAGS+=-I../../include -Wall ${PIC_FLAGS} ${LDFLAGS_LIB} ${LDFLAGS_LINKPATH}.. all: ${ALL_TARGETS} ALL_TARGETS= -DEBUGS=native.mk gdb.mk qnx.mk windbg.mk bochs.mk +DEBUGS=native.mk gdb.mk qnx.mk winkd.mk bochs.mk include $(DEBUGS) pre: diff --git a/libr/debug/p/debug_windbg.c b/libr/debug/p/debug_windbg.c index 4f18432a3c..936dc992c1 100644 --- a/libr/debug/p/debug_windbg.c +++ b/libr/debug/p/debug_windbg.c @@ -1,289 +1,628 @@ -// Copyright (c) 2014-2017, The Lemon Man, All rights reserved. LGPLv3 +/* radare - LGPL - Copyright 2020 - GustavoLCR */ -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. - -// You should have received a copy of the GNU Lesser General Public -// License along with this library. - -#include #include -#include -#include +#include -static WindCtx *wctx = NULL; +#ifndef CONTEXT_ARM +#define CONTEXT_ARM 0x00200000L +#endif +#ifndef CONTEXT_ARM64 +#define CONTEXT_ARM64 0x00400000L +#endif +#ifndef CONTEXT_AMD64 +#define CONTEXT_AMD64 0x00100000L +#endif +#ifndef CONTEXT_i386 +#define CONTEXT_i386 0x00010000L +#endif +#ifndef IMAGE_FILE_MACHINE_ARM64 +#define IMAGE_FILE_MACHINE_ARM64 0xAA64 +#endif +#ifndef DEBUG_DUMP_ACTIVE +#define DEBUG_DUMP_ACTIVE 1030 +#endif -static int r_debug_windbg_step(RDebug *dbg) { - return true; +#define TIMEOUT 500 +#define THISCALL(dbginterface, function, ...) dbginterface->lpVtbl->function (dbginterface, __VA_ARGS__) +#define ITHISCALL(dbginterface, function, ...) THISCALL (idbg->dbginterface, function, __VA_ARGS__) +#define RELEASE(I) if (I) THISCALL (I, Release); + +typedef struct { // Keep in sync with io_windbg.c + bool initialized; + ULONG64 server; + ULONG64 processBase; + DWORD lastExecutionStatus; + PDEBUG_CLIENT5 dbgClient; + PDEBUG_CONTROL4 dbgCtrl; + PDEBUG_DATA_SPACES4 dbgData; + PDEBUG_REGISTERS2 dbgReg; + PDEBUG_SYSTEM_OBJECTS4 dbgSysObj; + PDEBUG_SYMBOLS3 dbgSymbols; + PDEBUG_ADVANCED3 dbgAdvanced; +} DbgEngContext; + +static bool __is_target_kernel(DbgEngContext *idbg) { + ULONG Class, Qualifier; + if (SUCCEEDED (ITHISCALL (dbgCtrl, GetDebuggeeType, &Class, &Qualifier))) { + if (Class == DEBUG_CLASS_KERNEL) { + return true; + } + } + return false; } -static int r_debug_windbg_reg_read(RDebug *dbg, int type, ut8 *buf, int size) { - int ret = windbg_read_reg(wctx, buf, size); - if (!ret || size != ret) { - return -1; +static int windbg_init(RDebug *dbg) { + DbgEngContext *idbg = dbg->user; + if (!idbg || !idbg->initialized) { + return 0; + } + return 1; +} + +static int windbg_step(RDebug *dbg) { + DbgEngContext *idbg = dbg->user; + r_return_val_if_fail (idbg && idbg->initialized, 0); + idbg->lastExecutionStatus = DEBUG_STATUS_STEP_INTO; + return SUCCEEDED (ITHISCALL (dbgCtrl, SetExecutionStatus, DEBUG_STATUS_STEP_INTO)); +} + +static int windbg_step_over(RDebug *dbg) { + DbgEngContext *idbg = dbg->user; + r_return_val_if_fail (idbg && idbg->initialized, 0); + idbg->lastExecutionStatus = DEBUG_STATUS_STEP_OVER; + return SUCCEEDED (ITHISCALL (dbgCtrl, SetExecutionStatus, DEBUG_STATUS_STEP_OVER)); +} + +static int windbg_select(RDebug *dbg, int pid, int tid) { + DbgEngContext *idbg = dbg->user; + r_return_val_if_fail (idbg && idbg->initialized, 0); + ULONG Id = tid, Class, Qualifier; + if (!__is_target_kernel (idbg)) { + ITHISCALL (dbgSysObj, GetThreadIdBySystemId, tid, &Id); + } + if (SUCCEEDED (ITHISCALL (dbgSysObj, SetCurrentThreadId, Id))) { + return 1; } - r_reg_read_regs (dbg->reg, buf, ret); - // Report as if no register has been written as we've already updated the arena here return 0; } -static int r_debug_windbg_reg_write(RDebug *dbg, int type, const ut8 *buf, int size) { - if (!dbg->reg) { - return false; +static int windbg_continue(RDebug *dbg, int pid, int tid, int sig) { + DbgEngContext *idbg = dbg->user; + r_return_val_if_fail (idbg && idbg->initialized, 0); + idbg->lastExecutionStatus = DEBUG_STATUS_GO; + ITHISCALL (dbgCtrl, SetExecutionStatus, DEBUG_STATUS_GO); + return tid; +} + +// nicked from windows_debug.c +static RDebugReasonType exception_to_reason(DWORD ExceptionCode) { + switch (ExceptionCode) { + case EXCEPTION_ACCESS_VIOLATION: + case EXCEPTION_GUARD_PAGE: + return R_DEBUG_REASON_SEGFAULT; + case EXCEPTION_BREAKPOINT: + return R_DEBUG_REASON_BREAKPOINT; + case EXCEPTION_FLT_DENORMAL_OPERAND: + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + case EXCEPTION_FLT_INEXACT_RESULT: + case EXCEPTION_FLT_INVALID_OPERATION: + case EXCEPTION_FLT_OVERFLOW: + case EXCEPTION_FLT_STACK_CHECK: + case EXCEPTION_FLT_UNDERFLOW: + return R_DEBUG_REASON_FPU; + case EXCEPTION_ILLEGAL_INSTRUCTION: + return R_DEBUG_REASON_ILLEGAL; + case EXCEPTION_INT_DIVIDE_BY_ZERO: + return R_DEBUG_REASON_DIVBYZERO; + case EXCEPTION_SINGLE_STEP: + return R_DEBUG_REASON_STEP; + default: + return R_DEBUG_REASON_TRAP; } - int arena_size; - ut8 *arena = r_reg_get_bytes (dbg->reg, R_REG_TYPE_ALL, &arena_size); - if (!arena) { - eprintf ("Could not retrieve the register arena!\n"); - return false; +} + +static int windbg_stop(RDebug *dbg) { + DbgEngContext *idbg = dbg->user; + r_return_val_if_fail (idbg && idbg->initialized, 0); + return SUCCEEDED (ITHISCALL (dbgCtrl, SetInterrupt, DEBUG_INTERRUPT_ACTIVE)); +} + +static bool do_break = false; + +static void __break(void *user) { + RDebug *dbg = (RDebug *)user; + DbgEngContext *idbg = dbg->user; + if (__is_target_kernel (idbg)) { + windbg_stop (dbg); } - int ret = windbg_write_reg (wctx, arena, arena_size); - free (arena); + do_break = true; +} + +static int windbg_wait(RDebug *dbg, int pid) { + DbgEngContext *idbg = dbg->user; + r_return_val_if_fail (idbg && idbg->initialized, 0); + ULONG Type, ProcessId, ThreadId; + r_cons_break_push (__break, dbg); + const ULONG timeout = __is_target_kernel (idbg) ? INFINITE : TIMEOUT; + HRESULT hr; + while ((hr = ITHISCALL (dbgCtrl, WaitForEvent, DEBUG_WAIT_DEFAULT, timeout)) == S_FALSE) { + if (do_break) { + ITHISCALL (dbgCtrl, SetExecutionStatus, DEBUG_STATUS_BREAK); + do_break = false; + r_cons_break_pop (); + return R_DEBUG_REASON_USERSUSP; + } + } + r_cons_break_pop (); + if (FAILED (hr)) { + return R_DEBUG_REASON_DEAD; + } + ITHISCALL (dbgCtrl, GetLastEventInformation, &Type, &ProcessId, &ThreadId, NULL, 0, NULL, NULL, 0, NULL); + if (!__is_target_kernel (idbg)) { + ITHISCALL (dbgSysObj, GetCurrentProcessSystemId, &dbg->pid); + ITHISCALL (dbgSysObj, GetCurrentThreadSystemId, &dbg->tid); + } else { + dbg->pid = ProcessId; + dbg->tid = ThreadId; + } + int ret; + switch (Type) { + case 0: + // I dont really get why Type is zero here + if (idbg->lastExecutionStatus == DEBUG_STATUS_STEP_INTO + || idbg->lastExecutionStatus == DEBUG_STATUS_STEP_OVER) { + ret = R_DEBUG_REASON_STEP; + } else { + ret = R_DEBUG_REASON_ERROR; + } + break; + case DEBUG_EVENT_BREAKPOINT: + ret = R_DEBUG_REASON_BREAKPOINT; + break; + case DEBUG_EVENT_EXCEPTION: { + EXCEPTION_RECORD64 exr; + ITHISCALL (dbgCtrl, GetLastEventInformation, &Type, &ProcessId, &ThreadId, &exr, sizeof (exr), NULL, NULL, 0, NULL); + dbg->reason.type = exception_to_reason (exr.ExceptionCode); + dbg->reason.tid = dbg->tid; + dbg->reason.addr = exr.ExceptionAddress; + dbg->reason.timestamp = r_time_now (); + ret = dbg->reason.type; + break; + } + case DEBUG_EVENT_EXIT_PROCESS: + ret = R_DEBUG_REASON_EXIT_PID; + break; + case DEBUG_EVENT_CREATE_PROCESS: + ret = R_DEBUG_REASON_NEW_PID; + break; + default: + ret = R_DEBUG_REASON_ERROR; + break; + } + return ret; } -static int r_debug_windbg_continue(RDebug *dbg, int pid, int tid, int sig) { - return windbg_continue(wctx); -} - -static RDebugReasonType r_debug_windbg_wait(RDebug *dbg, int pid) { - RDebugReasonType reason = R_DEBUG_REASON_UNKNOWN; - kd_packet_t *pkt = NULL; - kd_stc_64 *stc; - windbg_lock_enter (wctx); - for (;;) { - void *bed = r_cons_sleep_begin (); - int ret = windbg_wait_packet (wctx, KD_PACKET_TYPE_STATE_CHANGE64, &pkt); - r_cons_sleep_end (bed); - if (ret != KD_E_OK || !pkt) { - reason = R_DEBUG_REASON_ERROR; - break; +static int windbg_breakpoint(RBreakpoint *bp, RBreakpointItem *b, bool set) { + static int bp_idx = 0; + RDebug *dbg = bp->user; + r_return_val_if_fail (dbg, 0); + DbgEngContext *idbg = dbg->user; + r_return_val_if_fail (idbg && idbg->initialized, 0); + ULONG type = b->hw ? DEBUG_BREAKPOINT_DATA : DEBUG_BREAKPOINT_CODE; + PDEBUG_BREAKPOINT bkpt; + if (FAILED (ITHISCALL (dbgCtrl, GetBreakpointById, b->internal, &bkpt))) { + HRESULT hr; + do { + b->internal = InterlockedIncrement (&bp_idx); + hr = ITHISCALL (dbgCtrl, AddBreakpoint, type, b->internal, &bkpt); + } while (hr == E_INVALIDARG); + if (FAILED (hr)) { + return 0; } - stc = (kd_stc_64 *) pkt->data; - dbg->reason.addr = stc->pc; - dbg->reason.tid = stc->kthread; - dbg->reason.signum = stc->state; - windbg_set_cpu (wctx, stc->cpu); - if (stc->state == DbgKdExceptionStateChange) { - dbg->reason.type = R_DEBUG_REASON_INT; - reason = R_DEBUG_REASON_INT; - break; - } else if (stc->state == DbgKdLoadSymbolsStateChange) { - dbg->reason.type = R_DEBUG_REASON_NEW_LIB; - reason = R_DEBUG_REASON_NEW_LIB; - break; + } + ULONG flags; + THISCALL (bkpt, GetFlags, &flags); + flags = set ? flags | DEBUG_BREAKPOINT_ENABLED : flags & ~DEBUG_BREAKPOINT_ENABLED; + if (b->hw) { + ULONG access_type = 0; + if (b->perm & R_BP_PROT_EXEC) { + access_type |= DEBUG_BREAK_EXECUTE; } - R_FREE (pkt); + if (b->perm & R_BP_PROT_READ) { + access_type |= DEBUG_BREAK_READ; + } + if (b->perm & R_BP_PROT_WRITE) { + access_type |= DEBUG_BREAK_WRITE; + } + if (b->perm & R_BP_PROT_ACCESS) { + access_type |= DEBUG_BREAK_READ; + access_type |= DEBUG_BREAK_WRITE; + } + THISCALL (bkpt, SetDataParameters, b->size, access_type); } - windbg_lock_leave (wctx); - free (pkt); - return reason; + THISCALL (bkpt, SetFlags, flags); + THISCALL (bkpt, GetCurrentPassCount, &b->togglehits); + THISCALL (bkpt, SetOffset, b->addr); + return 1; } -static int r_debug_windbg_attach(RDebug *dbg, int pid) { - RIODesc *desc = dbg->iob.io->desc; - - if (!desc || !desc->plugin || !desc->plugin->name || !desc->data) { - return false; - } - if (strncmp (desc->plugin->name, "windbg", 6)) { - return false; - } - if (dbg->arch && strcmp (dbg->arch, "x86")) { - return false; - } - wctx = (WindCtx *)desc->data; - - // Handshake - if (!windbg_sync (wctx)) { - eprintf ("Could not connect to windbg\n"); - windbg_ctx_free ((WindCtx **)&desc->data); - return false; - } - if (!windbg_read_ver (wctx)) { - windbg_ctx_free ((WindCtx **)&desc->data); - return false; - } - dbg->bits = windbg_get_bits (wctx); - // Make r_debug_is_dead happy - dbg->pid = 0; - return true; -} - -static int r_debug_windbg_detach(RDebug *dbg, int pid) { - eprintf ("Detaching...\n"); - return true; -} - -static char *r_debug_windbg_reg_profile(RDebug *dbg) { - if (!dbg) { - return NULL; - } - if (dbg->arch && strcmp (dbg->arch, "x86")) { - return NULL; - } - r_debug_windbg_attach (dbg, 0); - if (dbg->bits == R_SYS_BITS_32) { -#include "native/reg/windows-x86.h" - } else if (dbg->bits == R_SYS_BITS_64) { +static char *windbg_reg_profile(RDebug *dbg) { + DbgEngContext *idbg = dbg->user; + ULONG type; + if (!idbg || !idbg->initialized || FAILED (ITHISCALL (dbgCtrl, GetActualProcessorType, &type))) { + if (dbg->bits & R_SYS_BITS_64) { #include "native/reg/windows-x64.h" + } else { +#include "native/reg/windows-x86.h" + } + return NULL; + } + if (type == IMAGE_FILE_MACHINE_IA64 || type == IMAGE_FILE_MACHINE_AMD64) { +#include "native/reg/windows-x64.h" + } else if (type == IMAGE_FILE_MACHINE_I386) { +#include "native/reg/windows-x86.h" + } else if (type == IMAGE_FILE_MACHINE_ARM) { +#include "native/reg/windows-arm.h" + } else if (type == IMAGE_FILE_MACHINE_ARM64) { +#include "native/reg/windows-arm64.h" } return NULL; } -static int r_debug_windbg_breakpoint(RBreakpoint *bp, RBreakpointItem *b, bool set) { - int *tag; - if (!b) { - return false; +static int windbg_reg_read(RDebug *dbg, int type, ut8 *buf, int size) { + DbgEngContext *idbg = dbg->user; + r_return_val_if_fail (idbg && idbg->initialized, 0); + if (!idbg || !idbg->initialized || FAILED (ITHISCALL (dbgCtrl, GetActualProcessorType, &type))) { + return 0; } - // Use a 32 bit word here to keep this compatible with 32 bit hosts - if (!b->data) { - b->data = (char *)R_NEW0 (int); - if (!b->data) { - return 0; - } + if (type == IMAGE_FILE_MACHINE_IA64 || type == IMAGE_FILE_MACHINE_AMD64) { + DWORD *b = (DWORD *)(buf + 0x30); + *b |= 0xff | CONTEXT_AMD64; + } else if (type == IMAGE_FILE_MACHINE_I386) { + DWORD *b = (DWORD *)buf; + *b |= 0xff | CONTEXT_i386; + } else if (type == IMAGE_FILE_MACHINE_ARM64) { + DWORD *b = (DWORD *)buf; + *b |= 0xff | CONTEXT_ARM64; + } else if (type == IMAGE_FILE_MACHINE_ARM64) { + DWORD *b = (DWORD *)buf; + *b |= 0xff | CONTEXT_ARM; } - tag = (int *)b->data; - return windbg_bkpt (wctx, b->addr, set, b->hw, tag); + if (SUCCEEDED (ITHISCALL (dbgAdvanced, GetThreadContext, (PVOID)buf, size))) { + return size; + } + return 0; +} +static int windbg_reg_write(RDebug *dbg, int type, const ut8 *buf, int size) { + DbgEngContext *idbg = dbg->user; + r_return_val_if_fail (idbg && idbg->initialized, 0); + if (SUCCEEDED (ITHISCALL (dbgAdvanced, SetThreadContext, (PVOID)buf, size))) { + return size; + } + return 0; } -static int r_debug_windbg_init(RDebug *dbg) { +static RList *windbg_frames(RDebug *dbg, ut64 at) { + DbgEngContext *idbg = dbg->user; + r_return_val_if_fail (idbg && idbg->initialized, 0); + const size_t frame_cnt = 128; + PDEBUG_STACK_FRAME dbgframes = R_NEWS (DEBUG_STACK_FRAME, frame_cnt); + if (!dbgframes) { + return NULL; + } + ULONG frames_filled; + if (FAILED (ITHISCALL (dbgCtrl, GetStackTrace, 0, 0, 0, dbgframes, frame_cnt, &frames_filled))) { + free (dbgframes); + return NULL; + } + RList *frames = r_list_newf (free); + size_t i; + for (i = 0; i < frames_filled; i++) { + RDebugFrame *f = R_NEW0 (RDebugFrame); + if (!f) { + break; + } + f->sp = dbgframes[i].StackOffset; + f->bp = dbgframes[i].FrameOffset; + f->addr = dbgframes[i].ReturnOffset; + f->size = f->bp - f->sp; + r_list_append (frames, f); + } + return frames; +} + +static RList *windbg_modules_get(RDebug *dbg) { + DbgEngContext *idbg = dbg->user; + r_return_val_if_fail (idbg && idbg->initialized, 0); + ULONG mod_cnt, mod_un_cnt; + if (FAILED (ITHISCALL (dbgSymbols, GetNumberModules, &mod_cnt, &mod_un_cnt))) { + return NULL; + } + if (!mod_cnt) { + return NULL; + } + PDEBUG_MODULE_PARAMETERS params = R_NEWS (DEBUG_MODULE_PARAMETERS, mod_cnt); + if (!params) { + return NULL; + } + if (FAILED (ITHISCALL (dbgSymbols, GetModuleParameters, mod_cnt, 0, 0, params))) { + return NULL; + } + RList *modules_list = r_list_newf ((RListFree)r_debug_map_free); + if (!modules_list) { + return NULL; + } + size_t i; + for (i = 0; i < mod_cnt; i++) { + char *mod_name = malloc (params[i].ModuleNameSize); + char *image_name = malloc (params[i].ImageNameSize); + if (!mod_name || !image_name) { + free (mod_name); + free (image_name); + break; + } + if (FAILED ( + ITHISCALL (dbgSymbols, GetModuleNames, + DEBUG_ANY_ID, params[i].Base, + image_name, params[i].ImageNameSize, NULL, + mod_name, params[i].ModuleNameSize, NULL, + NULL, 0, NULL))) { + free (mod_name); + free (image_name); + break; + } + RDebugMap *mod = r_debug_map_new (mod_name, params[i].Base, params[i].Base + params[i].Size, 0, params[i].Size); + if (mod) { + mod->file = strdup (image_name); + r_list_append (modules_list, mod); + } + free (mod_name); + free (image_name); + } + return modules_list; +} + +static RList *windbg_map_get(RDebug *dbg) { + DbgEngContext *idbg = dbg->user; + r_return_val_if_fail (idbg && idbg->initialized, NULL); + int perm; + ULONG64 to = 0ULL; + MEMORY_BASIC_INFORMATION64 mbi; + RList *mod_list = windbg_modules_get (dbg); + RList *map_list = r_list_newf ((RListFree)r_debug_map_free); + const int mod_cnt = mod_list ? r_list_length (mod_list) : 0; + PIMAGE_NT_HEADERS64 h = R_NEWS (IMAGE_NT_HEADERS64, mod_cnt); + PIMAGE_SECTION_HEADER *s = R_NEWS0 (PIMAGE_SECTION_HEADER, mod_cnt); + RListIter *it; + RDebugMap *mod = NULL; + size_t i = 0; + r_list_foreach (mod_list, it, mod) { + if (FAILED (ITHISCALL (dbgData, ReadImageNtHeaders, mod->addr, h + i))) { + memset (h + i, 0, sizeof (IMAGE_NT_HEADERS64)); + } else { + IMAGE_DOS_HEADER dos; + ITHISCALL (dbgData, ReadVirtual, mod->addr, (PVOID)&dos, sizeof (IMAGE_DOS_HEADER), NULL); + const size_t header_size = h[i].OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC + ? sizeof (IMAGE_NT_HEADERS32) + : sizeof (IMAGE_NT_HEADERS64); + ULONG64 offset = mod->addr + dos.e_lfanew + header_size; + const ULONG size = sizeof (IMAGE_SECTION_HEADER) * h[i].FileHeader.NumberOfSections; + s[i] = malloc (size); + ITHISCALL (dbgData, ReadVirtual, offset, (PVOID)s[i], size, NULL); + } + i++; + } + ULONG page_size = 1; + ITHISCALL (dbgCtrl, GetPageSize, &page_size); + ULONG p_mask = page_size - 1; + while (SUCCEEDED (ITHISCALL (dbgData, QueryVirtual, to, &mbi))) { + to = mbi.BaseAddress + mbi.RegionSize; + perm = 0; + perm |= mbi.Protect & PAGE_READONLY ? R_PERM_R : 0; + perm |= mbi.Protect & PAGE_READWRITE ? R_PERM_RW : 0; + perm |= mbi.Protect & PAGE_EXECUTE ? R_PERM_X : 0; + perm |= mbi.Protect & PAGE_EXECUTE_READ ? R_PERM_RX : 0; + perm |= mbi.Protect & PAGE_EXECUTE_READWRITE ? R_PERM_RWX : 0; + perm = mbi.Protect & PAGE_NOACCESS ? 0 : perm; + if (!perm) { + continue; + } + char *name = ""; + if (mbi.Type == MEM_IMAGE) { + i = 0; + r_list_foreach (mod_list, it, mod) { + if (mbi.BaseAddress >= mod->addr && mbi.BaseAddress < mod->addr + mod->size) { + break; + } + i++; + } + if (i < mod_cnt && mod) { + size_t j; + for (j = 0; j < h[i].FileHeader.NumberOfSections; j++) { + ut64 sect_vaddr = mod->addr + s[i][j].VirtualAddress; + ut64 sect_vsize = (((ut64)s[i][j].Misc.VirtualSize) + p_mask) & ~p_mask; + if (mbi.BaseAddress >= sect_vaddr && mbi.BaseAddress < sect_vaddr + sect_vsize) { + name = sdb_fmt ("%s | %.8s", mod->name, s[i][j].Name); + break; + } + } + if (!*name) { + name = mod->name; + } + } + } + RDebugMap *map = r_debug_map_new (name, mbi.BaseAddress, to, perm, 0); + r_list_append (map_list, map); + } + for (i = 0; i < mod_cnt; i++) { + free (s[i]); + } + free (s); + free (h); + r_list_free (mod_list); + return map_list; +} + +static int windbg_attach(RDebug *dbg, int pid) { + ULONG Id = 0; + DbgEngContext *idbg = dbg->user; + r_return_val_if_fail (idbg && idbg->initialized, -1); + if (SUCCEEDED (ITHISCALL (dbgSysObj, GetCurrentProcessSystemId, &Id))) { + if (Id == pid && SUCCEEDED (ITHISCALL (dbgSysObj, GetCurrentThreadSystemId, &Id))) { + return Id; + } + } + if (SUCCEEDED (ITHISCALL (dbgClient, AttachProcess, idbg->server, pid, DEBUG_ATTACH_DEFAULT))) { + return windbg_wait (dbg, pid); + } + return -1; +} + +static int windbg_detach(RDebug *dbg, int pid) { + DbgEngContext *idbg = dbg->user; + r_return_val_if_fail (idbg && idbg->initialized, 0); + return SUCCEEDED (ITHISCALL (dbgClient, DetachProcesses)); +} + +static bool windbg_kill(RDebug *dbg, int pid, int tid, int sig) { + DbgEngContext *idbg = dbg->user; + r_return_val_if_fail (idbg && idbg->initialized, false); + if (!sig) { + ULONG exit_code, class, qualifier; + if (SUCCEEDED (ITHISCALL (dbgCtrl, GetDebuggeeType, &class, &qualifier))) { + if (class == DEBUG_CLASS_UNINITIALIZED) { + return false; + } + if (qualifier >= DEBUG_DUMP_SMALL && qualifier <= DEBUG_DUMP_ACTIVE) { + return true; + } + } + if (FAILED (ITHISCALL (dbgClient, GetExitCode, &exit_code))) { + return false; + } + return exit_code == STILL_ACTIVE; + } + HRESULT hr = ITHISCALL (dbgClient, TerminateProcesses); + return SUCCEEDED (hr); +} + +static RList *windbg_threads(RDebug *dbg, int pid) { + DbgEngContext *idbg = dbg->user; + r_return_val_if_fail (idbg && idbg->initialized, NULL); + ULONG thread_cnt = 0; + ITHISCALL (dbgSysObj, GetNumberThreads, &thread_cnt); + if (!thread_cnt) { + return NULL; + } + PULONG threads_ids = R_NEWS (ULONG, thread_cnt); + PULONG threads_sysids = R_NEWS (ULONG, thread_cnt); + RList *list = r_list_newf ((RListFree)r_debug_pid_free); + if (!list || !threads_ids || !threads_sysids) { + free (list); + free (threads_ids); + free (threads_sysids); + return NULL; + } + ITHISCALL (dbgSysObj, GetThreadIdsByIndex, 0, thread_cnt, threads_ids, threads_sysids); + size_t i; + for (i = 0; i < thread_cnt; i++) { + ULONG64 pc; + ITHISCALL (dbgSysObj, SetCurrentThreadId, threads_ids[i]); + ITHISCALL (dbgReg, GetInstructionOffset, &pc); + r_list_append (list, r_debug_pid_new (NULL, threads_sysids[i], 0, 's', pc)); + } + windbg_select (dbg, dbg->pid, dbg->tid); + free (threads_ids); + free (threads_sysids); + return list; +} + +static RDebugInfo *windbg_info(RDebug *dbg, const char *arg) { + DbgEngContext *idbg = dbg->user; + r_return_val_if_fail (idbg && idbg->initialized, NULL); + char exeinfo[MAX_PATH]; + char cmdline[MAX_PATH]; + if (SUCCEEDED (ITHISCALL (dbgClient, GetRunningProcessDescription, idbg->server, dbg->pid, DEBUG_PROC_DESC_NO_SERVICES | DEBUG_PROC_DESC_NO_MTS_PACKAGES, exeinfo, MAX_PATH, NULL, cmdline, MAX_PATH, NULL))) { + RDebugInfo *info = R_NEW0 (RDebugInfo); + if (!info) { + return NULL; + } + info->pid = dbg->pid; + info->tid = dbg->tid; + info->exe = strdup (exeinfo); + info->cmdline = strdup (cmdline); + } + return NULL; +} + +static bool windbg_gcore(RDebug *dbg, RBuffer *dest) { + DbgEngContext *idbg = dbg->user; + r_return_val_if_fail (idbg && idbg->initialized, false); + char *path = r_sys_getenv (R_SYS_TMP); + if (R_STR_ISEMPTY (path)) { + free (path); + path = r_sys_getdir (); + if (R_STR_ISEMPTY (path)) { + free (path); + return false; + } + } + path = r_str_appendf (path, "\\core.%d", dbg->pid); + ITHISCALL (dbgClient, WriteDumpFile, path, DEBUG_DUMP_DEFAULT); + free (path); return true; } -static RList *r_debug_windbg_pids(RDebug *dbg, int pid) { - RListIter *it; - WindProc *p; - - RList *ret = r_list_newf (free); - if (!ret) { - return NULL; - } - - RList *pids = windbg_list_process(wctx); - if (!pids) { - return ret; - } - r_list_foreach (pids, it, p) { - RDebugPid *newpid = R_NEW0 (RDebugPid); - if (!newpid) { - r_list_free (ret); - return NULL; +RList *windbg_pids(RDebug *dbg, int pid) { + DbgEngContext *idbg = dbg->user; + r_return_val_if_fail (idbg && idbg->initialized, NULL); + RList *list = r_list_newf ((RListFree)r_debug_pid_free); + ULONG ids[1000]; + ULONG ids_cnt; + if (SUCCEEDED (ITHISCALL (dbgClient, GetRunningProcessSystemIds, + idbg->server, ids, _countof (ids), &ids_cnt))) { + size_t i; + for (i = 0; i < ids_cnt; i++) { + char path[MAX_PATH]; + if (SUCCEEDED (ITHISCALL (dbgClient, GetRunningProcessDescription, + idbg->server, ids[i], DEBUG_PROC_DESC_DEFAULT, + path, sizeof (path), NULL, NULL, 0, NULL))) { + RDebugPid *pid = r_debug_pid_new (path, ids[i], 0, 'r', 0); + r_list_append (list, pid); + } } - newpid->path = strdup (p->name); - newpid->pid = p->uniqueid; - newpid->status = 's'; - newpid->runnable = true; - r_list_append (ret, newpid); } - // r_list_free (pids); - return ret; -} - -static int r_debug_windbg_select(RDebug *dbg, int pid, int tid) { - ut32 old = windbg_get_target (wctx); - int ret = windbg_set_target (wctx, pid); - if (!ret) { - return false; - } - ut64 base = windbg_get_target_base (wctx); - if (!base) { - windbg_set_target (wctx, old); - return false; - } - eprintf ("Process base is 0x%"PFMT64x"\n", base); - return true; -} - -static RList *r_debug_windbg_threads(RDebug *dbg, int pid) { - RListIter *it; - WindThread *t; - - RList *ret = r_list_newf (free); - if (!ret) { - return NULL; - } - - RList *threads = windbg_list_threads (wctx); - if (!threads) { - r_list_free (ret); - return NULL; - } - - r_list_foreach (threads, it, t) { - RDebugPid *newpid = R_NEW0 (RDebugPid); - if (!newpid) { - r_list_free (ret); - return NULL; - } - newpid->pid = t->uniqueid; - newpid->status = t->status; - newpid->runnable = t->runnable; - r_list_append (ret, newpid); - } - - return ret; -} - -static RList *r_debug_windbg_modules(RDebug *dbg) { - RListIter *it; - WindModule *m; - - RList *ret = r_list_newf (free); - if (!ret) { - return NULL; - } - - RList *modules = windbg_list_modules (wctx); - if (!modules) { - r_list_free (ret); - return NULL; - } - - r_list_foreach (modules, it, m) { - RDebugMap *mod = R_NEW0 (RDebugMap); - if (!mod) { - r_list_free (modules); - r_list_free (ret); - return NULL; - } - mod->file = m->name; - mod->size = m->size; - mod->addr = m->addr; - mod->addr_end = m->addr + m->size; - r_list_append (ret, mod); - } - - r_list_free (modules); - return ret; + return list; } RDebugPlugin r_debug_plugin_windbg = { .name = "windbg", .license = "LGPL3", - .arch = "x86", - .bits = R_SYS_BITS_32 | R_SYS_BITS_64, - .init = &r_debug_windbg_init, - .step = &r_debug_windbg_step, - .cont = &r_debug_windbg_continue, - .attach = &r_debug_windbg_attach, - .detach = &r_debug_windbg_detach, - .pids = &r_debug_windbg_pids, - .wait = &r_debug_windbg_wait, - .select = &r_debug_windbg_select, - .breakpoint = r_debug_windbg_breakpoint, - .reg_read = &r_debug_windbg_reg_read, - .reg_write = &r_debug_windbg_reg_write, - .reg_profile = &r_debug_windbg_reg_profile, - .threads = &r_debug_windbg_threads, - .modules_get = &r_debug_windbg_modules + .bits = R_SYS_BITS_64, + .arch = "x86,x64,arm,arm64", + .canstep = 1, + .init = windbg_init, + .attach = windbg_attach, + .detach = windbg_detach, + .breakpoint = windbg_breakpoint, + .frames = windbg_frames, + .kill = windbg_kill, + .select = windbg_select, + .step = windbg_step, + .step_over = windbg_step_over, + .threads = windbg_threads, + .cont = windbg_continue, + .wait = windbg_wait, + .stop = windbg_stop, + .reg_read = windbg_reg_read, + .reg_write = windbg_reg_write, + .reg_profile = windbg_reg_profile, + .map_get = windbg_map_get, + .modules_get = windbg_modules_get, + .info = windbg_info, + .gcore = windbg_gcore, + .pids = windbg_pids }; #ifndef R2_PLUGIN_INCORE @@ -292,4 +631,4 @@ R_API RLibStruct radare_plugin = { .data = &r_debug_plugin_windbg, .version = R2_VERSION }; -#endif +#endif // R2_PLUGIN_INCORE diff --git a/libr/debug/p/debug_winkd.c b/libr/debug/p/debug_winkd.c new file mode 100644 index 0000000000..7b3882012d --- /dev/null +++ b/libr/debug/p/debug_winkd.c @@ -0,0 +1,295 @@ +// Copyright (c) 2014-2017, The Lemon Man, All rights reserved. LGPLv3 + +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public +// License along with this library. + +#include +#include +#include +#include + +static WindCtx *wctx = NULL; + +static int r_debug_winkd_step(RDebug *dbg) { + return true; +} + +static int r_debug_winkd_reg_read(RDebug *dbg, int type, ut8 *buf, int size) { + int ret = winkd_read_reg(wctx, buf, size); + if (!ret || size != ret) { + return -1; + } + r_reg_read_regs (dbg->reg, buf, ret); + // Report as if no register has been written as we've already updated the arena here + return 0; +} + +static int r_debug_winkd_reg_write(RDebug *dbg, int type, const ut8 *buf, int size) { + if (!dbg->reg) { + return false; + } + int arena_size; + ut8 *arena = r_reg_get_bytes (dbg->reg, R_REG_TYPE_ALL, &arena_size); + if (!arena) { + eprintf ("Could not retrieve the register arena!\n"); + return false; + } + int ret = winkd_write_reg (wctx, arena, arena_size); + free (arena); + return ret; +} + +static int r_debug_winkd_continue(RDebug *dbg, int pid, int tid, int sig) { + return winkd_continue(wctx); +} + +static RDebugReasonType r_debug_winkd_wait(RDebug *dbg, int pid) { + RDebugReasonType reason = R_DEBUG_REASON_UNKNOWN; + kd_packet_t *pkt = NULL; + kd_stc_64 *stc; + winkd_lock_enter (wctx); + for (;;) { + void *bed = r_cons_sleep_begin (); + int ret = winkd_wait_packet (wctx, KD_PACKET_TYPE_STATE_CHANGE64, &pkt); + r_cons_sleep_end (bed); + if (ret != KD_E_OK || !pkt) { + reason = R_DEBUG_REASON_ERROR; + break; + } + stc = (kd_stc_64 *) pkt->data; + dbg->reason.addr = stc->pc; + dbg->reason.tid = stc->kthread; + dbg->reason.signum = stc->state; + winkd_set_cpu (wctx, stc->cpu); + if (stc->state == DbgKdExceptionStateChange) { + dbg->reason.type = R_DEBUG_REASON_INT; + reason = R_DEBUG_REASON_INT; + break; + } else if (stc->state == DbgKdLoadSymbolsStateChange) { + dbg->reason.type = R_DEBUG_REASON_NEW_LIB; + reason = R_DEBUG_REASON_NEW_LIB; + break; + } + R_FREE (pkt); + } + winkd_lock_leave (wctx); + free (pkt); + return reason; +} + +static int r_debug_winkd_attach(RDebug *dbg, int pid) { + RIODesc *desc = dbg->iob.io->desc; + + if (!desc || !desc->plugin || !desc->plugin->name || !desc->data) { + return false; + } + if (strncmp (desc->plugin->name, "winkd", 6)) { + return false; + } + if (dbg->arch && strcmp (dbg->arch, "x86")) { + return false; + } + wctx = (WindCtx *)desc->data; + + // Handshake + if (!winkd_sync (wctx)) { + eprintf ("Could not connect to winkd\n"); + winkd_ctx_free ((WindCtx **)&desc->data); + return false; + } + if (!winkd_read_ver (wctx)) { + winkd_ctx_free ((WindCtx **)&desc->data); + return false; + } + dbg->bits = winkd_get_bits (wctx); + // Make r_debug_is_dead happy + dbg->pid = 0; + return true; +} + +static int r_debug_winkd_detach(RDebug *dbg, int pid) { + eprintf ("Detaching...\n"); + return true; +} + +static char *r_debug_winkd_reg_profile(RDebug *dbg) { + if (!dbg) { + return NULL; + } + if (dbg->arch && strcmp (dbg->arch, "x86")) { + return NULL; + } + r_debug_winkd_attach (dbg, 0); + if (dbg->bits == R_SYS_BITS_32) { +#include "native/reg/windows-x86.h" + } else if (dbg->bits == R_SYS_BITS_64) { +#include "native/reg/windows-x64.h" + } + return NULL; +} + +static int r_debug_winkd_breakpoint(RBreakpoint *bp, RBreakpointItem *b, bool set) { + int *tag; + if (!b) { + return false; + } + // Use a 32 bit word here to keep this compatible with 32 bit hosts + if (!b->data) { + b->data = (char *)R_NEW0 (int); + if (!b->data) { + return 0; + } + } + tag = (int *)b->data; + return winkd_bkpt (wctx, b->addr, set, b->hw, tag); +} + +static int r_debug_winkd_init(RDebug *dbg) { + return true; +} + +static RList *r_debug_winkd_pids(RDebug *dbg, int pid) { + RListIter *it; + WindProc *p; + + RList *ret = r_list_newf (free); + if (!ret) { + return NULL; + } + + RList *pids = winkd_list_process(wctx); + if (!pids) { + return ret; + } + r_list_foreach (pids, it, p) { + RDebugPid *newpid = R_NEW0 (RDebugPid); + if (!newpid) { + r_list_free (ret); + return NULL; + } + newpid->path = strdup (p->name); + newpid->pid = p->uniqueid; + newpid->status = 's'; + newpid->runnable = true; + r_list_append (ret, newpid); + } + // r_list_free (pids); + return ret; +} + +static int r_debug_winkd_select(RDebug *dbg, int pid, int tid) { + ut32 old = winkd_get_target (wctx); + int ret = winkd_set_target (wctx, pid); + if (!ret) { + return false; + } + ut64 base = winkd_get_target_base (wctx); + if (!base) { + winkd_set_target (wctx, old); + return false; + } + eprintf ("Process base is 0x%"PFMT64x"\n", base); + return true; +} + +static RList *r_debug_winkd_threads(RDebug *dbg, int pid) { + RListIter *it; + WindThread *t; + + RList *ret = r_list_newf (free); + if (!ret) { + return NULL; + } + + RList *threads = winkd_list_threads (wctx); + if (!threads) { + r_list_free (ret); + return NULL; + } + + r_list_foreach (threads, it, t) { + RDebugPid *newpid = R_NEW0 (RDebugPid); + if (!newpid) { + r_list_free (ret); + return NULL; + } + newpid->pid = t->uniqueid; + newpid->status = t->status; + newpid->runnable = t->runnable; + r_list_append (ret, newpid); + } + + return ret; +} + +static RList *r_debug_winkd_modules(RDebug *dbg) { + RListIter *it; + WindModule *m; + + RList *ret = r_list_newf (free); + if (!ret) { + return NULL; + } + + RList *modules = winkd_list_modules (wctx); + if (!modules) { + r_list_free (ret); + return NULL; + } + + r_list_foreach (modules, it, m) { + RDebugMap *mod = R_NEW0 (RDebugMap); + if (!mod) { + r_list_free (modules); + r_list_free (ret); + return NULL; + } + mod->file = m->name; + mod->size = m->size; + mod->addr = m->addr; + mod->addr_end = m->addr + m->size; + r_list_append (ret, mod); + } + + r_list_free (modules); + return ret; +} + +RDebugPlugin r_debug_plugin_winkd = { + .name = "winkd", + .license = "LGPL3", + .arch = "x86", + .bits = R_SYS_BITS_32 | R_SYS_BITS_64, + .init = &r_debug_winkd_init, + .step = &r_debug_winkd_step, + .cont = &r_debug_winkd_continue, + .attach = &r_debug_winkd_attach, + .detach = &r_debug_winkd_detach, + .pids = &r_debug_winkd_pids, + .wait = &r_debug_winkd_wait, + .select = &r_debug_winkd_select, + .breakpoint = r_debug_winkd_breakpoint, + .reg_read = &r_debug_winkd_reg_read, + .reg_write = &r_debug_winkd_reg_write, + .reg_profile = &r_debug_winkd_reg_profile, + .threads = &r_debug_winkd_threads, + .modules_get = &r_debug_winkd_modules +}; + +#ifndef R2_PLUGIN_INCORE +R_API RLibStruct radare_plugin = { + .type = R_LIB_TYPE_DBG, + .data = &r_debug_plugin_winkd, + .version = R2_VERSION +}; +#endif diff --git a/libr/debug/p/native/maps/windows_maps.c b/libr/debug/p/native/maps/windows_maps.c index 084f8984cd..7c5c289840 100644 --- a/libr/debug/p/native/maps/windows_maps.c +++ b/libr/debug/p/native/maps/windows_maps.c @@ -201,7 +201,7 @@ static void proc_mem_img(HANDLE h_proc, RList *map_list, RList *mod_list, RWinMo sect_found = 2; } if (sect_found) { - char *map_name = r_str_newf ("%s | %s", mod->map->name, sect_hdr->Name); + char *map_name = r_str_newf ("%s | %.8s", mod->map->name, sect_hdr->Name); if (!map_name) { perror ("r_str_newf"); return; diff --git a/libr/debug/p/native/reg/windows-arm.h b/libr/debug/p/native/reg/windows-arm.h new file mode 100644 index 0000000000..fbca1f7d2f --- /dev/null +++ b/libr/debug/p/native/reg/windows-arm.h @@ -0,0 +1,71 @@ +return strdup ( +"=PC pc\n" +"=SP sp\n" +"=BP fp\n" +"=A0 r0\n" +"=A1 r1\n" +"=A2 r2\n" +"=A3 r3\n" +"=ZF zf\n" +"=SF nf\n" +"=OF vf\n" +"=CF cf\n" +"gpr r0 .32 4 0\n" +"gpr r1 .32 8 0\n" +"gpr r2 .32 12 0\n" +"gpr r3 .32 16 0\n" +"gpr r4 .32 20 0\n" +"gpr r5 .32 24 0\n" +"gpr r6 .32 28 0\n" +"gpr r7 .32 32 0\n" +"gpr r8 .32 36 0\n" +"gpr r9 .32 40 0\n" +"gpr r10 .32 44 0\n" +"gpr r11 .32 48 0\n" +"gpr r12 .32 52 0\n" +"gpr sp .32 56 0\n" +"gpr lr .32 60 0\n" +"gpr pc .32 64 0\n" +"flg cpsr .32 68 0 _____tfiae_____________j__qvczn\n" +"flg vf .1 68.28 0 overflow\n" +"flg cf .1 68.29 0 carry\n" +"flg zf .1 68.30 0 zero\n" +"flg nf .1 68.31 0 sign\n" +"gpr fpsr .32 72 0\n" +"fpu q0 .128 76 0\n" +"fpu q1 .128 92 0\n" +"fpu q2 .128 108 0\n" +"fpu q3 .128 124 0\n" +"fpu q4 .128 140 0\n" +"fpu q5 .128 156 0\n" +"fpu q6 .128 172 0\n" +"fpu q7 .128 188 0\n" +"fpu q8 .128 204 0\n" +"fpu q9 .128 220 0\n" +"fpu q10 .128 236 0\n" +"fpu q11 .128 252 0\n" +"fpu q12 .128 268 0\n" +"fpu q13 .128 284 0\n" +"fpu q14 .128 300 0\n" +"fpu q15 .128 316 0\n" +"drx bcr0 .32 332 0\n" +"drx bcr1 .32 336 0\n" +"drx bcr2 .32 340 0\n" +"drx bcr3 .32 344 0\n" +"drx bcr4 .32 348 0\n" +"drx bcr5 .32 352 0\n" +"drx bcr6 .32 356 0\n" +"drx bcr7 .32 360 0\n" +"drx bvr0 .32 364 0\n" +"drx bvr1 .32 368 0\n" +"drx bvr2 .32 372 0\n" +"drx bvr3 .32 376 0\n" +"drx bvr4 .32 380 0\n" +"drx bvr5 .32 384 0\n" +"drx bvr6 .32 388 0\n" +"drx bvr7 .32 392 0\n" +"drx wcr0 .32 396 0\n" +"drx wcr1 .32 400 0\n" +"drx wvr0 .32 404 0\n" +"drx wvr1 .32 408 0\n" +); diff --git a/libr/debug/p/native/reg/windows-arm64.h b/libr/debug/p/native/reg/windows-arm64.h new file mode 100644 index 0000000000..5142e0bf75 --- /dev/null +++ b/libr/debug/p/native/reg/windows-arm64.h @@ -0,0 +1,106 @@ +return strdup ( +"=PC pc\n" +"=SP sp\n" +"=BP fp\n" +"=A0 x0\n" +"=A1 x1\n" +"=A2 x2\n" +"=A3 x3\n" +"=ZF zf\n" +"=SF nf\n" +"=OF vf\n" +"=CF cf\n" +"=SN x16\n" +"flg cpsr .32 4 0 _____tfiae_____________j__qvczn\n" +"flg vf .1 4.28 0 overflow\n" +"flg cf .1 4.29 0 carry\n" +"flg zf .1 4.30 0 zero\n" +"flg nf .1 4.31 0 sign\n" +"gpr x0 .64 8 0\n" +"gpr x1 .64 16 0\n" +"gpr x2 .64 24 0\n" +"gpr x3 .64 32 0\n" +"gpr x4 .64 40 0\n" +"gpr x5 .64 48 0\n" +"gpr x6 .64 56 0\n" +"gpr x7 .64 64 0\n" +"gpr x8 .64 72 0\n" +"gpr x9 .64 80 0\n" +"gpr x10 .64 88 0\n" +"gpr x11 .64 96 0\n" +"gpr x12 .64 104 0\n" +"gpr x13 .64 112 0\n" +"gpr x14 .64 120 0\n" +"gpr x15 .64 128 0\n" +"gpr x16 .64 136 0\n" +"gpr x17 .64 144 0\n" +"gpr x18 .64 152 0\n" +"gpr x19 .64 160 0\n" +"gpr x20 .64 168 0\n" +"gpr x21 .64 176 0\n" +"gpr x22 .64 184 0\n" +"gpr x23 .64 192 0\n" +"gpr x24 .64 200 0\n" +"gpr x25 .64 208 0\n" +"gpr x26 .64 216 0\n" +"gpr x27 .64 224 0\n" +"gpr x28 .64 232 0\n" +"gpr fp .64 240 0\n" +"gpr lr .64 248 0\n" +"gpr sp .64 256 0\n" +"gpr pc .64 264 0\n" +"fpu v0 .128 272 0\n" +"fpu v1 .128 288 0\n" +"fpu v2 .128 304 0\n" +"fpu v3 .128 320 0\n" +"fpu v4 .128 336 0\n" +"fpu v5 .128 352 0\n" +"fpu v6 .128 368 0\n" +"fpu v7 .128 384 0\n" +"fpu v8 .128 400 0\n" +"fpu v9 .128 416 0\n" +"fpu v10 .128 432 0\n" +"fpu v11 .128 448 0\n" +"fpu v12 .128 464 0\n" +"fpu v13 .128 480 0\n" +"fpu v14 .128 496 0\n" +"fpu v15 .128 512 0\n" +"fpu v16 .128 528 0\n" +"fpu v17 .128 544 0\n" +"fpu v18 .128 560 0\n" +"fpu v19 .128 576 0\n" +"fpu v20 .128 592 0\n" +"fpu v21 .128 608 0\n" +"fpu v22 .128 624 0\n" +"fpu v23 .128 640 0\n" +"fpu v24 .128 656 0\n" +"fpu v25 .128 672 0\n" +"fpu v26 .128 688 0\n" +"fpu v27 .128 704 0\n" +"fpu v28 .128 720 0\n" +"fpu v29 .128 736 0\n" +"fpu v30 .128 752 0\n" +"fpu v31 .128 768 0\n" +"gpr fpcr .32 784 0\n" +"gpr fpsr .32 788 0\n" +"drx bcr0 .32 792 0\n" +"drx bcr1 .32 796 0\n" +"drx bcr2 .32 800 0\n" +"drx bcr3 .32 804 0\n" +"drx bcr4 .32 808 0\n" +"drx bcr5 .32 812 0\n" +"drx bcr6 .32 816 0\n" +"drx bcr7 .32 820 0\n" +"drx bvr0 .64 824 0\n" +"drx bvr1 .64 832 0\n" +"drx bvr2 .64 840 0\n" +"drx bvr3 .64 848 0\n" +"drx bvr4 .64 856 0\n" +"drx bvr5 .64 864 0\n" +"drx bvr6 .64 872 0\n" +"drx bvr7 .64 880 0\n" +"drx wcr0 .32 888 0\n" +"drx wcr1 .32 892 0\n" +"drx wvr0 .64 896 0\n" +"drx wvr1 .64 904 0\n" +); diff --git a/libr/debug/p/native/windows/windows_debug.c b/libr/debug/p/native/windows/windows_debug.c index 1eecb258a5..ab8172d358 100644 --- a/libr/debug/p/native/windows/windows_debug.c +++ b/libr/debug/p/native/windows/windows_debug.c @@ -37,14 +37,10 @@ int w32_init(RDebug *dbg) { W32DbgWInst *wrap = dbg->user; if (!wrap) { if (dbg->iob.io->w32dbg_wrap) { - wrap = (W32DbgWInst *)dbg->iob.io->w32dbg_wrap; + dbg->user = (W32DbgWInst *)dbg->iob.io->w32dbg_wrap; } else { - wrap = w32dbg_wrap_new (); - dbg->iob.io->w32dbg_wrap = (struct w32dbg_wrap_instance_t *)wrap; - wrap->pi.dwProcessId = dbg->pid; - wrap->pi.dwThreadId = dbg->tid; + return 0; } - dbg->user = wrap; } // escalate privs (required for win7/vista) setup_debug_privileges (true); diff --git a/libr/debug/p/windbg.mk b/libr/debug/p/windbg.mk deleted file mode 100644 index 4ff53210e6..0000000000 --- a/libr/debug/p/windbg.mk +++ /dev/null @@ -1,24 +0,0 @@ -CFLAGS+=-I$(SHLR)/windbg/ -LIB_PATH=$(SHLR)/windbg/ - --include ../../global.mk --include ../../../global.mk -LDFLAGS+=-L$(LTOP)/util -lr_util -LDFLAGS+=-L$(LTOP)/cons -lr_cons -LDFLAGS+=-L$(LTOP)/parse -lr_parse -LDFLAGS+=-L$(LTOP)/anal -lr_anal -LDFLAGS+=-L$(LTOP)/reg -lr_reg -LDFLAGS+=-L$(LTOP)/bp -lr_bp -LDFLAGS+=-L$(LTOP)/io -lr_io - -include $(STOP)/windbg/deps.mk - -OBJ_WINDBG=debug_windbg.o - -STATIC_OBJ+=${OBJ_WINDBG} -TARGET_WINDBG=debug_windbg.${EXT_SO} - -ALL_TARGETS+=${TARGET_WINDBG} - -${TARGET_WINDBG}: ${OBJ_WINDBG} - ${CC} $(call libname,debug_windbg) ${OBJ_WINDBG} ${CFLAGS} ${LDFLAGS} diff --git a/libr/debug/p/winkd.mk b/libr/debug/p/winkd.mk new file mode 100644 index 0000000000..4740e179ae --- /dev/null +++ b/libr/debug/p/winkd.mk @@ -0,0 +1,24 @@ +CFLAGS+=-I$(SHLR)/winkd/ +LIB_PATH=$(SHLR)/winkd/ + +-include ../../global.mk +-include ../../../global.mk +LDFLAGS+=-L$(LTOP)/util -lr_util +LDFLAGS+=-L$(LTOP)/cons -lr_cons +LDFLAGS+=-L$(LTOP)/parse -lr_parse +LDFLAGS+=-L$(LTOP)/anal -lr_anal +LDFLAGS+=-L$(LTOP)/reg -lr_reg +LDFLAGS+=-L$(LTOP)/bp -lr_bp +LDFLAGS+=-L$(LTOP)/io -lr_io + +include $(STOP)/winkd/deps.mk + +OBJ_WINKD=debug_winkd.o + +STATIC_OBJ+=${OBJ_WINKD} +TARGET_WINKD=debug_winkd.${EXT_SO} + +ALL_TARGETS+=${TARGET_WINKD} + +${TARGET_WINKD}: ${OBJ_WINKD} + ${CC} $(call libname,debug_winkd) ${OBJ_WINKD} ${CFLAGS} ${LDFLAGS} diff --git a/libr/include/r_debug.h b/libr/include/r_debug.h index 1b5ec6b7ab..0535546b79 100644 --- a/libr/include/r_debug.h +++ b/libr/include/r_debug.h @@ -621,6 +621,7 @@ extern RDebugPlugin r_debug_plugin_rap; extern RDebugPlugin r_debug_plugin_gdb; extern RDebugPlugin r_debug_plugin_bf; extern RDebugPlugin r_debug_plugin_io; +extern RDebugPlugin r_debug_plugin_winkd; extern RDebugPlugin r_debug_plugin_windbg; extern RDebugPlugin r_debug_plugin_bochs; extern RDebugPlugin r_debug_plugin_qnx; diff --git a/libr/include/r_io.h b/libr/include/r_io.h index dcfa45fa20..e67a58d16b 100644 --- a/libr/include/r_io.h +++ b/libr/include/r_io.h @@ -478,6 +478,7 @@ extern RIOPlugin r_io_plugin_malloc; extern RIOPlugin r_io_plugin_sparse; extern RIOPlugin r_io_plugin_ptrace; extern RIOPlugin r_io_plugin_w32dbg; +extern RIOPlugin r_io_plugin_windbg; extern RIOPlugin r_io_plugin_mach; extern RIOPlugin r_io_plugin_debug; extern RIOPlugin r_io_plugin_shm; @@ -492,7 +493,7 @@ extern RIOPlugin r_io_plugin_default; extern RIOPlugin r_io_plugin_ihex; extern RIOPlugin r_io_plugin_self; extern RIOPlugin r_io_plugin_gzip; -extern RIOPlugin r_io_plugin_windbg; +extern RIOPlugin r_io_plugin_winkd; extern RIOPlugin r_io_plugin_r2pipe; extern RIOPlugin r_io_plugin_r2web; extern RIOPlugin r_io_plugin_qnx; diff --git a/libr/io/meson.build b/libr/io/meson.build index 5ef137e543..0decf1df96 100644 --- a/libr/io/meson.build +++ b/libr/io/meson.build @@ -35,7 +35,7 @@ r_io_sources = [ 'p/io_shm.c', 'p/io_sparse.c', 'p/io_tcp.c', - 'p/io_windbg.c', + 'p/io_winkd.c', 'p/io_winedbg.c', 'p/io_zip.c', ] @@ -43,6 +43,7 @@ r_io_sources = [ if host_machine.system() == 'windows' r_io_sources += [ 'p/io_r2k_windows.c', + 'p/io_windbg.c', 'p/io_w32.c', 'p/io_w32dbg.c', ] @@ -54,7 +55,7 @@ r_io_deps = [ r_socket_dep, bochs_dep, gdb_dep, - windbg_dep, + winkd_dep, qnx_dep, zip_dep, ar_dep, diff --git a/libr/io/p/Makefile b/libr/io/p/Makefile index e5935451a8..76ee98b786 100644 --- a/libr/io/p/Makefile +++ b/libr/io/p/Makefile @@ -15,7 +15,7 @@ endif all: ${ALL_TARGETS} ALL_TARGETS= -PLUGINS=ptrace.mk debug.mk gdb.mk malloc.mk shm.mk mach.mk w32dbg.mk procpid.mk windbg.mk bochs.mk qnx.mk r2k.mk ar.mk rbuf.mk gprobe.mk +PLUGINS=ptrace.mk debug.mk gdb.mk malloc.mk shm.mk mach.mk w32dbg.mk procpid.mk winkd.mk bochs.mk qnx.mk r2k.mk ar.mk rbuf.mk gprobe.mk #zip.mk #PLUGINS=ptrace.mk debug.mk gdb.mk malloc.mk mach.mk w32dbg.mk procpid.mk include ${PLUGINS} diff --git a/libr/io/p/io_windbg.c b/libr/io/p/io_windbg.c index e54fd058e8..4c640aadb5 100644 --- a/libr/io/p/io_windbg.c +++ b/libr/io/p/io_windbg.c @@ -1,106 +1,687 @@ -// Copyright (c) 2014-2017, The Lemon Man, All rights reserved. LGPLv3 +/* radare - LGPL - Copyright 2020 - GustavoLCR */ -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. +#define INITGUID +#include +#include -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. +typedef HRESULT (__stdcall *DebugCreate_t)( + _In_ REFIID InterfaceId, + _Out_ PVOID *Interface +); -// You should have received a copy of the GNU Lesser General Public -// License along with this library. +typedef HRESULT (__stdcall *DebugConnectWide_t)( + _In_ PCWSTR RemoteOptions, + _In_ REFIID InterfaceId, + _Out_ PVOID *Interface +); -#include -#include -#include -#include -#include -#include +static DebugCreate_t w32_DebugCreate = NULL; +static DebugConnectWide_t w32_DebugConnectWide = NULL; -static bool __plugin_open(RIO *io, const char *file, bool many) { - return (!strncmp (file, "windbg://", 9)); +#define WINDBGURI "windbg://" + +typedef struct { // Keep in sync with debug_windbg.c + bool initialized; + ULONG64 server; + ULONG64 processBase; + DWORD lastExecutionStatus; + PDEBUG_CLIENT5 dbgClient; + PDEBUG_CONTROL4 dbgCtrl; + PDEBUG_DATA_SPACES4 dbgData; + PDEBUG_REGISTERS2 dbgReg; + PDEBUG_SYSTEM_OBJECTS4 dbgSysObj; + PDEBUG_SYMBOLS3 dbgSymbols; + PDEBUG_ADVANCED3 dbgAdvanced; +} DbgEngContext; + +#define THISCALL(dbginterface, function, ...) dbginterface->lpVtbl->function (dbginterface, __VA_ARGS__) +#define ITHISCALL(dbginterface, function, ...) THISCALL (idbg->dbginterface, function, __VA_ARGS__) + +#define DECLARE_CALLBACKS_IMPL(Type, IFace) \ +typedef struct IFace##_impl { \ + IFace *lpVtbl; \ + DbgEngContext *m_idbg; \ + ULONG m_ref; \ +} Type##_IMPL, *P##Type##_IMPL; \ + +#define INIT_IUNKNOWN_CALLBACKS(IFace, lpVtbl) \ +lpVtbl->QueryInterface = IFace##_QueryInterface_impl; \ +lpVtbl->AddRef = IFace##_AddRef_impl; \ +lpVtbl->Release = IFace##_Release_impl \ + +#define DECLARE_NEW(IFace, IVtbl) \ +static P##IFace IFace##_impl_new( \ + DbgEngContext *idbg) { \ + if (!idbg) { \ + return NULL; \ + } \ + P##IFace##_IMPL callbacks = R_NEW (IFace##_IMPL); \ + if (!callbacks) { \ + return NULL; \ + } \ + callbacks->lpVtbl = R_NEW (IVtbl); \ + if (!callbacks->lpVtbl) { \ + free (callbacks); \ + return NULL; \ + } \ + IFace##_vtbl_init ((P##IFace)callbacks); \ + callbacks->m_idbg = idbg; \ + callbacks->m_ref = 1; \ + return (P##IFace)callbacks; \ } -static RIODesc *__open(RIO *io, const char *file, int rw, int mode) { - if (!__plugin_open (io, file, 0)) { - return NULL; - } - - if (!iob_select ("pipe")) { - eprintf("Could not initialize the IO backend\n"); - return NULL; - } - - void *io_ctx = iob_open (file + 9); - if (!io_ctx) { - eprintf ("Could not open the pipe\n"); - return NULL; - } - eprintf ("Opened pipe %s with fd %p\n", file + 9, io_ctx); - - WindCtx *ctx = windbg_ctx_new (io_ctx); - if (!ctx) { - eprintf ("Failed to initialize windbg context\n"); - return NULL; - } - return r_io_desc_new (io, &r_io_plugin_windbg, file, rw, mode, ctx); +#define DECLARE_QUERYINTERFACE(IFace, IFaceIID) \ +static STDMETHODIMP IFace##_QueryInterface_impl ( \ + P##IFace This, \ + _In_ REFIID InterfaceId, \ + _Out_ PVOID *Interface) { \ + *Interface = NULL; \ + if (IsEqualIID (InterfaceId, &IID_IUnknown) || \ + IsEqualIID (InterfaceId, &IFaceIID)) { \ + *Interface = This; \ + THISCALL (This, AddRef); \ + return S_OK; \ + } else { \ + return E_NOINTERFACE; \ + } \ } -static int __write(RIO *io, RIODesc *fd, const ut8 *buf, int count) { - if (!fd) { - return -1; - } - if (windbg_get_target (fd->data)) { - return windbg_write_at_uva (fd->data, buf, io->off, count); - } - return windbg_write_at (fd->data, buf, io->off, count); +#define DECLARE_ADDREF(IFace) \ +static ULONG IFace##_AddRef_impl(P##IFace This) { \ + P##IFace##_IMPL impl = (P##IFace##_IMPL)This; \ + return InterlockedIncrement (&impl->m_ref); \ } -static ut64 __lseek(RIO *io, RIODesc *fd, ut64 offset, int whence) { +#define DECLARE_RELEASE(IFace) \ +static ULONG IFace##_Release_impl(P##IFace This) { \ + P##IFace##_IMPL impl = (P##IFace##_IMPL)This; \ + ULONG ret = InterlockedDecrement (&impl->m_ref); \ + if (!ret) { \ + free (This->lpVtbl); \ + free (This); \ + } \ + return ret; \ +} + +DECLARE_CALLBACKS_IMPL (DEBUG_EVENT_CALLBACKS, IDebugEventCallbacksVtbl) +DECLARE_CALLBACKS_IMPL (DEBUG_INPUT_CALLBACKS, IDebugInputCallbacksVtbl) +DECLARE_CALLBACKS_IMPL (DEBUG_OUTPUT_CALLBACKS, IDebugOutputCallbacksVtbl) + +static STDMETHODIMP __interest_mask(PDEBUG_EVENT_CALLBACKS This, PULONG Mask) { + *Mask = DEBUG_EVENT_BREAKPOINT | DEBUG_EVENT_CREATE_PROCESS; + *Mask |= DEBUG_EVENT_EXCEPTION | DEBUG_EVENT_SYSTEM_ERROR; + *Mask |= DEBUG_EVENT_EXIT_PROCESS; + return S_OK; +} + +static STDMETHODIMP __createprocess_cb( + PDEBUG_EVENT_CALLBACKS This, + ULONG64 ImageFileHandle, + ULONG64 Handle, + ULONG64 BaseOffset, + ULONG ModuleSize, + PCSTR ModuleName, + PCSTR ImageName, + ULONG CheckSum, + ULONG TimeDateStamp, + ULONG64 InitialThreadHandle, + ULONG64 ThreadDataOffset, + ULONG64 StartOffset) { + PDEBUG_EVENT_CALLBACKS_IMPL impl = (PDEBUG_EVENT_CALLBACKS_IMPL)This; + impl->m_idbg->processBase = BaseOffset; + return DEBUG_STATUS_BREAK; +} + +static STDMETHODIMP __breakpoint_cb(PDEBUG_EVENT_CALLBACKS This, PDEBUG_BREAKPOINT Bp) { + return DEBUG_STATUS_BREAK; +} + +static STDMETHODIMP __exception_cb(PDEBUG_EVENT_CALLBACKS This, PEXCEPTION_RECORD64 Exception, ULONG FirstChance) { + return DEBUG_STATUS_BREAK; +} + +static STDMETHODIMP __exit_process_cb(PDEBUG_EVENT_CALLBACKS This, ULONG ExitCode) { + return DEBUG_STATUS_BREAK; +} + +static STDMETHODIMP __system_error_cb(PDEBUG_EVENT_CALLBACKS This, ULONG Error, ULONG Level) { + return DEBUG_STATUS_BREAK; +} + +static STDMETHODIMP __input_cb(PDEBUG_INPUT_CALLBACKS This, ULONG BufferSize) { + char prompt[512]; + PDEBUG_INPUT_CALLBACKS_IMPL impl = (PDEBUG_INPUT_CALLBACKS_IMPL)This; + DbgEngContext *idbg = impl->m_idbg; + ITHISCALL (dbgCtrl, GetPromptText, prompt, sizeof (prompt), NULL); + r_line_set_prompt (prompt); + const char *str = r_line_readline (); + char *ret = r_str_ndup (str, R_MIN (strlen (str), BufferSize)); + ITHISCALL (dbgCtrl, ReturnInput, ret); + return S_OK; +} + +static STDMETHODIMP __input_end_cb(PDEBUG_INPUT_CALLBACKS This) { + return S_OK; +} + +static STDMETHODIMP __output_cb(PDEBUG_OUTPUT_CALLBACKS This, ULONG Mask, PCSTR Text) { + eprintf (Text); + return S_OK; +} + +DECLARE_QUERYINTERFACE (DEBUG_EVENT_CALLBACKS, IID_IDebugEventCallbacks) +DECLARE_QUERYINTERFACE (DEBUG_INPUT_CALLBACKS, IID_IDebugInputCallbacks) +DECLARE_QUERYINTERFACE (DEBUG_OUTPUT_CALLBACKS, IID_IDebugOutputCallbacks) + +DECLARE_ADDREF (DEBUG_EVENT_CALLBACKS) +DECLARE_ADDREF (DEBUG_INPUT_CALLBACKS) +DECLARE_ADDREF (DEBUG_OUTPUT_CALLBACKS) + +DECLARE_RELEASE (DEBUG_EVENT_CALLBACKS) +DECLARE_RELEASE (DEBUG_INPUT_CALLBACKS) +DECLARE_RELEASE (DEBUG_OUTPUT_CALLBACKS) + +static void DEBUG_EVENT_CALLBACKS_vtbl_init(PDEBUG_EVENT_CALLBACKS callbacks) { + INIT_IUNKNOWN_CALLBACKS (DEBUG_EVENT_CALLBACKS, callbacks->lpVtbl); + callbacks->lpVtbl->GetInterestMask = __interest_mask; + callbacks->lpVtbl->Breakpoint = __breakpoint_cb; + callbacks->lpVtbl->Exception = __exception_cb; + callbacks->lpVtbl->CreateProcess = __createprocess_cb; + callbacks->lpVtbl->ExitProcess = __exit_process_cb; + callbacks->lpVtbl->SystemError = __system_error_cb; +} + +static void DEBUG_INPUT_CALLBACKS_vtbl_init(PDEBUG_INPUT_CALLBACKS callbacks) { + INIT_IUNKNOWN_CALLBACKS (DEBUG_INPUT_CALLBACKS, callbacks->lpVtbl); + callbacks->lpVtbl->StartInput = __input_cb; + callbacks->lpVtbl->EndInput = __input_end_cb; +} + +static void DEBUG_OUTPUT_CALLBACKS_vtbl_init(PDEBUG_OUTPUT_CALLBACKS callbacks) { + INIT_IUNKNOWN_CALLBACKS (DEBUG_OUTPUT_CALLBACKS, callbacks->lpVtbl); + callbacks->lpVtbl->Output = __output_cb; +} + +DECLARE_NEW (DEBUG_EVENT_CALLBACKS, IDebugEventCallbacksVtbl) +DECLARE_NEW (DEBUG_INPUT_CALLBACKS, IDebugInputCallbacksVtbl) +DECLARE_NEW (DEBUG_OUTPUT_CALLBACKS, IDebugOutputCallbacksVtbl) + +static void __free_context(DbgEngContext *idbg) { +#define RELEASE(I) \ + if (idbg->I) { \ + ITHISCALL (I, Release); \ + idbg->I = NULL; \ + } + RELEASE (dbgAdvanced); + RELEASE (dbgClient); + RELEASE (dbgCtrl); + RELEASE (dbgData); + RELEASE (dbgReg); + RELEASE (dbgSymbols); + RELEASE (dbgSysObj); + free (idbg); +#undef RELEASE +} + +static bool init_callbacks(DbgEngContext *idbg) { +#define RELEASE(I) if (I) THISCALL (I, Release); + if (!idbg->dbgClient) { + return false; + } + + PDEBUG_EVENT_CALLBACKS event_callbacks = DEBUG_EVENT_CALLBACKS_impl_new (idbg); + PDEBUG_INPUT_CALLBACKS input_callbacks = DEBUG_INPUT_CALLBACKS_impl_new (idbg); + PDEBUG_OUTPUT_CALLBACKS output_callbacks = DEBUG_OUTPUT_CALLBACKS_impl_new (idbg); + + if (!event_callbacks || !output_callbacks || !event_callbacks) { + RELEASE (event_callbacks); + RELEASE (input_callbacks); + RELEASE (output_callbacks); + return false; + } + + if (FAILED (ITHISCALL (dbgClient, SetEventCallbacks, event_callbacks)) || + FAILED (ITHISCALL (dbgClient, SetInputCallbacks, input_callbacks)) || + FAILED (ITHISCALL (dbgClient, SetOutputCallbacks, output_callbacks))) { + goto fail; + } + + RELEASE (event_callbacks); + RELEASE (input_callbacks); + RELEASE (output_callbacks); + return true; +fail: + ITHISCALL (dbgClient, SetEventCallbacks, NULL); + ITHISCALL (dbgClient, SetInputCallbacks, NULL); + ITHISCALL (dbgClient, SetOutputCallbacks, NULL); + return false; +#undef RELEASE +} + +static DbgEngContext *create_remote_context(const char *opts) { + DbgEngContext *idbg = R_NEW0 (DbgEngContext); + + if (!idbg) { + return false; + } + + LPWSTR wopts = (LPWSTR)r_utf8_to_utf16 (opts); + + // Initialize interfaces + if (w32_DebugConnectWide (wopts, &IID_IDebugClient5, &idbg->dbgClient) != S_OK) { + goto fail; + } + if (w32_DebugConnectWide (wopts, &IID_IDebugControl4, &idbg->dbgCtrl) != S_OK) { + goto fail; + } + if (w32_DebugConnectWide (wopts, &IID_IDebugDataSpaces4, &idbg->dbgData) != S_OK) { + goto fail; + } + if (w32_DebugConnectWide (wopts, &IID_IDebugRegisters2, &idbg->dbgReg) != S_OK) { + goto fail; + } + if (w32_DebugConnectWide (wopts, &IID_IDebugSystemObjects4, &idbg->dbgSysObj) != S_OK) { + goto fail; + } + if (w32_DebugConnectWide (wopts, &IID_IDebugAdvanced3, &idbg->dbgAdvanced) != S_OK) { + goto fail; + } + if (w32_DebugConnectWide (wopts, &IID_IDebugSymbols3, &idbg->dbgSymbols) != S_OK) { + goto fail; + } + if (!init_callbacks (idbg)) { + goto fail; + } + idbg->initialized = true; + return idbg; +fail: + __free_context (idbg); + return NULL; +} + +static DbgEngContext *create_context(void) { + DbgEngContext *idbg = R_NEW0 (DbgEngContext); + + if (!idbg) { + return false; + } + + // Initialize interfaces + if (w32_DebugCreate (&IID_IDebugClient5, &idbg->dbgClient) != S_OK) { + goto fail; + } + if (w32_DebugCreate (&IID_IDebugControl4, &idbg->dbgCtrl) != S_OK) { + goto fail; + } + if (w32_DebugCreate (&IID_IDebugDataSpaces4, &idbg->dbgData) != S_OK) { + goto fail; + } + if (w32_DebugCreate (&IID_IDebugRegisters2, &idbg->dbgReg) != S_OK) { + goto fail; + } + if (w32_DebugCreate (&IID_IDebugSystemObjects4, &idbg->dbgSysObj) != S_OK) { + goto fail; + } + if (w32_DebugCreate (&IID_IDebugAdvanced3, &idbg->dbgAdvanced) != S_OK) { + goto fail; + } + if (w32_DebugCreate (&IID_IDebugSymbols3, &idbg->dbgSymbols) != S_OK) { + goto fail; + } + if (!init_callbacks (idbg)) { + goto fail; + } + idbg->initialized = true; + return idbg; +fail: + __free_context (idbg); + return NULL; +} + +static int windbg_init(void) { + if (w32_DebugCreate && w32_DebugConnectWide) { + return 1; + } + char *ext_path = r_sys_getenv ("_NT_DEBUGGER_EXTENSION_PATH"); + HANDLE h = NULL; + if (R_STR_ISNOTEMPTY (ext_path)) { + char *s = strtok (ext_path, ";"); + do { + PWCHAR dir = r_utf8_to_utf16 (s); + SetDllDirectoryW (dir); + free (dir); + h = LoadLibrary (TEXT ("dbgeng.dll")); + } while (!h && (s = strtok (NULL, ";"))); + SetDllDirectoryW (NULL); + } + free (ext_path); + if (!h) { + h = LoadLibrary (TEXT ("dbgeng.dll")); + } + if (!h) { + r_sys_perror ("LoadLibrary (\"dbgeng.dll\")"); + return 0; + } + + w32_DebugCreate = (DebugCreate_t)GetProcAddress (h, "DebugCreate"); + if (!w32_DebugCreate) { + r_sys_perror ("GetProcAddress (\"DebugCreate\")"); + return 0; + } + + w32_DebugConnectWide = (DebugConnectWide_t)GetProcAddress (h, "DebugConnectWide"); + if (!w32_DebugConnectWide) { + r_sys_perror ("GetProcAddress (\"DebugConnectWide\")"); + return 0; + } + + return 1; +} + +static bool windbg_check(RIO *io, const char *uri, bool many) { + return !strncmp (uri, WINDBGURI, strlen (WINDBGURI)); +} + +typedef enum { + TARGET_LOCAL_SPAWN, + TARGET_LOCAL_ATTACH, + TARGET_LOCAL_KERNEL, + TARGET_DUMP_FILE, + TARGET_KERNEL, +} DbgEngTarget; + +static RIODesc *windbg_open(RIO *io, const char *uri, int perm, int mode) { + if (!windbg_check (io, uri, 0)) { + return NULL; + } + if (!windbg_init ()) { + return NULL; + } + HRESULT hr = E_FAIL; + RIODesc *fd = NULL; + RCore *core = io->corebind.core; + DbgEngContext *idbg = NULL; + const char *args = uri + strlen (WINDBGURI); + if (r_str_startswith (args, "-remote")) { + args += strlen ("-remote") + 1; + idbg = create_remote_context (args); + if (idbg) { + goto remote_client; + } + } else { + idbg = create_context (); + if (idbg && r_str_startswith (args, "-premote")) { + args += strlen ("-premote") + 1; + if (FAILED (ITHISCALL (dbgClient, ConnectProcessServer, args, &idbg->server))) { + __free_context (idbg); + return NULL; + } + goto remote_client; + } + } + if (!idbg) { + return NULL; + } + ITHISCALL (dbgCtrl, AddEngineOptions, DEBUG_ENGOPT_INITIAL_BREAK); + ITHISCALL (dbgCtrl, AddEngineOptions, DEBUG_ENGOPT_FINAL_BREAK); + ITHISCALL (dbgCtrl, AddEngineOptions, DEBUG_ENGOPT_ALLOW_READ_ONLY_BREAKPOINTS); + ITHISCALL (dbgCtrl, SetCodeLevel, DEBUG_LEVEL_ASSEMBLY); + int argc; + char **argv = r_str_argv (args, &argc); + const size_t argv_sz = sizeof (char *) * ((size_t)argc + 2); + char **tmp = realloc (argv, argv_sz); + if (!tmp) { + __free_context (idbg); + r_str_argv_free (argv); + return NULL; + } + argv = tmp; + memmove (argv + 1, argv, argv_sz - sizeof (char *)); + argv[0] = strdup (WINDBGURI); + argc++; + const char *command = NULL; + bool image_path_set = false, symbol_path_set = false; + DbgEngTarget target = TARGET_LOCAL_SPAWN; + DWORD spawn_options = DEBUG_ONLY_THIS_PROCESS | CREATE_NEW_CONSOLE; + DWORD attach_options = DEBUG_ATTACH_DEFAULT; + DWORD pid = 0; + int c; + RGetopt opt; + r_getopt_init (&opt, argc, argv, "c:dgGh:i:k:op:y:z:"); + while ((c = r_getopt_next (&opt)) != -1) { + switch (c) { + case 'c': + command = opt.arg; + break; + case 'd': + ITHISCALL (dbgCtrl, AddEngineOptions, DEBUG_ENGOPT_INITIAL_MODULE_BREAK); + break; + case 'g': + ITHISCALL (dbgCtrl, RemoveEngineOptions, DEBUG_ENGOPT_INITIAL_BREAK); + break; + case 'G': + ITHISCALL (dbgCtrl, RemoveEngineOptions, DEBUG_ENGOPT_FINAL_BREAK); + break; + case 'h': + if (strcmp (opt.arg, "d")) { + spawn_options |= DEBUG_CREATE_PROCESS_NO_DEBUG_HEAP; + } + break; + case 'i': + ITHISCALL (dbgSymbols, SetImagePath, opt.arg); + image_path_set = true; + break; + case 'k': + if (strcmp (opt.arg, "l")) { + target = TARGET_LOCAL_KERNEL; + } else if (strcmp (opt.arg, "qm")) { + ITHISCALL (dbgCtrl, AddEngineOptions, DEBUG_ENGOPT_KD_QUIET_MODE); + } else { + target = TARGET_KERNEL; + args = opt.arg; + } + break; + case 'o': + spawn_options &= ~DEBUG_ONLY_THIS_PROCESS; + spawn_options |= DEBUG_PROCESS; + break; + case 'p': + if (r_str_isnumber (opt.arg)) { + target = TARGET_LOCAL_ATTACH; + pid = atoi (opt.arg); + } else { + if (strcmp (opt.arg, "b")) { + attach_options |= DEBUG_ATTACH_INVASIVE_NO_INITIAL_BREAK; + } else if (strcmp (opt.arg, "e")) { + attach_options |= DEBUG_ATTACH_EXISTING; + } else if (strcmp (opt.arg, "v")) { + attach_options |= DEBUG_ATTACH_NONINVASIVE; + } + } + break; + case 'y': + symbol_path_set = true; + ITHISCALL (dbgSymbols, SetSymbolPath, opt.arg); + break; + case 'z': + target = TARGET_DUMP_FILE; + args = opt.arg; + break; + default: + break; + } + } + if (!symbol_path_set) { + const char *store = io->corebind.cfgGet (core, "pdb.symstore"); + const char *server = io->corebind.cfgGet (core, "pdb.server"); + char *s = strdup (server); + r_str_replace_ch (s, ';', '*', true); + char *sympath = r_str_newf ("cache*;srv*%s*%s", store, s); + ITHISCALL (dbgSymbols, SetSymbolPath, sympath); + free (s); + free (sympath); + } + if (!image_path_set) { + char *path = r_sys_getenv ("PATH"); + ITHISCALL (dbgSymbols, AppendImagePath, path); + free (path); + } + switch (target) { + case TARGET_LOCAL_SPAWN: + if (argv[opt.ind]) { + char *cmd = r_str_format_msvc_argv ((size_t)opt.argc - opt.ind, argv + opt.ind); + hr = ITHISCALL (dbgClient, CreateProcess, 0ULL, cmd, spawn_options); + free (cmd); + } else { + eprintf ("Missing argument for local spawn\n"); + } + break; + case TARGET_LOCAL_ATTACH: // -p (PID) + hr = ITHISCALL (dbgClient, AttachProcess, 0ULL, pid, attach_options); + break; + case TARGET_LOCAL_KERNEL: // -kl + if (ITHISCALL (dbgClient, IsKernelDebuggerEnabled) == S_FALSE) { + eprintf ("Live Kernel debug not available. Set the /debug boot switch to enable it\n"); + } else { + hr = ITHISCALL (dbgClient, AttachKernel, DEBUG_ATTACH_LOCAL_KERNEL, args); + } + break; + case TARGET_DUMP_FILE: // -z + hr = ITHISCALL (dbgClient, OpenDumpFile, args); + break; + case TARGET_KERNEL: // -k + hr = ITHISCALL (dbgClient, AttachKernel, DEBUG_ATTACH_KERNEL_CONNECTION, args); + break; + } + if (hr != S_OK) { + r_str_argv_free (argv); + __free_context (idbg); + return NULL; + } + ITHISCALL (dbgCtrl, WaitForEvent, DEBUG_WAIT_DEFAULT, INFINITE); + if (command) { + ITHISCALL (dbgCtrl, Execute, DEBUG_OUTCTL_ALL_CLIENTS, command, DEBUG_EXECUTE_DEFAULT); + } + r_str_argv_free (argv); +remote_client: + fd = r_io_desc_new (io, &r_io_plugin_windbg, uri, perm | R_PERM_X, mode, idbg); + fd->name = strdup (args); + core->dbg->user = idbg; + io->corebind.cmd (io->corebind.core, "dL windbg"); + return fd; +} + +static int windbg_close(RIODesc *fd) { + DbgEngContext *idbg = fd->data; + if (idbg->server) { + ITHISCALL (dbgClient, EndSession, DEBUG_END_DISCONNECT); + ITHISCALL (dbgClient, DisconnectProcessServer, idbg->server); + idbg->server = 0ULL; + } else { + ITHISCALL (dbgClient, EndSession, DEBUG_END_PASSIVE); + } + __free_context (idbg); + return 1; +} + +static ut64 windbg_lseek(RIO *io, RIODesc *fd, ut64 offset, int whence) { switch (whence) { case R_IO_SEEK_SET: - return io->off = offset; + io->off = offset; + break; case R_IO_SEEK_CUR: - return io->off + offset; + io->off += (st64)offset; + break; case R_IO_SEEK_END: - return ST64_MAX; - default: - return offset; + io->off = UT64_MAX; + break; } + return io->off; } -static int __read(RIO *io, RIODesc *fd, ut8 *buf, int count) { - if (!fd) { - return -1; +static int windbg_read(RIO *io, RIODesc *fd, ut8 *buf, int count) { + DbgEngContext *idbg = fd->data; + ULONG bytesRead = 0ULL; + if (FAILED (ITHISCALL (dbgData, ReadVirtual, io->off, (PVOID)buf, count, &bytesRead))) { + ULONG64 ValidBase; + ULONG ValidSize; + if (SUCCEEDED (ITHISCALL (dbgData, GetValidRegionVirtual, io->off, count, &ValidBase, &ValidSize))) { + if (ValidSize && ValidBase < io->off + count) { + const ULONG64 skipped = ValidBase - io->off; + const ULONG toRead = count - skipped; + ITHISCALL (dbgData, ReadVirtual, ValidBase, (PVOID)(buf + skipped), toRead, &bytesRead); + bytesRead += skipped; + } + } } - - if (windbg_get_target (fd->data)) { - return windbg_read_at_uva (fd->data, buf, io->off, count); - } - - return windbg_read_at (fd->data, buf, io->off, count); + return bytesRead; } -static int __close(RIODesc *fd) { - windbg_ctx_free ((WindCtx**)&fd->data); +static int windbg_write(RIO *io, RIODesc *fd, const ut8 *buf, int count) { + DbgEngContext *idbg = fd->data; + ULONG bytesWritten = 0ULL; + ITHISCALL (dbgData, WriteVirtual, io->off, (PVOID)buf, count, &bytesWritten); + return bytesWritten; +} + +static int windbg_getpid(RIODesc *fd) { + DbgEngContext *idbg = fd->data; + ULONG Id = 0, Class, Qualifier; + if (SUCCEEDED (ITHISCALL (dbgCtrl, GetDebuggeeType, &Class, &Qualifier))) { + if (Class == DEBUG_CLASS_KERNEL) { + ITHISCALL (dbgSysObj, GetCurrentProcessId, &Id); + } else { + ITHISCALL (dbgSysObj, GetCurrentProcessSystemId, &Id); + } + } + return Id; +} + +static int windbg_gettid(RIODesc *fd) { + DbgEngContext *idbg = fd->data; + ULONG Id = 0, Class, Qualifier; + if (SUCCEEDED (ITHISCALL (dbgCtrl, GetDebuggeeType, &Class, &Qualifier))) { + if (Class == DEBUG_CLASS_KERNEL) { + ITHISCALL (dbgSysObj, GetCurrentThreadId, &Id); + } else { + ITHISCALL (dbgSysObj, GetCurrentThreadSystemId, &Id); + } + } + return Id; +} + +static bool windbg_getbase(RIODesc *fd, ut64 *base) { + DbgEngContext *idbg = fd->data; + *base = idbg->processBase; return true; } +static char *windbg_system(RIO *io, RIODesc *fd, const char *cmd) { + DbgEngContext *idbg = fd->data; + if (R_STR_ISEMPTY (cmd) || !strncmp ("pid", cmd, 3)) { + return NULL; + } + ITHISCALL (dbgCtrl, Execute, DEBUG_OUTCTL_ALL_CLIENTS, cmd, DEBUG_EXECUTE_DEFAULT); + return NULL; +} + RIOPlugin r_io_plugin_windbg = { .name = "windbg", - .desc = "Attach to a KD debugger", - .uris = "windbg://", + .desc = "WinDBG (DbgEng.dll) based io plugin for Windows", .license = "LGPL3", - .open = __open, - .close = __close, - .read = __read, - .check = __plugin_open, - .lseek = __lseek, - .write = __write, - .isdbg = true + .uris = WINDBGURI, + .isdbg = true, + .init = windbg_init, + .open = windbg_open, + .lseek = windbg_lseek, + .read = windbg_read, + .write = windbg_write, + .system = windbg_system, + .close = windbg_close, + .getpid = windbg_getpid, + .gettid = windbg_gettid, + .getbase = windbg_getbase, + .check = windbg_check, }; #ifndef R2_PLUGIN_INCORE diff --git a/libr/io/p/io_winkd.c b/libr/io/p/io_winkd.c new file mode 100644 index 0000000000..ea781e3603 --- /dev/null +++ b/libr/io/p/io_winkd.c @@ -0,0 +1,112 @@ +// Copyright (c) 2014-2017, The Lemon Man, All rights reserved. LGPLv3 + +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public +// License along with this library. + +#include +#include +#include +#include +#include +#include + +static bool __plugin_open(RIO *io, const char *file, bool many) { + return (!strncmp (file, "winkd://", 8)); +} + +static RIODesc *__open(RIO *io, const char *file, int rw, int mode) { + if (!__plugin_open (io, file, 0)) { + return NULL; + } + + if (!iob_select ("pipe")) { + eprintf("Could not initialize the IO backend\n"); + return NULL; + } + + void *io_ctx = iob_open (file + 9); + if (!io_ctx) { + eprintf ("Could not open the pipe\n"); + return NULL; + } + eprintf ("Opened pipe %s with fd %p\n", file + 9, io_ctx); + + WindCtx *ctx = winkd_ctx_new (io_ctx); + if (!ctx) { + eprintf ("Failed to initialize winkd context\n"); + return NULL; + } + return r_io_desc_new (io, &r_io_plugin_winkd, file, rw, mode, ctx); +} + +static int __write(RIO *io, RIODesc *fd, const ut8 *buf, int count) { + if (!fd) { + return -1; + } + if (winkd_get_target (fd->data)) { + return winkd_write_at_uva (fd->data, buf, io->off, count); + } + return winkd_write_at (fd->data, buf, io->off, count); +} + +static ut64 __lseek(RIO *io, RIODesc *fd, ut64 offset, int whence) { + switch (whence) { + case R_IO_SEEK_SET: + return io->off = offset; + case R_IO_SEEK_CUR: + return io->off + offset; + case R_IO_SEEK_END: + return ST64_MAX; + default: + return offset; + } +} + +static int __read(RIO *io, RIODesc *fd, ut8 *buf, int count) { + if (!fd) { + return -1; + } + + if (winkd_get_target (fd->data)) { + return winkd_read_at_uva (fd->data, buf, io->off, count); + } + + return winkd_read_at (fd->data, buf, io->off, count); +} + +static int __close(RIODesc *fd) { + winkd_ctx_free ((WindCtx**)&fd->data); + return true; +} + +RIOPlugin r_io_plugin_winkd = { + .name = "winkd", + .desc = "Attach to a KD debugger", + .uris = "winkd://", + .license = "LGPL3", + .open = __open, + .close = __close, + .read = __read, + .check = __plugin_open, + .lseek = __lseek, + .write = __write, + .isdbg = true +}; + +#ifndef R2_PLUGIN_INCORE +R_API RLibStruct radare_plugin = { + .type = R_LIB_TYPE_IO, + .data = &r_io_plugin_winkd, + .version = R2_VERSION +}; +#endif diff --git a/libr/io/p/windbg.mk b/libr/io/p/windbg.mk deleted file mode 100644 index e8cc11cc9c..0000000000 --- a/libr/io/p/windbg.mk +++ /dev/null @@ -1,21 +0,0 @@ -OBJ_WINDBG=io_windbg.o - -STATIC_OBJ+=${OBJ_WINDBG} -TARGET_WINDBG=io_windbg.${EXT_SO} -ALL_TARGETS+=${TARGET_WINDBG} - -LIB_PATH=$(SHLR)/windbg -CFLAGS+=-I$(SHLR)/windbg -LDFLAGS+=$(SHLR)/windbg/libr_windbg.$(EXT_AR) - -ifeq (${WITHPIC},0) -LINKFLAGS+=../../util/libr_util.a -LINKFLAGS+=../../io/libr_io.a -else -LINKFLAGS+=-L../../util -lr_util -LINKFLAGS+=-L.. -lr_io -endif - -${TARGET_WINDBG}: ${OBJ_WINDBG} - ${CC} $(call libname,io_windbg) ${OBJ_WINDBG} ${CFLAGS} \ - ${LINKFLAGS} ${LDFLAGS_LIB} $(LDFLAGS) diff --git a/libr/io/p/winkd.mk b/libr/io/p/winkd.mk new file mode 100644 index 0000000000..116c260701 --- /dev/null +++ b/libr/io/p/winkd.mk @@ -0,0 +1,21 @@ +OBJ_WINKD=io_winkd.o + +STATIC_OBJ+=${OBJ_WINKD} +TARGET_WINKD=io_winkd.${EXT_SO} +ALL_TARGETS+=${TARGET_WINKD} + +LIB_PATH=$(SHLR)/winkd +CFLAGS+=-I$(SHLR)/winkd +LDFLAGS+=$(SHLR)/winkd/libr_winkd.$(EXT_AR) + +ifeq (${WITHPIC},0) +LINKFLAGS+=../../util/libr_util.a +LINKFLAGS+=../../io/libr_io.a +else +LINKFLAGS+=-L../../util -lr_util +LINKFLAGS+=-L.. -lr_io +endif + +${TARGET_WINKD}: ${OBJ_WINKD} + ${CC} $(call libname,io_winkd) ${OBJ_WINKD} ${CFLAGS} \ + ${LINKFLAGS} ${LDFLAGS_LIB} $(LDFLAGS) diff --git a/libr/meson.build b/libr/meson.build index fcb0c759c8..bd675cebda 100644 --- a/libr/meson.build +++ b/libr/meson.build @@ -230,7 +230,7 @@ debug_plugins = [ 'null', 'qnx', 'rap', - 'windbg' + 'winkd' ] egg_plugins = [ @@ -290,16 +290,18 @@ io_plugins = [ 'shm', 'sparse', 'tcp', - 'windbg', + 'winkd', 'winedbg', 'zip' ] if host_machine.system() == 'windows' io_plugins += [ + 'windbg', 'w32dbg', 'w32', ] + debug_plugins += 'windbg' endif lang_plugins = [ diff --git a/plugins.def.cfg b/plugins.def.cfg index e7f952012e..d79009e420 100644 --- a/plugins.def.cfg +++ b/plugins.def.cfg @@ -207,7 +207,7 @@ debug.gdb debug.qnx debug.native debug.rap -debug.windbg +debug.winkd debug.bochs debug.null egg.exec @@ -255,7 +255,7 @@ io.self io.shm io.w32 io.w32dbg -io.windbg +io.winkd io.winedbg io.zip io.r2k diff --git a/plugins.nogpl.cfg b/plugins.nogpl.cfg index 025e6d6cd3..36011b21a5 100644 --- a/plugins.nogpl.cfg +++ b/plugins.nogpl.cfg @@ -96,7 +96,7 @@ debug.esil debug.gdb debug.native debug.rap -debug.windbg +debug.winkd egg.exec egg.xor fs.posix @@ -119,7 +119,7 @@ io.self io.shm io.w32 io.w32dbg -io.windbg +io.winkd io.zip lang.vala parse.6502_pseudo diff --git a/plugins.static.cfg b/plugins.static.cfg index 02e0fa19c4..573e0ec07b 100644 --- a/plugins.static.cfg +++ b/plugins.static.cfg @@ -160,7 +160,7 @@ debug.gdb debug.qnx debug.native debug.rap -debug.windbg +debug.winkd debug.bochs debug.null egg.exec @@ -207,7 +207,7 @@ io.self io.shm io.w32 io.w32dbg -io.windbg +io.winkd io.zip io.r2k io.ar diff --git a/plugins.static.nogpl.cfg b/plugins.static.nogpl.cfg index 6f5a4b5bb1..b3244fb52b 100644 --- a/plugins.static.nogpl.cfg +++ b/plugins.static.nogpl.cfg @@ -157,7 +157,7 @@ debug.gdb debug.qnx debug.native debug.rap -debug.windbg +debug.winkd debug.bochs debug.null egg.exec @@ -189,7 +189,7 @@ io.self io.shm io.w32 io.w32dbg -io.windbg +io.winkd io.zip io.r2k io.ar diff --git a/shlr/Makefile b/shlr/Makefile index aa00025d91..c267762b55 100644 --- a/shlr/Makefile +++ b/shlr/Makefile @@ -60,7 +60,7 @@ CS_REV= CS_PATCHES=1 endif -.PHONY: capstone-sync capstone-build all clean mrproper libgdbr libwindbg bochs tree-sitter-sync sdbs +.PHONY: capstone-sync capstone-build all clean mrproper libgdbr libwinkd bochs tree-sitter-sync sdbs ifeq ($(shell gcc -v > /dev/null 2>&1 && echo works),works) HOST_CC?=gcc @@ -94,14 +94,14 @@ all: exit 1 endif -preall: libwindbg capstone-build tree-sitter-build radare2-shell-parser-build bochs +preall: libwinkd capstone-build tree-sitter-build radare2-shell-parser-build bochs @for MOD in ${MODS} ; do \ echo $(MAKE) -C $$MOD ; \ $(MAKE) -C $$MOD HAVE_VALA= ROOT="${PWD}/../" CC="${CC}" ; \ done SDBFILES=sdb/src/.sdb${EXT_EXE} sdb/sdb${EXT_EXE} sdb/src/.sdb sdb/sdb -PREMODS=capstone gdb windbg sdb bochs ar +PREMODS=capstone gdb winkd sdb bochs ar clean mrproper: rm -f ${SDBFILES} @@ -154,8 +154,8 @@ I=../libr/include libgdbr: $(MAKE) -C gdb all -libwindbg: - $(MAKE) -C windbg all +libwinkd: + $(MAKE) -C winkd all bochs: $(MAKE) -C bochs all @@ -375,7 +375,7 @@ SHLRS+=java/libr_java.a SHLRS+=lz4/liblz4.a SHLRS+=qnx/lib/libqnxr.a SHLRS+=yxml/libyxml.a -SHLRS+=windbg/libr_windbg.a +SHLRS+=winkd/libr_winkd.a SHLRS+=zip/librz.a libr_shlr.${EXT_AR}: diff --git a/shlr/meson.build b/shlr/meson.build index e1c765b8b7..05e7888732 100644 --- a/shlr/meson.build +++ b/shlr/meson.build @@ -527,25 +527,25 @@ grub_dep = declare_dependency( ) -# handle windbg dependency -windbg_files = [ - 'windbg/iob_pipe.c', - 'windbg/kd.c', - 'windbg/transport.c', - 'windbg/windbg.c', +# handle winkd dependency +winkd_files = [ + 'winkd/iob_pipe.c', + 'winkd/kd.c', + 'winkd/transport.c', + 'winkd/winkd.c', ] -windbg_inc = [platform_inc, include_directories('windbg')] +winkd_inc = [platform_inc, include_directories('winkd')] -libr2windbg = static_library('r2windbg', windbg_files, +libr2winkd = static_library('r2winkd', winkd_files, dependencies: [r_util_dep], - include_directories: windbg_inc, + include_directories: winkd_inc, implicit_include_directories: false ) -windbg_dep = declare_dependency( - link_with: libr2windbg, - include_directories: windbg_inc +winkd_dep = declare_dependency( + link_with: libr2winkd, + include_directories: winkd_inc ) diff --git a/shlr/windbg/deps.mk b/shlr/windbg/deps.mk deleted file mode 100644 index dde19c9073..0000000000 --- a/shlr/windbg/deps.mk +++ /dev/null @@ -1 +0,0 @@ -LINK+=$(STOP)/windbg/libr_windbg.${EXT_AR} diff --git a/shlr/windbg/windbg.h b/shlr/windbg/windbg.h deleted file mode 100644 index 418169d039..0000000000 --- a/shlr/windbg/windbg.h +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) 2014, The Lemon Man, All rights reserved. - -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. - -// You should have received a copy of the GNU Lesser General Public -// License along with this library. - -#ifndef _windbg_H_ -#define _windbg_H_ - -#include -#include "kd.h" - -typedef struct _WindCtx WindCtx; - -typedef struct WindProc { - ut64 eprocess; - ut32 uniqueid; - ut64 vadroot; - ut64 dir_base_table; - ut64 peb; - char name[17]; -} WindProc; - -typedef struct WindThread { - ut32 uniqueid; - bool runnable; - char status; - ut64 ethread; - ut64 entrypoint; -} WindThread; - -typedef struct WindModule { - char *name; - ut64 addr; - ut64 size; -} WindModule; - -enum { - K_PaeEnabled = 0x036, - K_PsActiveProcessHead = 0x050, - K_CmNtCSDVersion = 0x268, -}; - -enum { - E_ActiveProcessLinks, // EPROCESS - E_UniqueProcessId, // EPROCESS - E_Peb, // EPROCESS - E_ImageFileName, // EPROCESS - E_VadRoot, // EPROCESS - E_ThreadListHead, // EPROCESS - P_DirectoryTableBase, // PCB - P_ImageBaseAddress, // PEB - P_ProcessParameters, // PEB - R_ImagePathName, // RTL_USER_PROCESS_PARAMETERS - ET_Tcb, // ETHREAD - ET_ThreadListEntry, // ETHREAD - ET_Win32StartAddress, // ETHREAD - ET_Cid, // ETHREAD - C_UniqueThread, // CLIENT_ID - O_Max, -}; - -typedef struct { - int build; - int sp; - int bits; - int flags; - int f[O_Max]; -} Profile; - -// grep -e "^windbg_" shlr/wind/wind.c | sed -e 's/ {$/;/' -e 's/^/int /' -int windbg_get_bits(WindCtx *ctx); -ut64 windbg_get_target_base(WindCtx *ctx); -ut32 windbg_get_target(WindCtx *ctx); -bool windbg_set_target(WindCtx *ctx, ut32 pid); -RList *windbg_list_process(WindCtx *ctx); -RList *windbg_list_threads(WindCtx *ctx); -RList *windbg_list_modules(WindCtx *ctx); -int windbg_get_cpus(WindCtx *ctx); -bool windbg_set_cpu(WindCtx *ctx, int cpu); -int windbg_get_cpu(WindCtx *ctx); -WindCtx * windbg_ctx_new(void *io_ptr); -void windbg_ctx_free(WindCtx **ctx); -int windbg_wait_packet(WindCtx *ctx, const ut32 type, kd_packet_t **p); -int windbg_sync(WindCtx *ctx); -bool windbg_read_ver(WindCtx *ctx); -int windbg_continue(WindCtx *ctx); -bool windbg_write_reg(WindCtx *ctx, const uint8_t *buf, int size); -int windbg_read_reg(WindCtx *ctx, uint8_t *buf, int size); -int windbg_query_mem(WindCtx *ctx, const ut64 addr, int *address_space, int *flags); -int windbg_bkpt(WindCtx *ctx, const ut64 addr, const int set, const int hw, int *handle); -int windbg_read_at(WindCtx *ctx, uint8_t *buf, const ut64 offset, const int count); -int windbg_read_at_uva(WindCtx *ctx, uint8_t *buf, ut64 offset, int count); -int windbg_read_at_phys(WindCtx *ctx, uint8_t *buf, const ut64 offset, const int count); -int windbg_write_at(WindCtx *ctx, const uint8_t *buf, const ut64 offset, const int count); -int windbg_write_at_uva(WindCtx *ctx, const uint8_t *buf, ut64 offset, int count); -int windbg_write_at_phys(WindCtx *ctx, const uint8_t *buf, const ut64 offset, const int count); -bool windbg_va_to_pa(WindCtx *ctx, ut64 va, ut64 *pa); -void windbg_break(void *ctx); -int windbg_break_read(WindCtx *ctx); -bool windbg_lock_enter(WindCtx *ctx); -bool windbg_lock_leave(WindCtx *ctx); -bool windbg_lock_tryenter(WindCtx *ctx); -#endif diff --git a/shlr/windbg/Makefile b/shlr/winkd/Makefile similarity index 85% rename from shlr/windbg/Makefile rename to shlr/winkd/Makefile index 9220e82b7e..5d9c5d5f91 100644 --- a/shlr/windbg/Makefile +++ b/shlr/winkd/Makefile @@ -6,13 +6,13 @@ include ../../mk/${COMPILER}.mk CFLAGS+=${PIC_CFLAGS} CFLAGS+=-I../../libr/include -LIBAR=libr_windbg.${EXT_AR} +LIBAR=libr_winkd.${EXT_AR} LDFLAGS+=-L../../libr/util LIBS=-lr_util include ../../shlr/sdb.mk -OFILES=transport.o kd.o windbg.o iob_pipe.o +OFILES=transport.o kd.o winkd.o iob_pipe.o all: ${LIBAR} diff --git a/shlr/winkd/deps.mk b/shlr/winkd/deps.mk new file mode 100644 index 0000000000..d87bd67e73 --- /dev/null +++ b/shlr/winkd/deps.mk @@ -0,0 +1 @@ +LINK+=$(STOP)/winkd/libr_winkd.${EXT_AR} diff --git a/shlr/windbg/iob_pipe.c b/shlr/winkd/iob_pipe.c similarity index 100% rename from shlr/windbg/iob_pipe.c rename to shlr/winkd/iob_pipe.c diff --git a/shlr/windbg/kd.c b/shlr/winkd/kd.c similarity index 100% rename from shlr/windbg/kd.c rename to shlr/winkd/kd.c diff --git a/shlr/windbg/kd.h b/shlr/winkd/kd.h similarity index 100% rename from shlr/windbg/kd.h rename to shlr/winkd/kd.h diff --git a/shlr/windbg/profiles.h b/shlr/winkd/profiles.h similarity index 100% rename from shlr/windbg/profiles.h rename to shlr/winkd/profiles.h diff --git a/shlr/windbg/transport.c b/shlr/winkd/transport.c similarity index 100% rename from shlr/windbg/transport.c rename to shlr/winkd/transport.c diff --git a/shlr/windbg/transport.h b/shlr/winkd/transport.h similarity index 100% rename from shlr/windbg/transport.h rename to shlr/winkd/transport.h diff --git a/shlr/windbg/windbg.c b/shlr/winkd/winkd.c similarity index 75% rename from shlr/windbg/windbg.c rename to shlr/winkd/winkd.c index 6f9e8c7223..bb3c7b7193 100644 --- a/shlr/windbg/windbg.c +++ b/shlr/winkd/winkd.c @@ -8,7 +8,7 @@ #include #include #include "transport.h" -#include "windbg.h" +#include "winkd.h" #include "kd.h" #define O_FLAG_XPVAD 1 @@ -43,7 +43,7 @@ Profile *p_table[] = { NULL, }; -Profile *windbg_get_profile(int bits, int build, int sp) { +Profile *winkd_get_profile(int bits, int build, int sp) { int i; for (i = 0; p_table[i]; i++) { if (p_table[i]->build != build) { @@ -84,38 +84,38 @@ struct _WindCtx { RThreadLock *dontmix; }; -bool windbg_lock_enter(WindCtx *ctx) { - r_cons_break_push (windbg_break, ctx); +bool winkd_lock_enter(WindCtx *ctx) { + r_cons_break_push (winkd_break, ctx); r_th_lock_enter (ctx->dontmix); return true; } -bool windbg_lock_tryenter(WindCtx *ctx) { +bool winkd_lock_tryenter(WindCtx *ctx) { if (!r_th_lock_tryenter (ctx->dontmix)) { return false; } - r_cons_break_push (windbg_break, ctx); + r_cons_break_push (winkd_break, ctx); return true; } -bool windbg_lock_leave(WindCtx *ctx) { +bool winkd_lock_leave(WindCtx *ctx) { r_cons_break_pop (); r_th_lock_leave (ctx->dontmix); return true; } -int windbg_get_bits(WindCtx *ctx) { +int winkd_get_bits(WindCtx *ctx) { return ctx->is_x64 ? R_SYS_BITS_64 : R_SYS_BITS_32; } -int windbg_get_cpus(WindCtx *ctx) { +int winkd_get_cpus(WindCtx *ctx) { if (!ctx) { return -1; } return ctx->cpu_count; } -bool windbg_set_cpu(WindCtx *ctx, int cpu) { +bool winkd_set_cpu(WindCtx *ctx, int cpu) { if (!ctx || cpu > ctx->cpu_count) { return false; } @@ -123,18 +123,18 @@ bool windbg_set_cpu(WindCtx *ctx, int cpu) { return true; } -int windbg_get_cpu(WindCtx *ctx) { +int winkd_get_cpu(WindCtx *ctx) { if (!ctx) { return -1; } return ctx->cpu; } -bool windbg_set_target(WindCtx *ctx, uint32_t pid) { +bool winkd_set_target(WindCtx *ctx, uint32_t pid) { WindProc *p; RListIter *it; if (pid) { - RList *l = windbg_list_process (ctx); + RList *l = winkd_list_process (ctx); r_list_foreach (l, it, p) { if (p->uniqueid == pid) { ctx->target = p; @@ -147,21 +147,21 @@ bool windbg_set_target(WindCtx *ctx, uint32_t pid) { return true; } -uint32_t windbg_get_target(WindCtx *ctx) { +uint32_t winkd_get_target(WindCtx *ctx) { if (!ctx || !ctx->io_ptr || !ctx->syncd) { return 0; } return ctx->target? ctx->target->uniqueid: 0; } -ut64 windbg_get_target_base(WindCtx *ctx) { +ut64 winkd_get_target_base(WindCtx *ctx) { ut64 base = 0; if (!ctx || !ctx->io_ptr || !ctx->syncd || !ctx->target) { return 0; } - if (!windbg_read_at_uva (ctx, (uint8_t *) &base, + if (!winkd_read_at_uva (ctx, (uint8_t *) &base, ctx->target->peb + O_(P_ImageBaseAddress), 4 << ctx->is_x64)) { return 0; } @@ -169,7 +169,7 @@ ut64 windbg_get_target_base(WindCtx *ctx) { return base; } -WindCtx *windbg_ctx_new(void *io_ptr) { +WindCtx *winkd_ctx_new(void *io_ptr) { WindCtx *ctx = calloc (1, sizeof(WindCtx)); if (!ctx) { return NULL; @@ -179,7 +179,7 @@ WindCtx *windbg_ctx_new(void *io_ptr) { return ctx; } -void windbg_ctx_free(WindCtx **ctx) { +void winkd_ctx_free(WindCtx **ctx) { if (!ctx || !*ctx) { return; } @@ -224,7 +224,7 @@ static int do_io_reply(WindCtx *ctx, kd_packet_t *pkt) { int ret; ioc.req = 0x3430; ioc.ret = KD_RET_ENOENT; - windbg_lock_enter (ctx); + winkd_lock_enter (ctx); id = pkt->id; ret = kd_send_data_packet (ctx->io_ptr, KD_PACKET_TYPE_FILE_IO, (ctx->seq_id ^= 1), (uint8_t *) &ioc, sizeof (kd_ioc_t), NULL, 0); @@ -232,21 +232,21 @@ static int do_io_reply(WindCtx *ctx, kd_packet_t *pkt) { goto error; } WIND_DBG eprintf("Waiting for io_reply ack...\n"); - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); if (ret != KD_E_OK) { goto error; } id = 0; - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); WIND_DBG eprintf("Ack received, restore flow\n"); return true; error: id = 0; - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); return 0; } -int windbg_wait_packet(WindCtx *ctx, const uint32_t type, kd_packet_t **p) { +int winkd_wait_packet(WindCtx *ctx, const uint32_t type, kd_packet_t **p) { kd_packet_t *pkt = NULL; int ret; int retries = 10; @@ -310,12 +310,12 @@ R_PACKED ( uint32_t flags; }) mmvad_short; -int windbg_walk_vadtree(WindCtx *ctx, ut64 address, ut64 parent) { +int winkd_walk_vadtree(WindCtx *ctx, ut64 address, ut64 parent) { mmvad_short entry = { { 0 } }; ut64 start, end; int prot; - if (windbg_read_at (ctx, (uint8_t *) &entry, address - 0x4, sizeof(mmvad_short)) != sizeof (mmvad_short)) { + if (winkd_read_at (ctx, (uint8_t *) &entry, address - 0x4, sizeof(mmvad_short)) != sizeof (mmvad_short)) { eprintf ("0x%"PFMT64x " Could not read the node!\n", (ut64) address); return 0; } @@ -333,16 +333,16 @@ int windbg_walk_vadtree(WindCtx *ctx, ut64 address, ut64 parent) { (ut64) start, (ut64) end, (ut64) prot); if (entry.left) { - windbg_walk_vadtree (ctx, entry.left, address); + winkd_walk_vadtree (ctx, entry.left, address); } if (entry.right) { - windbg_walk_vadtree (ctx, entry.right, address); + winkd_walk_vadtree (ctx, entry.right, address); } return 1; } -RList *windbg_list_process(WindCtx *ctx) { +RList *winkd_list_process(WindCtx *ctx) { RList *ret; ut64 ptr, base; @@ -356,14 +356,14 @@ RList *windbg_list_process(WindCtx *ctx) { ptr = 0; // Grab the PsActiveProcessHead from _KDDEBUGGER_DATA64 - windbg_read_at (ctx, (uint8_t *) &ptr, ctx->dbg_addr + K_PsActiveProcessHead, + winkd_read_at (ctx, (uint8_t *) &ptr, ctx->dbg_addr + K_PsActiveProcessHead, 4 << ctx->is_x64); base = ptr; WIND_DBG eprintf("Process list head : 0x%016"PFMT64x "\n", ptr); // Walk the LIST_ENTRY - windbg_read_at (ctx, (uint8_t *) &ptr, ptr, 4 << ctx->is_x64); + winkd_read_at (ctx, (uint8_t *) &ptr, ptr, 4 << ctx->is_x64); ret = r_list_newf (free); @@ -373,14 +373,14 @@ RList *windbg_list_process(WindCtx *ctx) { next = 0; // Read the ActiveProcessLinks entry - windbg_read_at (ctx, (uint8_t *) &next, ptr, 4 << ctx->is_x64); + winkd_read_at (ctx, (uint8_t *) &next, ptr, 4 << ctx->is_x64); // This points to the 'ActiveProcessLinks' list, adjust the ptr so that it point to the // EPROCESS base ptr -= O_(E_ActiveProcessLinks); // Read the short name - windbg_read_at (ctx, (uint8_t *) &buf, ptr + O_(E_ImageFileName), 16); + winkd_read_at (ctx, (uint8_t *) &buf, ptr + O_(E_ImageFileName), 16); buf[16] = '\0'; ut64 vadroot = 0; @@ -388,10 +388,10 @@ RList *windbg_list_process(WindCtx *ctx) { ut64 peb = 0; ut64 dir_base_table = 0; - windbg_read_at (ctx, (uint8_t *) &vadroot, ptr + O_(E_VadRoot), 4 << ctx->is_x64); - windbg_read_at (ctx, (uint8_t *) &uniqueid, ptr + O_(E_UniqueProcessId), 4 << ctx->is_x64); - windbg_read_at (ctx, (uint8_t *) &peb, ptr + O_(E_Peb), 4 << ctx->is_x64); - windbg_read_at (ctx, (uint8_t *) &dir_base_table, ptr + O_(P_DirectoryTableBase), 4 << ctx->is_x64); + winkd_read_at (ctx, (uint8_t *) &vadroot, ptr + O_(E_VadRoot), 4 << ctx->is_x64); + winkd_read_at (ctx, (uint8_t *) &uniqueid, ptr + O_(E_UniqueProcessId), 4 << ctx->is_x64); + winkd_read_at (ctx, (uint8_t *) &peb, ptr + O_(E_Peb), 4 << ctx->is_x64); + winkd_read_at (ctx, (uint8_t *) &dir_base_table, ptr + O_(P_DirectoryTableBase), 4 << ctx->is_x64); WindProc *proc = calloc (1, sizeof(WindProc)); @@ -404,7 +404,7 @@ RList *windbg_list_process(WindCtx *ctx) { r_list_append (ret, proc); - // windbg_walk_vadtree(ctx, vadroot, -1); + // winkd_walk_vadtree(ctx, vadroot, -1); ptr = next; } while (ptr != base); @@ -413,15 +413,15 @@ RList *windbg_list_process(WindCtx *ctx) { return ret; } -int windbg_write_at_uva(WindCtx *ctx, const uint8_t *buf, ut64 offset, int count) { +int winkd_write_at_uva(WindCtx *ctx, const uint8_t *buf, ut64 offset, int count) { ut64 pa; ut32 totwritten = 0; while (totwritten < count) { - if (!windbg_va_to_pa (ctx, offset, &pa)) { + if (!winkd_va_to_pa (ctx, offset, &pa)) { return 0; } ut32 restOfPage = 0x1000 - (offset & 0xfff); - int written = windbg_write_at_phys (ctx, buf + totwritten, pa, R_MIN (count - totwritten, restOfPage)); + int written = winkd_write_at_phys (ctx, buf + totwritten, pa, R_MIN (count - totwritten, restOfPage)); if (!written) { break; } @@ -431,15 +431,15 @@ int windbg_write_at_uva(WindCtx *ctx, const uint8_t *buf, ut64 offset, int count return totwritten; } -int windbg_read_at_uva(WindCtx *ctx, uint8_t *buf, ut64 offset, int count) { +int winkd_read_at_uva(WindCtx *ctx, uint8_t *buf, ut64 offset, int count) { ut64 pa; ut32 totread = 0; while (totread < count) { - if (!windbg_va_to_pa (ctx, offset, &pa)) { + if (!winkd_va_to_pa (ctx, offset, &pa)) { return 0; } ut32 restOfPage = 0x1000 - (offset & 0xfff); - int read = windbg_read_at_phys (ctx, buf + totread, pa, R_MIN (count - totread, restOfPage)); + int read = winkd_read_at_phys (ctx, buf + totread, pa, R_MIN (count - totread, restOfPage)); if (!read) { break; } @@ -449,7 +449,7 @@ int windbg_read_at_uva(WindCtx *ctx, uint8_t *buf, ut64 offset, int count) { return totread; } -RList *windbg_list_modules(WindCtx *ctx) { +RList *winkd_list_modules(WindCtx *ctx) { RList *ret; ut64 ptr, base; @@ -471,7 +471,7 @@ RList *windbg_list_modules(WindCtx *ctx) { ut64 ldroff = ctx->is_x64 ? 0x18 : 0xC; // Grab the _PEB_LDR_DATA from PEB - windbg_read_at_uva (ctx, (uint8_t *) &ptr, ctx->target->peb + ldroff, 4 << ctx->is_x64); + winkd_read_at_uva (ctx, (uint8_t *) &ptr, ctx->target->peb + ldroff, 4 << ctx->is_x64); WIND_DBG eprintf("_PEB_LDR_DATA : 0x%016"PFMT64x "\n", ptr); @@ -480,7 +480,7 @@ RList *windbg_list_modules(WindCtx *ctx) { base = ptr + mlistoff; - windbg_read_at_uva (ctx, (uint8_t *) &ptr, base, 4 << ctx->is_x64); + winkd_read_at_uva (ctx, (uint8_t *) &ptr, base, 4 << ctx->is_x64); WIND_DBG eprintf ("InMemoryOrderModuleList : 0x%016"PFMT64x "\n", ptr); @@ -493,7 +493,7 @@ RList *windbg_list_modules(WindCtx *ctx) { do { ut64 next = 0; - windbg_read_at_uva (ctx, (uint8_t *) &next, ptr, 4 << ctx->is_x64); + winkd_read_at_uva (ctx, (uint8_t *) &next, ptr, 4 << ctx->is_x64); WIND_DBG eprintf ("_LDR_DATA_TABLE_ENTRY : 0x%016"PFMT64x "\n", next); if (!next) { @@ -507,21 +507,21 @@ RList *windbg_list_modules(WindCtx *ctx) { if (!mod) { break; } - windbg_read_at_uva (ctx, (uint8_t *) &mod->addr, ptr + baseoff, 4 << ctx->is_x64); - windbg_read_at_uva (ctx, (uint8_t *) &mod->size, ptr + sizeoff, 4 << ctx->is_x64); + winkd_read_at_uva (ctx, (uint8_t *) &mod->addr, ptr + baseoff, 4 << ctx->is_x64); + winkd_read_at_uva (ctx, (uint8_t *) &mod->size, ptr + sizeoff, 4 << ctx->is_x64); ut16 length; - windbg_read_at_uva (ctx, (uint8_t *) &length, ptr + nameoff, sizeof (ut16)); + winkd_read_at_uva (ctx, (uint8_t *) &length, ptr + nameoff, sizeof (ut16)); ut64 bufferaddr = 0; - windbg_read_at_uva (ctx, (uint8_t *) &bufferaddr, ptr + nameoff + sizeof (ut32), 4 << ctx->is_x64); + winkd_read_at_uva (ctx, (uint8_t *) &bufferaddr, ptr + nameoff + sizeof (ut32), 4 << ctx->is_x64); wchar_t *unname = calloc ((ut64)length + 2, 1); if (!unname) { break; } - windbg_read_at_uva (ctx, (uint8_t *)unname, bufferaddr, length); + winkd_read_at_uva (ctx, (uint8_t *)unname, bufferaddr, length); mod->name = calloc ((ut64)length + 1, 1); if (!mod->name) { @@ -538,7 +538,7 @@ RList *windbg_list_modules(WindCtx *ctx) { return ret; } -RList *windbg_list_threads(WindCtx *ctx) { +RList *winkd_list_threads(WindCtx *ctx) { RList *ret; ut64 ptr, base; @@ -562,7 +562,7 @@ RList *windbg_list_threads(WindCtx *ctx) { } // Grab the ThreadListHead from _EPROCESS - windbg_read_at (ctx, (uint8_t *) &ptr, ptr + O_(E_ThreadListHead), 4 << ctx->is_x64); + winkd_read_at (ctx, (uint8_t *) &ptr, ptr + O_(E_ThreadListHead), 4 << ctx->is_x64); if (!ptr) { return NULL; } @@ -574,7 +574,7 @@ RList *windbg_list_threads(WindCtx *ctx) { do { ut64 next = 0; - windbg_read_at (ctx, (uint8_t *) &next, ptr, 4 << ctx->is_x64); + winkd_read_at (ctx, (uint8_t *) &next, ptr, 4 << ctx->is_x64); if (!next) { eprintf ("Corrupted ThreadListEntry found at: 0x%"PFMT64x"\n", ptr); break; @@ -584,10 +584,10 @@ RList *windbg_list_threads(WindCtx *ctx) { ptr -= O_(ET_ThreadListEntry); ut64 entrypoint = 0; - windbg_read_at (ctx, (uint8_t *) &entrypoint, ptr + O_(ET_Win32StartAddress), 4 << ctx->is_x64); + winkd_read_at (ctx, (uint8_t *) &entrypoint, ptr + O_(ET_Win32StartAddress), 4 << ctx->is_x64); ut64 uniqueid = 0; - windbg_read_at (ctx, (uint8_t *) &uniqueid, ptr + O_(ET_Cid) + O_(C_UniqueThread), 4 << ctx->is_x64); + winkd_read_at (ctx, (uint8_t *) &uniqueid, ptr + O_(ET_Cid) + O_(C_UniqueThread), 4 << ctx->is_x64); if (uniqueid) { WindThread *thread = calloc (1, sizeof(WindThread)); thread->uniqueid = uniqueid; @@ -614,7 +614,7 @@ RList *windbg_list_threads(WindCtx *ctx) { // http://blogs.msdn.com/b/ntdebugging/archive/2010/02/05/understanding-pte-part-1-let-s-get-physical.aspx // http://blogs.msdn.com/b/ntdebugging/archive/2010/04/14/understanding-pte-part2-flags-and-large-pages.aspx // http://blogs.msdn.com/b/ntdebugging/archive/2010/06/22/part-3-understanding-pte-non-pae-and-x64.aspx -bool windbg_va_to_pa(WindCtx *ctx, ut64 va, ut64 *pa) { +bool winkd_va_to_pa(WindCtx *ctx, ut64 va, ut64 *pa) { ut64 pml4i, pdpi, pdi, pti; ut64 tmp, mask; @@ -655,7 +655,7 @@ bool windbg_va_to_pa(WindCtx *ctx, ut64 va, ut64 *pa) { if (ctx->is_x64) { // PML4 lookup - if (!windbg_read_at_phys (ctx, (uint8_t *) &tmp, tmp + pml4i * 8, 8)) { + if (!winkd_read_at_phys (ctx, (uint8_t *) &tmp, tmp + pml4i * 8, 8)) { return false; } tmp &= mask; @@ -664,7 +664,7 @@ bool windbg_va_to_pa(WindCtx *ctx, ut64 va, ut64 *pa) { if (ctx->pae) { // PDPT lookup - if (!windbg_read_at_phys (ctx, (uint8_t *) &tmp, tmp + pdpi * 8, 8)) { + if (!winkd_read_at_phys (ctx, (uint8_t *) &tmp, tmp + pdpi * 8, 8)) { return false; } tmp &= mask; @@ -672,7 +672,7 @@ bool windbg_va_to_pa(WindCtx *ctx, ut64 va, ut64 *pa) { } // PDT lookup - if (!windbg_read_at_phys (ctx, (uint8_t *) &tmp, tmp + pdi * (4 << ctx->pae), 4 << ctx->pae)) { + if (!winkd_read_at_phys (ctx, (uint8_t *) &tmp, tmp + pdi * (4 << ctx->pae), 4 << ctx->pae)) { return false; } WIND_DBG eprintf("PDE : %016"PFMT64x "\n", tmp); @@ -688,7 +688,7 @@ bool windbg_va_to_pa(WindCtx *ctx, ut64 va, ut64 *pa) { } // PT lookup - if (!windbg_read_at_phys (ctx, (uint8_t *) &tmp, (tmp & mask) + pti * (4 << ctx->pae), 4 << ctx->pae)) { + if (!winkd_read_at_phys (ctx, (uint8_t *) &tmp, (tmp & mask) + pti * (4 << ctx->pae), 4 << ctx->pae)) { return false; } WIND_DBG eprintf("PTE : %016"PFMT64x "\n", tmp); @@ -706,7 +706,7 @@ bool windbg_va_to_pa(WindCtx *ctx, ut64 va, ut64 *pa) { return false; } -bool windbg_read_ver(WindCtx *ctx) { +bool winkd_read_ver(WindCtx *ctx) { kd_req_t req = { 0 }; @@ -720,7 +720,7 @@ bool windbg_read_ver(WindCtx *ctx) { req.req = 0x3146; req.cpu = ctx->cpu; - windbg_lock_enter (ctx); + winkd_lock_enter (ctx); ret = kd_send_data_packet (ctx->io_ptr, KD_PACKET_TYPE_STATE_MANIPULATE, (ctx->seq_id ^= 1), (uint8_t *) &req, sizeof(kd_req_t), NULL, 0); @@ -728,17 +728,17 @@ bool windbg_read_ver(WindCtx *ctx) { goto error; } - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); if (ret != KD_E_OK) { goto error; } - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_STATE_MANIPULATE, &pkt); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_STATE_MANIPULATE, &pkt); if (ret != KD_E_OK) { goto error; } - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); kd_req_t *rr = PKT_REQ (pkt); @@ -772,7 +772,7 @@ bool windbg_read_ver(WindCtx *ctx) { ctx->is_x64 = (rr->r_ver.machine == KD_MACH_AMD64); ut64 ptr = 0; - if (!windbg_read_at (ctx, (uint8_t *) &ptr, rr->r_ver.dbg_addr, 4 << ctx->is_x64)) { + if (!winkd_read_at (ctx, (uint8_t *) &ptr, rr->r_ver.dbg_addr, 4 << ctx->is_x64)) { free (pkt); return false; } @@ -783,17 +783,17 @@ bool windbg_read_ver(WindCtx *ctx) { // Thanks to this we don't have to find a way to read the cr4 uint16_t pae_enabled; - if (!windbg_read_at (ctx, (uint8_t *) &pae_enabled, ctx->dbg_addr + K_PaeEnabled, sizeof(uint16_t))) { + if (!winkd_read_at (ctx, (uint8_t *) &pae_enabled, ctx->dbg_addr + K_PaeEnabled, sizeof(uint16_t))) { free (pkt); return false; } // Grab the CmNtCSDVersion field to extract the Service Pack number - windbg_read_at (ctx, (uint8_t *) &ptr, ctx->dbg_addr + K_CmNtCSDVersion, 8); - windbg_read_at (ctx, (uint8_t *) &ptr, ptr, 4 << ctx->is_x64); + winkd_read_at (ctx, (uint8_t *) &ptr, ctx->dbg_addr + K_CmNtCSDVersion, 8); + winkd_read_at (ctx, (uint8_t *) &ptr, ptr, 4 << ctx->is_x64); ctx->pae = pae_enabled & 1; - ctx->os_profile = windbg_get_profile (32 << ctx->is_x64, rr->r_ver.minor, (ptr >> 8) & 0xff); + ctx->os_profile = winkd_get_profile (32 << ctx->is_x64, rr->r_ver.minor, (ptr >> 8) & 0xff); if (!ctx->os_profile) { eprintf ("Could not find a suitable profile for the target OS\n"); free (pkt); @@ -802,11 +802,11 @@ bool windbg_read_ver(WindCtx *ctx) { free (pkt); return true; error: - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); return 0; } -int windbg_sync(WindCtx *ctx) { +int winkd_sync(WindCtx *ctx) { int ret = -1; kd_packet_t *s; @@ -818,7 +818,7 @@ int windbg_sync(WindCtx *ctx) { return 1; } - windbg_lock_enter (ctx); + winkd_lock_enter (ctx); // Send the breakin packet if (iob_write (ctx->io_ptr, (const uint8_t *) "b", 1) != 1) { @@ -834,14 +834,14 @@ int windbg_sync(WindCtx *ctx) { } // Wait for the response - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_RESET, NULL); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_RESET, NULL); if (ret != KD_E_OK) { ret = 0; goto end; } // Syncronize with the first KD_PACKET_TYPE_STATE_CHANGE64 packet - windbg_wait_packet (ctx, KD_PACKET_TYPE_STATE_CHANGE64, &s); + winkd_wait_packet (ctx, KD_PACKET_TYPE_STATE_CHANGE64, &s); // Reset the sequence id ctx->seq_id = 0x80800001; @@ -863,11 +863,11 @@ int windbg_sync(WindCtx *ctx) { ret = 1; end: - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); return ret; } -int windbg_continue(WindCtx *ctx) { +int winkd_continue(WindCtx *ctx) { kd_req_t req = { 0 }; @@ -883,12 +883,12 @@ int windbg_continue(WindCtx *ctx) { // behave like suggested by ReactOS source req.r_cont.tf = 0x400; - windbg_lock_enter (ctx); + winkd_lock_enter (ctx); ret = kd_send_data_packet (ctx->io_ptr, KD_PACKET_TYPE_STATE_MANIPULATE, (ctx->seq_id ^= 1), (uint8_t *) &req, sizeof (kd_req_t), NULL, 0); if (ret == KD_E_OK) { - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); if (ret == KD_E_OK) { r_list_free (ctx->plist_cache); ctx->plist_cache = NULL; @@ -899,11 +899,11 @@ int windbg_continue(WindCtx *ctx) { ret = false; end: - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); return ret; } -bool windbg_write_reg(WindCtx *ctx, const uint8_t *buf, int size) { +bool winkd_write_reg(WindCtx *ctx, const uint8_t *buf, int size) { kd_packet_t *pkt; kd_req_t req = { 0 @@ -919,7 +919,7 @@ bool windbg_write_reg(WindCtx *ctx, const uint8_t *buf, int size) { WIND_DBG eprintf("Regwrite() size: %x\n", size); - windbg_lock_enter (ctx); + winkd_lock_enter (ctx); ret = kd_send_data_packet (ctx->io_ptr, KD_PACKET_TYPE_STATE_MANIPULATE, (ctx->seq_id ^= 1), (uint8_t *) &req, sizeof(kd_req_t), buf, size); @@ -927,17 +927,17 @@ bool windbg_write_reg(WindCtx *ctx, const uint8_t *buf, int size) { goto error; } - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); if (ret != KD_E_OK) { goto error; } - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_STATE_MANIPULATE, &pkt); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_STATE_MANIPULATE, &pkt); if (ret != KD_E_OK) { goto error; } - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); kd_req_t *rr = PKT_REQ (pkt); @@ -951,11 +951,11 @@ bool windbg_write_reg(WindCtx *ctx, const uint8_t *buf, int size) { return size; error: - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); return 0; } -int windbg_read_reg(WindCtx *ctx, uint8_t *buf, int size) { +int winkd_read_reg(WindCtx *ctx, uint8_t *buf, int size) { kd_req_t req; kd_packet_t *pkt = NULL; int ret; @@ -973,7 +973,7 @@ int windbg_read_reg(WindCtx *ctx, uint8_t *buf, int size) { // Don't wait on the lock in read_reg since it's frequently called. Otherwise the user // will be forced to interrupt exit read_reg constantly while another task is in progress - if (!windbg_lock_tryenter (ctx)) { + if (!winkd_lock_tryenter (ctx)) { goto error; } @@ -983,17 +983,17 @@ int windbg_read_reg(WindCtx *ctx, uint8_t *buf, int size) { goto error; } - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); if (ret != KD_E_OK) { goto error; } - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_STATE_MANIPULATE, &pkt); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_STATE_MANIPULATE, &pkt); if (ret != KD_E_OK) { goto error; } - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); kd_req_t *rr = PKT_REQ (pkt); @@ -1009,11 +1009,11 @@ int windbg_read_reg(WindCtx *ctx, uint8_t *buf, int size) { return size; error: - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); return 0; } -int windbg_query_mem(WindCtx *ctx, const ut64 addr, int *address_space, int *flags) { +int winkd_query_mem(WindCtx *ctx, const ut64 addr, int *address_space, int *flags) { kd_req_t req; kd_packet_t *pkt; int ret; @@ -1030,7 +1030,7 @@ int windbg_query_mem(WindCtx *ctx, const ut64 addr, int *address_space, int *fla req.r_query_mem.addr = addr; req.r_query_mem.address_space = 0; // Tells the kernel that 'addr' is a virtual address - windbg_lock_enter (ctx); + winkd_lock_enter (ctx); ret = kd_send_data_packet (ctx->io_ptr, KD_PACKET_TYPE_STATE_MANIPULATE, (ctx->seq_id ^= 1), (uint8_t *) &req, sizeof(kd_req_t), NULL, 0); @@ -1038,17 +1038,17 @@ int windbg_query_mem(WindCtx *ctx, const ut64 addr, int *address_space, int *fla goto error; } - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); if (ret != KD_E_OK) { goto error; } - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_STATE_MANIPULATE, &pkt); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_STATE_MANIPULATE, &pkt); if (ret != KD_E_OK) { goto error; } - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); kd_req_t *rr = PKT_REQ (pkt); @@ -1068,12 +1068,12 @@ int windbg_query_mem(WindCtx *ctx, const ut64 addr, int *address_space, int *fla return ret; error: - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); return 0; } -int windbg_bkpt(WindCtx *ctx, const ut64 addr, const int set, const int hw, int *handle) { +int winkd_bkpt(WindCtx *ctx, const ut64 addr, const int set, const int hw, int *handle) { kd_req_t req = { 0 }; @@ -1093,7 +1093,7 @@ int windbg_bkpt(WindCtx *ctx, const ut64 addr, const int set, const int hw, int req.r_del_bp.handle = *handle; } - windbg_lock_enter (ctx); + winkd_lock_enter (ctx); ret = kd_send_data_packet (ctx->io_ptr, KD_PACKET_TYPE_STATE_MANIPULATE, (ctx->seq_id ^= 1), (uint8_t *) &req, sizeof(kd_req_t), NULL, 0); @@ -1101,17 +1101,17 @@ int windbg_bkpt(WindCtx *ctx, const ut64 addr, const int set, const int hw, int goto error; } - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); if (ret != KD_E_OK) { goto error; } - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_STATE_MANIPULATE, &pkt); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_STATE_MANIPULATE, &pkt); if (ret != KD_E_OK) { goto error; } - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); kd_req_t *rr = PKT_REQ (pkt); @@ -1124,11 +1124,11 @@ int windbg_bkpt(WindCtx *ctx, const ut64 addr, const int set, const int hw, int free (pkt); return ret; error: - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); return 0; } -int windbg_read_at_phys(WindCtx *ctx, uint8_t *buf, const ut64 offset, const int count) { +int winkd_read_at_phys(WindCtx *ctx, uint8_t *buf, const ut64 offset, const int count) { kd_req_t req = { 0 }, *rr; @@ -1146,7 +1146,7 @@ int windbg_read_at_phys(WindCtx *ctx, uint8_t *buf, const ut64 offset, const int // Don't wait on the lock in read_reg since it's frequently called. Otherwise the user // will be forced to interrupt exit read_at_phys constantly while another task is in progress - if (!windbg_lock_tryenter (ctx)) { + if (!winkd_lock_tryenter (ctx)) { goto error; } @@ -1156,17 +1156,17 @@ int windbg_read_at_phys(WindCtx *ctx, uint8_t *buf, const ut64 offset, const int goto error; } - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); if (ret != KD_E_OK) { goto error; } - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_STATE_MANIPULATE, &pkt); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_STATE_MANIPULATE, &pkt); if (ret != KD_E_OK) { goto error; } - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); rr = PKT_REQ (pkt); @@ -1180,11 +1180,11 @@ int windbg_read_at_phys(WindCtx *ctx, uint8_t *buf, const ut64 offset, const int free (pkt); return ret; error: - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); return 0; } -int windbg_read_at(WindCtx *ctx, uint8_t *buf, const ut64 offset, const int count) { +int winkd_read_at(WindCtx *ctx, uint8_t *buf, const ut64 offset, const int count) { kd_req_t *rr, req = { 0 }; @@ -1202,7 +1202,7 @@ int windbg_read_at(WindCtx *ctx, uint8_t *buf, const ut64 offset, const int coun // Don't wait on the lock in read_at since it's frequently called, including each // time "enter" is pressed. Otherwise the user will be forced to interrupt exit // read_registers constantly while another task is in progress - if (!windbg_lock_tryenter (ctx)) { + if (!winkd_lock_tryenter (ctx)) { goto error; } @@ -1212,16 +1212,16 @@ int windbg_read_at(WindCtx *ctx, uint8_t *buf, const ut64 offset, const int coun goto error; } - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); if (ret != KD_E_OK) { goto error; } - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_STATE_MANIPULATE, &pkt); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_STATE_MANIPULATE, &pkt); if (ret != KD_E_OK) { return 0; } - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); rr = PKT_REQ (pkt); @@ -1235,11 +1235,11 @@ int windbg_read_at(WindCtx *ctx, uint8_t *buf, const ut64 offset, const int coun free (pkt); return ret; error: - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); return 0; } -int windbg_write_at(WindCtx *ctx, const uint8_t *buf, const ut64 offset, const int count) { +int winkd_write_at(WindCtx *ctx, const uint8_t *buf, const ut64 offset, const int count) { kd_packet_t *pkt; kd_req_t req = { 0 @@ -1256,7 +1256,7 @@ int windbg_write_at(WindCtx *ctx, const uint8_t *buf, const ut64 offset, const i req.r_mem.addr = offset; req.r_mem.length = payload; - windbg_lock_enter (ctx); + winkd_lock_enter (ctx); ret = kd_send_data_packet (ctx->io_ptr, KD_PACKET_TYPE_STATE_MANIPULATE, (ctx->seq_id ^= 1), (uint8_t *) &req, @@ -1265,17 +1265,17 @@ int windbg_write_at(WindCtx *ctx, const uint8_t *buf, const ut64 offset, const i goto error; } - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); if (ret != KD_E_OK) { goto error; } - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_STATE_MANIPULATE, &pkt); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_STATE_MANIPULATE, &pkt); if (ret != KD_E_OK) { goto error; } - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); rr = PKT_REQ (pkt); @@ -1288,11 +1288,11 @@ int windbg_write_at(WindCtx *ctx, const uint8_t *buf, const ut64 offset, const i free (pkt); return ret; error: - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); return 0; } -int windbg_write_at_phys(WindCtx *ctx, const uint8_t *buf, const ut64 offset, const int count) { +int winkd_write_at_phys(WindCtx *ctx, const uint8_t *buf, const ut64 offset, const int count) { kd_packet_t *pkt; kd_req_t req; int ret; @@ -1313,7 +1313,7 @@ int windbg_write_at_phys(WindCtx *ctx, const uint8_t *buf, const ut64 offset, co req.r_mem.length = payload; req.r_mem.read = 0; // Default caching option - windbg_lock_enter (ctx); + winkd_lock_enter (ctx); ret = kd_send_data_packet (ctx->io_ptr, KD_PACKET_TYPE_STATE_MANIPULATE, (ctx->seq_id ^= 1), (uint8_t *) &req, sizeof(kd_req_t), buf, payload); @@ -1321,17 +1321,17 @@ int windbg_write_at_phys(WindCtx *ctx, const uint8_t *buf, const ut64 offset, co goto error; } - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_ACKNOWLEDGE, NULL); if (ret != KD_E_OK) { goto error; } - ret = windbg_wait_packet (ctx, KD_PACKET_TYPE_STATE_MANIPULATE, &pkt); + ret = winkd_wait_packet (ctx, KD_PACKET_TYPE_STATE_MANIPULATE, &pkt); if (ret != KD_E_OK) { goto error; } - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); kd_req_t *rr = PKT_REQ (pkt); @@ -1343,18 +1343,18 @@ int windbg_write_at_phys(WindCtx *ctx, const uint8_t *buf, const ut64 offset, co free (pkt); return ret; error: - windbg_lock_leave (ctx); + winkd_lock_leave (ctx); return 0; } -void windbg_break(void *arg) { +void winkd_break(void *arg) { // This command shouldn't be wrapped by locks since it can always be sent and we don't // want break queued up after another background task WindCtx *ctx = (WindCtx *)arg; (void)iob_write (ctx->io_ptr, (const uint8_t *)"b", 1); } -int windbg_break_read(WindCtx *ctx) { +int winkd_break_read(WindCtx *ctx) { #if __WINDOWS__ && !defined(_MSC_VER) static BOOL WINAPI (*w32_CancelIoEx)(HANDLE, LPOVERLAPPED) = NULL; if (!w32_CancelIoEx) { diff --git a/shlr/winkd/winkd.h b/shlr/winkd/winkd.h new file mode 100644 index 0000000000..e1af67e546 --- /dev/null +++ b/shlr/winkd/winkd.h @@ -0,0 +1,113 @@ +// Copyright (c) 2014, The Lemon Man, All rights reserved. + +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public +// License along with this library. + +#ifndef _winkd_H_ +#define _winkd_H_ + +#include +#include "kd.h" + +typedef struct _WindCtx WindCtx; + +typedef struct WindProc { + ut64 eprocess; + ut32 uniqueid; + ut64 vadroot; + ut64 dir_base_table; + ut64 peb; + char name[17]; +} WindProc; + +typedef struct WindThread { + ut32 uniqueid; + bool runnable; + char status; + ut64 ethread; + ut64 entrypoint; +} WindThread; + +typedef struct WindModule { + char *name; + ut64 addr; + ut64 size; +} WindModule; + +enum { + K_PaeEnabled = 0x036, + K_PsActiveProcessHead = 0x050, + K_CmNtCSDVersion = 0x268, +}; + +enum { + E_ActiveProcessLinks, // EPROCESS + E_UniqueProcessId, // EPROCESS + E_Peb, // EPROCESS + E_ImageFileName, // EPROCESS + E_VadRoot, // EPROCESS + E_ThreadListHead, // EPROCESS + P_DirectoryTableBase, // PCB + P_ImageBaseAddress, // PEB + P_ProcessParameters, // PEB + R_ImagePathName, // RTL_USER_PROCESS_PARAMETERS + ET_Tcb, // ETHREAD + ET_ThreadListEntry, // ETHREAD + ET_Win32StartAddress, // ETHREAD + ET_Cid, // ETHREAD + C_UniqueThread, // CLIENT_ID + O_Max, +}; + +typedef struct { + int build; + int sp; + int bits; + int flags; + int f[O_Max]; +} Profile; + +// grep -e "^winkd_" shlr/wind/wind.c | sed -e 's/ {$/;/' -e 's/^/int /' +int winkd_get_bits(WindCtx *ctx); +ut64 winkd_get_target_base(WindCtx *ctx); +ut32 winkd_get_target(WindCtx *ctx); +bool winkd_set_target(WindCtx *ctx, ut32 pid); +RList *winkd_list_process(WindCtx *ctx); +RList *winkd_list_threads(WindCtx *ctx); +RList *winkd_list_modules(WindCtx *ctx); +int winkd_get_cpus(WindCtx *ctx); +bool winkd_set_cpu(WindCtx *ctx, int cpu); +int winkd_get_cpu(WindCtx *ctx); +WindCtx * winkd_ctx_new(void *io_ptr); +void winkd_ctx_free(WindCtx **ctx); +int winkd_wait_packet(WindCtx *ctx, const ut32 type, kd_packet_t **p); +int winkd_sync(WindCtx *ctx); +bool winkd_read_ver(WindCtx *ctx); +int winkd_continue(WindCtx *ctx); +bool winkd_write_reg(WindCtx *ctx, const uint8_t *buf, int size); +int winkd_read_reg(WindCtx *ctx, uint8_t *buf, int size); +int winkd_query_mem(WindCtx *ctx, const ut64 addr, int *address_space, int *flags); +int winkd_bkpt(WindCtx *ctx, const ut64 addr, const int set, const int hw, int *handle); +int winkd_read_at(WindCtx *ctx, uint8_t *buf, const ut64 offset, const int count); +int winkd_read_at_uva(WindCtx *ctx, uint8_t *buf, ut64 offset, int count); +int winkd_read_at_phys(WindCtx *ctx, uint8_t *buf, const ut64 offset, const int count); +int winkd_write_at(WindCtx *ctx, const uint8_t *buf, const ut64 offset, const int count); +int winkd_write_at_uva(WindCtx *ctx, const uint8_t *buf, ut64 offset, int count); +int winkd_write_at_phys(WindCtx *ctx, const uint8_t *buf, const ut64 offset, const int count); +bool winkd_va_to_pa(WindCtx *ctx, ut64 va, ut64 *pa); +void winkd_break(void *ctx); +int winkd_break_read(WindCtx *ctx); +bool winkd_lock_enter(WindCtx *ctx); +bool winkd_lock_leave(WindCtx *ctx); +bool winkd_lock_tryenter(WindCtx *ctx); +#endif diff --git a/sys/rebuild.sh b/sys/rebuild.sh index 2c6a53ce1c..b2843fb183 100755 --- a/sys/rebuild.sh +++ b/sys/rebuild.sh @@ -84,8 +84,8 @@ RebuildGdb() { Rebuild libr/debug } -RebuildWindbg() { - Rebuild shlr/windbg +RebuildWinkd() { + Rebuild shlr/winkd Rebuild libr/io Rebuild libr/debug } @@ -104,7 +104,7 @@ case "$1" in grub|fs)RebuildFs; ;; bin) RebuildBin ; ;; gdb) RebuildGdb ; ;; -windbg) RebuildWindbg ; ;; +winkd) RebuildWinkd ; ;; sdb) RebuildSdb ; ;; spp) RebuildSpp ; ;; tcc) RebuildTcc ; ;; diff --git a/test/db/archos/linux-x64/dbg_dL b/test/db/archos/linux-x64/dbg_dL index 1ee575b956..34dbba6260 100644 --- a/test/db/archos/linux-x64/dbg_dL +++ b/test/db/archos/linux-x64/dbg_dL @@ -11,6 +11,6 @@ EXPECT=<