Add DbgEng based debug backend for Windows ##debug (#17491)

* Rename `windbg` plugin to `winkd` ##debug
* Add DbgEng based debug backend for Windows ##debug
This commit is contained in:
GustavoLCR 2020-08-24 08:01:10 -03:00 committed by GitHub
parent d8d7edf470
commit 489538e02b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 2183 additions and 677 deletions

4
.github/labeler.yml vendored
View File

@ -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/**/*

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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}

View File

@ -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}

View File

@ -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',

View File

@ -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:

View File

@ -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 <r_asm.h>
#include <r_debug.h>
#include <windbg.h>
#include <kd.h>
#include <DbgEng.h>
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

295
libr/debug/p/debug_winkd.c Normal file
View File

@ -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 <r_asm.h>
#include <r_debug.h>
#include <winkd.h>
#include <kd.h>
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

View File

@ -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;

View File

@ -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"
);

View File

@ -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"
);

View File

@ -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);

View File

@ -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}

24
libr/debug/p/winkd.mk Normal file
View File

@ -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}

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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}

View File

@ -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 <r_core.h>
#include <DbgEng.h>
// 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 <r_io.h>
#include <r_lib.h>
#include <r_socket.h>
#include <r_util.h>
#include <transport.h>
#include <windbg.h>
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

112
libr/io/p/io_winkd.c Normal file
View File

@ -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 <r_io.h>
#include <r_lib.h>
#include <r_socket.h>
#include <r_util.h>
#include <transport.h>
#include <winkd.h>
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

View File

@ -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)

21
libr/io/p/winkd.mk Normal file
View File

@ -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)

View File

@ -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 = [

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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}:

View File

@ -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
)

View File

@ -1 +0,0 @@
LINK+=$(STOP)/windbg/libr_windbg.${EXT_AR}

View File

@ -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 <stdint.h>
#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

View File

@ -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}

1
shlr/winkd/deps.mk Normal file
View File

@ -0,0 +1 @@
LINK+=$(STOP)/winkd/libr_winkd.${EXT_AR}

View File

@ -8,7 +8,7 @@
#include <r_cons.h>
#include <r_list.h>
#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) {

113
shlr/winkd/winkd.h Normal file
View File

@ -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 <stdint.h>
#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

View File

@ -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 ; ;;

View File

@ -11,6 +11,6 @@ EXPECT=<<EOF
6 --- null MIT
7 --- qnx LGPL3
8 --- rap LGPL3
9 --- windbg LGPL3
9 --- winkd LGPL3
EOF
RUN