Rizin
unix-like reverse engineering framework and cli tools
windows_debug.c File Reference
#include <ntstatus.h>
#include "windows_debug.h"
#include "../../common_windows.h"
#include <w32dbg_wrap.h>

Go to the source code of this file.

Macros

#define WIN32_NO_STATUS
 
#define SystemHandleInformation   16
 

Functions

bool setup_debug_privileges (bool b)
 
int w32_init (RzDebug *dbg)
 
static int w32_findthread_cmp (int *tid, PTHREAD_ITEM th)
 
static PTHREAD_ITEM find_thread (RzDebug *dbg, int tid)
 
static PTHREAD_ITEM add_thread (RzDebug *dbg, DWORD pid, DWORD tid, HANDLE hThread, LPVOID lpThreadLocalBase, LPVOID lpStartAddress, BOOL bFinished)
 
static int suspend_thread (HANDLE th)
 
static int resume_thread (HANDLE th)
 
static void continue_thread (HANDLE th)
 
static bool is_thread_alive (RzDebug *dbg, int tid)
 
static bool is_process_alive (HANDLE ph)
 
static int set_thread_context (HANDLE th, const ut8 *buf, int size)
 
static int get_thread_context (HANDLE th, ut8 *buf, int size, DWORD context_flags)
 
static void transfer_drx (RzDebug *dbg, const ut8 *buf)
 
static void print_fpu_context (HANDLE th, CONTEXT *buf)
 
int w32_step (RzDebug *dbg)
 
static void get_arm_hwbp_values (ut64 address, ut32 *control, ut64 *value)
 
static void get_arm64_hwwp_values (ut64 address, int size, int rw, ut32 *control, ut64 *value)
 
static bool is_watchpoint (RzBreakpointItem *b)
 
static bool is_breakpoint (RzBreakpointItem *b)
 
int w32_hwbp_arm_add (RzDebug *dbg, RzBreakpoint *bp, RzBreakpointItem *b)
 
int w32_hwbp_arm_del (RzDebug *dbg, RzBreakpoint *bp, RzBreakpointItem *b)
 
static HANDLE get_thread_handle_from_tid (RzDebug *dbg, int tid)
 
int w32_reg_read (RzDebug *dbg, int type, ut8 *buf, int size)
 
int w32_reg_write (RzDebug *dbg, int type, const ut8 *buf, int size)
 
static bool already_attached (W32DbgWInst *wrap, int pid)
 
int w32_attach (RzDebug *dbg, int pid)
 
int w32_detach (RzDebug *dbg, int pid)
 
static char * get_file_name_from_handle (HANDLE handle_file)
 
static char * resolve_path (HANDLE ph, HANDLE mh)
 
static void libfree (void *lib)
 
static int findlibcmp (void *BaseOfDll, void *lib)
 
static void * find_library (void *BaseOfDll)
 
static void remove_library (PLIB_ITEM library)
 
static void add_library (DWORD pid, LPVOID lpBaseOfDll, HANDLE hFile, char *dllname)
 
static void * last_library (void)
 
int w32_attach_new_process (RzDebug *dbg, int pid)
 
int w32_select (RzDebug *dbg, int pid, int tid)
 
int w32_kill (RzDebug *dbg, int pid, int tid, int sig)
 
void w32_break_process (void *user)
 
int w32_dbg_wait (RzDebug *dbg, int pid)
 
int w32_continue (RzDebug *dbg, int pid, int tid, int sig)
 
RzDebugMapw32_map_alloc (RzDebug *dbg, ut64 addr, int size)
 
int w32_map_dealloc (RzDebug *dbg, ut64 addr, int size)
 
static int io_perms_to_prot (int io_perms)
 
int w32_map_protect (RzDebug *dbg, ut64 addr, int size, int perms)
 
static ut64 pc_from_context (CONTEXT *ctx)
 
static char * get_process_path (HANDLE ph, int pid)
 
RzListw32_thread_list (RzDebug *dbg, int pid, RzList *list)
 
static void w32_info_user (RzDebug *dbg, RzDebugInfo *rdi)
 
static void w32_info_exe (RzDebug *dbg, RzDebugInfo *rdi)
 
RzDebugInfow32_info (RzDebug *dbg, const char *arg)
 
static RzDebugPidbuild_debug_pid (int pid, int ppid, HANDLE ph, const WCHAR *name)
 
RzListw32_pid_list (RzDebug *dbg, int pid, RzList *list)
 
RzListw32_desc_list (int pid)
 

Variables

const DWORD wait_time = 1000
 
static RzListlib_list = NULL
 
static bool breaked = false
 

Macro Definition Documentation

◆ SystemHandleInformation

#define SystemHandleInformation   16

Definition at line 14 of file windows_debug.c.

◆ WIN32_NO_STATUS

#define WIN32_NO_STATUS

Definition at line 5 of file windows_debug.c.

Function Documentation

◆ add_library()

static void add_library ( DWORD  pid,
LPVOID  lpBaseOfDll,
HANDLE  hFile,
char *  dllname 
)
static

Definition at line 782 of file windows_debug.c.

782  {
783  if (lib_list == NULL) {
785  if (!lib_list) {
786  RZ_LOG_ERROR("Failed to allocate memory");
787  return;
788  }
789  }
790  RzListIter *it;
791  PLIB_ITEM lib;
792  rz_list_foreach (lib_list, it, lib) {
793  if (lib->hFile == hFile && lib->BaseOfDll == lpBaseOfDll) {
794  return;
795  }
796  }
797  lib = RZ_NEW0(LIB_ITEM);
798  if (!lib) {
799  RZ_LOG_ERROR("Failed to allocate memory");
800  return;
801  }
802  lib->pid = pid;
803  lib->hFile = hFile;
804  lib->BaseOfDll = lpBaseOfDll;
805  lib->Path = strdup(dllname);
806  lib->Name = strdup(rz_file_basename(dllname));
807 
808  (void)rz_list_append(lib_list, lib);
809 }
#define NULL
Definition: cris-opc.c:27
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc pid
Definition: sflib.h:64
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\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" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
RZ_API const char * rz_file_basename(const char *path)
Definition: file.c:83
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
#define RZ_NEW0(x)
Definition: rz_types.h:284
void * BaseOfDll
char * Path
char * Name
HANDLE hFile
static void libfree(void *lib)
static RzList * lib_list
Definition: windows_debug.c:12

References LIB_ITEM::BaseOfDll, LIB_ITEM::hFile, lib_list, libfree(), LIB_ITEM::Name, NULL, LIB_ITEM::Path, LIB_ITEM::pid, pid, rz_file_basename(), rz_list_append(), rz_list_newf(), RZ_LOG_ERROR, RZ_NEW0, and strdup().

Referenced by w32_dbg_wait().

◆ add_thread()

static PTHREAD_ITEM add_thread ( RzDebug dbg,
DWORD  pid,
DWORD  tid,
HANDLE  hThread,
LPVOID  lpThreadLocalBase,
LPVOID  lpStartAddress,
BOOL  bFinished 
)
static

Definition at line 107 of file windows_debug.c.

107  {
109  if (!dbg->threads) {
111  }
112  if (!lpStartAddress) {
113  w32_NtQueryInformationThread(hThread, 9, &lpStartAddress, sizeof(LPVOID), NULL);
114  }
115  THREAD_ITEM th = {
116  pid,
117  tid,
118  bFinished,
119  false,
120  hThread,
121  lpThreadLocalBase,
122  lpStartAddress
123  };
124  PTHREAD_ITEM pthread = find_thread(dbg, tid);
125  if (pthread) {
126  *pthread = th;
127  return NULL;
128  }
129  pthread = RZ_NEW0(THREAD_ITEM);
130  if (!pthread) {
131  RZ_LOG_ERROR("Memory allocation failed.\n");
132  return NULL;
133  }
134  *pthread = th;
135  rz_list_append(dbg->threads, pthread);
136  return pthread;
137 }
RzDebug * dbg
Definition: desil.c:30
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RzList * threads
Definition: rz_debug.h:251
static PTHREAD_ITEM find_thread(RzDebug *dbg, int tid)
Definition: windows_debug.c:99

References dbg, find_thread(), free(), NULL, pid, rz_list_append(), rz_list_newf(), RZ_LOG_ERROR, RZ_NEW0, rz_return_val_if_fail, and rz_debug_t::threads.

Referenced by w32_dbg_wait().

◆ already_attached()

static bool already_attached ( W32DbgWInst wrap,
int  pid 
)
inlinestatic

Definition at line 594 of file windows_debug.c.

594  {
595  return wrap->pi.hProcess && wrap->pi.dwProcessId == pid && wrap->pi.dwThreadId;
596 }
PROCESS_INFORMATION pi
Definition: w32dbg_wrap.h:40

References W32DbgWInst::pi, and pid.

Referenced by w32_attach().

◆ build_debug_pid()

static RzDebugPid* build_debug_pid ( int  pid,
int  ppid,
HANDLE  ph,
const WCHAR *  name 
)
static

Definition at line 1425 of file windows_debug.c.

1425  {
1426  char *path = get_process_path(ph, pid);
1427  int uid = -1;
1428 
1429  DWORD sid;
1430  if (w32_ProcessIdToSessionId && w32_ProcessIdToSessionId(pid, &sid)) {
1431  uid = sid;
1432  }
1433  if (!path) {
1434  path = rz_utf16_to_utf8(name);
1435  }
1436  // it is possible to get pc for a non debugged process but the operation is expensive and might be risky
1437  RzDebugPid *ret = rz_debug_pid_new(path, pid, uid, 's', 0);
1438  ret->ppid = ppid;
1439  free(path);
1440  return ret;
1441 }
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
#define ph(a_type)
Definition: ph.h:27
RZ_API RzDebugPid * rz_debug_pid_new(const char *path, int pid, int uid, char status, ut64 pc)
Definition: pid.c:6
Definition: z80asm.h:102
static char * get_process_path(HANDLE ph, int pid)
DWORD

References DWORD, free(), get_process_path(), path, ph, pid, rz_debug_pid_t::ppid, and rz_debug_pid_new().

Referenced by w32_pid_list().

◆ continue_thread()

static void continue_thread ( HANDLE  th)
inlinestatic

Definition at line 155 of file windows_debug.c.

155  {
156  int ret;
157  do {
158  ret = resume_thread(th);
159  } while (ret > 0);
160 }
static int resume_thread(HANDLE th)

References resume_thread().

Referenced by w32_continue().

◆ find_library()

static void* find_library ( void *  BaseOfDll)
static

Definition at line 773 of file windows_debug.c.

773  {
775  return it ? it->data : NULL;
776 }
RZ_API RZ_BORROW RzListIter * rz_list_find(RZ_NONNULL const RzList *list, const void *p, RZ_NONNULL RzListComparator cmp)
Returns RzListIter element which matches via the RzListComparator.
Definition: list.c:620
int(* RzListComparator)(const void *value, const void *list_data)
Definition: rz_list.h:33
void * data
Definition: rz_list.h:14
static int findlibcmp(void *BaseOfDll, void *lib)

References rz_list_iter_t::data, findlibcmp(), lib_list, NULL, and rz_list_find().

Referenced by w32_dbg_wait().

◆ find_thread()

static PTHREAD_ITEM find_thread ( RzDebug dbg,
int  tid 
)
inlinestatic

Definition at line 99 of file windows_debug.c.

99  {
100  if (!dbg->threads) {
101  return NULL;
102  }
104  return it ? it->data : NULL;
105 }
static int w32_findthread_cmp(int *tid, PTHREAD_ITEM th)
Definition: windows_debug.c:95

References rz_list_iter_t::data, dbg, NULL, rz_list_find(), rz_debug_t::threads, and w32_findthread_cmp().

Referenced by add_thread(), get_thread_handle_from_tid(), is_thread_alive(), uv_resident_set_memory(), w32_continue(), w32_dbg_wait(), w32_info(), w32_select(), and w32_thread_list().

◆ findlibcmp()

static int findlibcmp ( void *  BaseOfDll,
void *  lib 
)
static

Definition at line 768 of file windows_debug.c.

768  {
769  PLIB_ITEM lib_item = (PLIB_ITEM)lib;
770  return !lib_item->hFile || lib_item->hFile == INVALID_HANDLE_VALUE || lib_item->BaseOfDll != BaseOfDll;
771 }
#define INVALID_HANDLE_VALUE
Definition: iowin32.c:21
struct LIB_ITEM * PLIB_ITEM

References LIB_ITEM::BaseOfDll, LIB_ITEM::hFile, and INVALID_HANDLE_VALUE.

Referenced by find_library().

◆ get_arm64_hwwp_values()

static void get_arm64_hwwp_values ( ut64  address,
int  size,
int  rw,
ut32 control,
ut64 value 
)
inlinestatic

Definition at line 409 of file windows_debug.c.

409  {
410  const unsigned int offset = address % 8;
411  const ut32 byte_mask = ((1 << size) - 1) << offset;
412  const ut32 priv = 1 << 2;
413  const ut32 enable = 1;
414  ut32 load_store = 0;
415  switch (rw) {
416  case RZ_PERM_R:
417  load_store = 1;
418  break;
419  case RZ_PERM_W:
420  load_store = 2;
421  break;
422  case RZ_PERM_RW:
423  load_store = 3;
424  break;
425  }
426  *control = byte_mask << 5 | load_store << 3 | priv | enable;
427  *value = address - offset;
428 }
static int value
Definition: cmd_api.c:93
uint32_t ut32
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
#define RZ_PERM_R
Definition: rz_types.h:93
#define RZ_PERM_RW
Definition: rz_types.h:96
#define RZ_PERM_W
Definition: rz_types.h:94
control

References control, RZ_PERM_R, RZ_PERM_RW, RZ_PERM_W, and value.

Referenced by w32_hwbp_arm_add(), and w32_hwbp_arm_del().

◆ get_arm_hwbp_values()

static void get_arm_hwbp_values ( ut64  address,
ut32 control,
ut64 value 
)
inlinestatic

Definition at line 400 of file windows_debug.c.

400  {
401  const ut32 type = 0b0100 << 20; // match
402  const ut32 bas = 0xF << 5; // match a64 and a32
403  const ut32 priv = 1 << 2;
404  const ut32 enable = 1;
405  *control = type | bas | priv | enable;
406  *value = address;
407 }
int type
Definition: mipsasm.c:17

References control, type, and value.

Referenced by w32_hwbp_arm_add(), and w32_hwbp_arm_del().

◆ get_file_name_from_handle()

static char* get_file_name_from_handle ( HANDLE  handle_file)
static

Definition at line 649 of file windows_debug.c.

649  {
650  HANDLE handle_file_map = NULL;
651  LPWSTR filename = NULL;
652  DWORD file_size_high = 0;
653  LPVOID map = NULL;
654  DWORD file_size_low = GetFileSize(handle_file, &file_size_high);
655 
656  if (file_size_low == 0 && file_size_high == 0) {
657  return NULL;
658  }
659  handle_file_map = CreateFileMappingW(handle_file, NULL, PAGE_READONLY, 0, 1, NULL);
660  if (!handle_file_map) {
661  goto err_get_file_name_from_handle;
662  }
663  filename = malloc((MAX_PATH + 1) * sizeof(WCHAR));
664  if (!filename) {
665  goto err_get_file_name_from_handle;
666  }
667  /* Create a file mapping to get the file name. */
668  map = MapViewOfFile(handle_file_map, FILE_MAP_READ, 0, 0, 1);
669  if (!map || !GetMappedFileNameW(GetCurrentProcess(), map, filename, MAX_PATH)) {
670  RZ_FREE(filename);
671  goto err_get_file_name_from_handle;
672  }
673  WCHAR temp_buffer[512];
674  /* Translate path with device name to drive letters. */
675  if (!GetLogicalDriveStringsW(_countof(temp_buffer) - 1, temp_buffer)) {
676  goto err_get_file_name_from_handle;
677  }
678  WCHAR name[MAX_PATH];
679  WCHAR drive[3] = L" :";
680  LPWSTR cur_drive = temp_buffer;
681  while (*cur_drive) {
682  /* Look up each device name */
683  *drive = *cur_drive;
684  if (QueryDosDeviceW(drive, name, MAX_PATH)) {
685  size_t name_length = wcslen(name);
686 
687  if (name_length < MAX_PATH) {
688  if (wcsnicmp(filename, name, name_length) == 0 && *(filename + name_length) == L'\\') {
689  WCHAR temp_filename[MAX_PATH];
690  _snwprintf_s(temp_filename, MAX_PATH, _TRUNCATE, L"%s%s",
691  drive, filename + name_length);
692  wcsncpy(filename, temp_filename,
693  wcslen(temp_filename) + 1);
694  filename[MAX_PATH] = L'\0';
695  break;
696  }
697  }
698  }
699  cur_drive++;
700  }
701 err_get_file_name_from_handle:
702  if (map) {
703  UnmapViewOfFile(map);
704  }
705  if (handle_file_map) {
706  CloseHandle(handle_file_map);
707  }
708  if (filename) {
709  char *ret = rz_sys_conv_win_to_utf8(filename);
710  free(filename);
711  return ret;
712  }
713  return NULL;
714 }
size_t map(int syms, int left, int len)
Definition: enough.c:237
const char * filename
Definition: ioapi.h:137
void * malloc(size_t size)
Definition: malloc.c:123
#define RZ_FREE(x)
Definition: rz_types.h:369
DWORD LPWSTR
DWORD * HANDLE
#define L
Definition: zip_err_str.c:7

References DWORD, free(), HANDLE, L, LPWSTR, malloc(), map(), NULL, and RZ_FREE.

Referenced by resolve_path().

◆ get_process_path()

static char* get_process_path ( HANDLE  ph,
int  pid 
)
static

Definition at line 1249 of file windows_debug.c.

1249  {
1250  bool close_handle = false;
1251  char *path = NULL;
1252  if (!ph) {
1253  ph = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
1254  if (!ph) {
1255  ph = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
1256  if (!ph) {
1257  ph = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
1258  if (!ph) {
1259  return NULL;
1260  }
1261  }
1262  }
1263  close_handle = true;
1264  }
1265  if (w32_QueryFullProcessImageNameW) {
1266  WCHAR tmp[MAX_PATH + 1];
1267  DWORD sz = MAX_PATH;
1268  if (w32_QueryFullProcessImageNameW(ph, 0, tmp, &sz)) {
1269  path = rz_utf16_to_utf8(tmp);
1270  }
1271  } else {
1272  path = resolve_path(ph, NULL);
1273  }
1274  if (close_handle) {
1275  CloseHandle(ph);
1276  }
1277  return path;
1278 }
#define FALSE
Definition: mybfd.h:102
static char * resolve_path(HANDLE ph, HANDLE mh)

References DWORD, FALSE, NULL, path, ph, pid, resolve_path(), and autogen_x86imm::tmp.

Referenced by build_debug_pid(), and w32_thread_list().

◆ get_thread_context()

static int get_thread_context ( HANDLE  th,
ut8 buf,
int  size,
DWORD  context_flags 
)
static

Definition at line 199 of file windows_debug.c.

199  {
200  int ret = 0;
201  CONTEXT ctx = { 0 };
202  // TODO: support various types?
203  ctx.ContextFlags = context_flags;
204  if (GetThreadContext(th, &ctx)) {
205  if (size > sizeof(ctx)) {
206  size = sizeof(ctx);
207  }
208  memcpy(buf, &ctx, size);
209  ret = size;
210  } else {
211  if (is_process_alive(th)) {
212  rz_sys_perror("GetThreadContext");
213  }
214  }
215  return ret;
216 }
voidpf void * buf
Definition: ioapi.h:138
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
#define rz_sys_perror(x)
Definition: rz_types.h:336
static bool is_process_alive(HANDLE ph)

References is_process_alive(), memcpy(), and rz_sys_perror.

Referenced by w32_dbg_wait(), w32_hwbp_arm_add(), w32_hwbp_arm_del(), and w32_reg_read().

◆ get_thread_handle_from_tid()

static HANDLE get_thread_handle_from_tid ( RzDebug dbg,
int  tid 
)
static

Definition at line 529 of file windows_debug.c.

529  {
531  W32DbgWInst *wrap = dbg->plugin_data;
532  HANDLE th = NULL;
533  if (wrap->pi.dwThreadId == tid) {
534  th = wrap->pi.hThread;
535  } else {
536  PTHREAD_ITEM thread = find_thread(dbg, tid);
537  if (thread) {
538  th = thread->hThread;
539  }
540  }
541  return th;
542 }
HANDLE hThread
void * plugin_data
Definition: rz_debug.h:296

References dbg, find_thread(), HANDLE, THREAD_ITEM::hThread, NULL, W32DbgWInst::pi, rz_debug_t::plugin_data, and rz_return_val_if_fail.

Referenced by w32_reg_read(), and w32_reg_write().

◆ io_perms_to_prot()

static int io_perms_to_prot ( int  io_perms)
static

Definition at line 1206 of file windows_debug.c.

1206  {
1207  int prot_perms;
1208 
1209  if ((io_perms & RZ_PERM_RWX) == RZ_PERM_RWX) {
1210  prot_perms = PAGE_EXECUTE_READWRITE;
1211  } else if ((io_perms & (RZ_PERM_W | RZ_PERM_X)) == (RZ_PERM_W | RZ_PERM_X)) {
1212  prot_perms = PAGE_EXECUTE_READWRITE;
1213  } else if ((io_perms & (RZ_PERM_R | RZ_PERM_X)) == (RZ_PERM_R | RZ_PERM_X)) {
1214  prot_perms = PAGE_EXECUTE_READ;
1215  } else if ((io_perms & RZ_PERM_RW) == RZ_PERM_RW) {
1216  prot_perms = PAGE_READWRITE;
1217  } else if (io_perms & RZ_PERM_W) {
1218  prot_perms = PAGE_READWRITE;
1219  } else if (io_perms & RZ_PERM_X) {
1220  prot_perms = PAGE_EXECUTE;
1221  } else if (io_perms & RZ_PERM_R) {
1222  prot_perms = PAGE_READONLY;
1223  } else {
1224  prot_perms = PAGE_NOACCESS;
1225  }
1226  return prot_perms;
1227 }
#define RZ_PERM_X
Definition: rz_types.h:95
#define RZ_PERM_RWX
Definition: rz_types.h:98

References RZ_PERM_R, RZ_PERM_RW, RZ_PERM_RWX, RZ_PERM_W, and RZ_PERM_X.

Referenced by w32_map_protect().

◆ is_breakpoint()

static bool is_breakpoint ( RzBreakpointItem b)
inlinestatic

Definition at line 434 of file windows_debug.c.

434  {
435  return b->perm & RZ_PERM_X;
436 }
#define b(i)
Definition: sha256.c:42

References b, and RZ_PERM_X.

Referenced by w32_hwbp_arm_add(), and w32_hwbp_arm_del().

◆ is_process_alive()

static bool is_process_alive ( HANDLE  ph)
static

Definition at line 177 of file windows_debug.c.

177  {
178  if (ph) {
179  DWORD code;
180  if (!GetExitCodeProcess(ph, &code)) {
181  GetExitCodeThread(ph, &code);
182  }
183  return code == STILL_ACTIVE;
184  }
185  return false;
186 }
const char * code
Definition: pal.c:98
Definition: inftree9.h:24

References code, DWORD, and ph.

Referenced by get_thread_context().

◆ is_thread_alive()

static bool is_thread_alive ( RzDebug dbg,
int  tid 
)
static

Definition at line 162 of file windows_debug.c.

162  {
163  PTHREAD_ITEM th = find_thread(dbg, tid);
164  if (!th) {
165  return false;
166  }
167  if (!th->bFinished) {
168  if (SuspendThread(th->hThread) != -1) {
169  ResumeThread(th->hThread);
170  return true;
171  }
172  }
173  th->bFinished = true;
174  return false;
175 }

References THREAD_ITEM::bFinished, dbg, find_thread(), and THREAD_ITEM::hThread.

Referenced by w32_dbg_wait(), w32_hwbp_arm_add(), w32_hwbp_arm_del(), w32_reg_read(), w32_reg_write(), and w32_select().

◆ is_watchpoint()

static bool is_watchpoint ( RzBreakpointItem b)
inlinestatic

Definition at line 430 of file windows_debug.c.

430  {
431  return b->perm & (RZ_PERM_RW | RZ_PERM_R | RZ_PERM_W);
432 }

References b, RZ_PERM_R, RZ_PERM_RW, and RZ_PERM_W.

Referenced by w32_hwbp_arm_add(), and w32_hwbp_arm_del().

◆ last_library()

static void* last_library ( void  )
static

Definition at line 811 of file windows_debug.c.

811  {
812  return rz_list_tail(lib_list) ? rz_list_tail(lib_list)->data : NULL;
813 }

References lib_list, and NULL.

Referenced by w32_info().

◆ libfree()

static void libfree ( void *  lib)
static

Definition at line 758 of file windows_debug.c.

758  {
759  PLIB_ITEM lib_item = (PLIB_ITEM)lib;
760  free(lib_item->Name);
761  free(lib_item->Path);
762  if (lib_item->hFile && lib_item->hFile != INVALID_HANDLE_VALUE) {
763  CloseHandle(lib_item->hFile);
764  }
765  free(lib_item);
766 }

References free(), LIB_ITEM::hFile, INVALID_HANDLE_VALUE, LIB_ITEM::Name, and LIB_ITEM::Path.

Referenced by add_library().

◆ pc_from_context()

static ut64 pc_from_context ( CONTEXT *  ctx)
inlinestatic

Definition at line 1236 of file windows_debug.c.

1236  {
1237 #if __x86_64__
1238  return ctx->Rip;
1239 #elif __arm__ || __arm64__
1240  return ctx->Pc;
1241 #elif __i386__
1242  return ctx->Eip;
1243 #else
1244 #pragma warning("platform not supported")
1245  return 0;
1246 #endif
1247 }

Referenced by w32_thread_list().

◆ print_fpu_context()

static void print_fpu_context ( HANDLE  th,
CONTEXT *  buf 
)
static

Definition at line 391 of file windows_debug.c.

391  {
392  // TODO
393 }

Referenced by w32_reg_read().

◆ remove_library()

static void remove_library ( PLIB_ITEM  library)
static

Definition at line 778 of file windows_debug.c.

778  {
779  rz_list_delete_data(lib_list, library);
780 }
RZ_API bool rz_list_delete_data(RZ_NONNULL RzList *list, void *ptr)
Deletes an entry in the list by searching for a pointer.
Definition: list.c:148

References lib_list, and rz_list_delete_data().

Referenced by w32_dbg_wait().

◆ resolve_path()

static char* resolve_path ( HANDLE  ph,
HANDLE  mh 
)
static

Definition at line 716 of file windows_debug.c.

716  {
717  // TODO: add maximum path length support
718  const DWORD maxlength = MAX_PATH;
719  WCHAR filename[MAX_PATH];
720  DWORD length = GetModuleFileNameExW(ph, mh, filename, maxlength);
721  if (length > 0) {
722  return rz_utf16_to_utf8(filename);
723  }
724  char *name = get_file_name_from_handle(mh);
725  if (name) {
726  return name;
727  }
728  // Upon failure fallback to GetProcessImageFileName
729  length = GetProcessImageFileNameW(mh, filename, maxlength);
730  if (length == 0) {
731  return NULL;
732  }
733  // Convert NT path to win32 path
734  WCHAR *tmp = wcschr(filename + 1, L'\\');
735  if (!tmp) {
736  return NULL;
737  }
738  tmp = wcschr(tmp + 1, L'\\');
739  if (!tmp) {
740  return NULL;
741  }
742  length = tmp - filename;
743  WCHAR device[MAX_PATH];
744  char *ret = NULL;
745  for (WCHAR drv[] = L"A:"; drv[0] <= L'Z'; drv[0]++) {
746  if (QueryDosDeviceW(drv, device, maxlength) > 0) {
747  if (!wcsncmp(filename, device, length)) {
748  WCHAR path[MAX_PATH];
749  _snwprintf(path, maxlength, L"%s%s", drv, tmp);
750  ret = rz_utf16_to_utf8(path);
751  break;
752  }
753  }
754  }
755  return ret;
756 }
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
const char * name
Definition: op.c:541
static char * get_file_name_from_handle(HANDLE handle_file)

References DWORD, get_file_name_from_handle(), L, length, name, NULL, path, ph, and autogen_x86imm::tmp.

Referenced by get_process_path(), w32_dbg_wait(), and w32_info_exe().

◆ resume_thread()

static int resume_thread ( HANDLE  th)
static

Definition at line 147 of file windows_debug.c.

147  {
148  int ret;
149  if ((ret = ResumeThread(th)) == -1) {
150  rz_sys_perror("ResumeThread");
151  }
152  return ret;
153 }

References rz_sys_perror.

Referenced by continue_thread(), w32_dbg_wait(), w32_detach(), w32_hwbp_arm_add(), w32_hwbp_arm_del(), w32_reg_read(), and w32_reg_write().

◆ set_thread_context()

static int set_thread_context ( HANDLE  th,
const ut8 buf,
int  size 
)
static

Definition at line 188 of file windows_debug.c.

188  {
189  bool ret;
190  CONTEXT ctx = { 0 };
191  size = RZ_MIN(size, sizeof(ctx));
192  memcpy(&ctx, buf, size);
193  if (!(ret = SetThreadContext(th, &ctx))) {
194  rz_sys_perror("SetThreadContext");
195  }
196  return ret;
197 }
#define RZ_MIN(x, y)

References memcpy(), RZ_MIN, and rz_sys_perror.

Referenced by w32_hwbp_arm_add(), w32_hwbp_arm_del(), and w32_reg_write().

◆ setup_debug_privileges()

bool setup_debug_privileges ( bool  b)

Definition at line 16 of file windows_debug.c.

16  {
17  HANDLE tok;
18  if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tok)) {
19  return false;
20  }
21  bool ret = false;
22  LUID luid;
23  if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {
24  TOKEN_PRIVILEGES tp;
25  tp.PrivilegeCount = 1;
26  tp.Privileges[0].Luid = luid;
27  tp.Privileges[0].Attributes = b ? SE_PRIVILEGE_ENABLED : 0;
28  if (AdjustTokenPrivileges(tok, FALSE, &tp, 0, NULL, NULL)) {
29  // TODO: handle ERROR_NOT_ALL_ASSIGNED
30  ret = GetLastError() == ERROR_SUCCESS;
31  }
32  }
33  CloseHandle(tok);
34  return ret;
35 }

References b, FALSE, HANDLE, and NULL.

Referenced by w32_init().

◆ suspend_thread()

static int suspend_thread ( HANDLE  th)
inlinestatic

Definition at line 139 of file windows_debug.c.

139  {
140  int ret;
141  if ((ret = SuspendThread(th)) == -1) {
142  rz_sys_perror("SuspendThread");
143  }
144  return ret;
145 }

References rz_sys_perror.

Referenced by w32_dbg_wait(), w32_hwbp_arm_add(), w32_hwbp_arm_del(), w32_reg_read(), w32_reg_write(), and w32_select().

◆ transfer_drx()

static void transfer_drx ( RzDebug dbg,
const ut8 buf 
)
static

Definition at line 387 of file windows_debug.c.

387  {
388  // Do nothing (not supported)
389 }

Referenced by w32_reg_write().

◆ w32_attach()

int w32_attach ( RzDebug dbg,
int  pid 
)

Definition at line 598 of file windows_debug.c.

598  {
599  W32DbgWInst *wrap = dbg->plugin_data;
600  if (already_attached(wrap, pid)) {
601  return wrap->pi.dwThreadId;
602  }
603  if (wrap->pi.hProcess && wrap->pi.hProcess != INVALID_HANDLE_VALUE) {
604  CloseHandle(wrap->pi.hProcess);
605  }
606  dbg->main_pid = pid;
607  wrap->pi.dwProcessId = pid;
608  wrap->params.type = W32_ATTACH;
609  w32dbg_wrap_wait_ret(wrap);
610  if (!wrap->params.ret) {
611  w32dbgw_err(wrap);
612  rz_sys_perror("DebugActiveProcess");
613  wrap->pi.hProcess = NULL;
614  wrap->pi.dwProcessId = 0;
615  return -1;
616  }
617  dbg->cur->wait(dbg, pid);
619  return wrap->pi.dwThreadId;
620 }
RZ_API int rz_debug_continue(RzDebug *dbg)
Definition: debug.c:1332
W32DbgWParams params
Definition: w32dbg_wrap.h:36
w32dbg_wrap_req type
Definition: w32dbg_wrap.h:18
RzDebugReasonType(* wait)(RzDebug *dbg, int pid)
Definition: rz_debug.h:384
struct rz_debug_plugin_t * cur
Definition: rz_debug.h:295
int main_pid
Definition: rz_debug.h:246
@ W32_ATTACH
Definition: w32dbg_wrap.h:10
int w32dbg_wrap_wait_ret(W32DbgWInst *inst)
Definition: w32dbg_wrap.c:71
#define w32dbgw_err(inst)
Definition: w32dbg_wrap.h:46
static bool already_attached(W32DbgWInst *wrap, int pid)

References already_attached(), rz_debug_t::cur, dbg, INVALID_HANDLE_VALUE, rz_debug_t::main_pid, NULL, W32DbgWInst::params, W32DbgWInst::pi, pid, rz_debug_t::plugin_data, W32DbgWParams::ret, rz_debug_continue(), rz_sys_perror, W32DbgWParams::type, W32_ATTACH, w32dbg_wrap_wait_ret(), w32dbgw_err, and rz_debug_plugin_t::wait.

Referenced by w32_attach_new_process().

◆ w32_attach_new_process()

int w32_attach_new_process ( RzDebug dbg,
int  pid 
)

Definition at line 817 of file windows_debug.c.

817  {
818  int tid = -1;
819 
820  if (!w32_detach(dbg, dbg->pid)) {
821  eprintf("Failed to detach from (%d)\n", dbg->pid);
822  return -1;
823  }
824 
825  if ((tid = w32_attach(dbg, pid)) < 0) {
826  eprintf("Failed to attach to (%d)\n", pid);
827  return -1;
828  }
829 
830  dbg->tid = tid;
831  dbg->pid = pid;
832  // Call select to sync the new pid's data
833  rz_debug_select(dbg, pid, tid);
834  return dbg->tid;
835 }
RZ_API bool rz_debug_select(RzDebug *dbg, int pid, int tid)
Definition: debug.c:595
#define eprintf(x, y...)
Definition: rlcc.c:7
int w32_attach(RzDebug *dbg, int pid)
int w32_detach(RzDebug *dbg, int pid)

References dbg, eprintf, rz_debug_t::pid, pid, rz_debug_select(), rz_debug_t::tid, w32_attach(), and w32_detach().

Referenced by w32_select().

◆ w32_break_process()

void w32_break_process ( void *  user)

Definition at line 912 of file windows_debug.c.

912  {
913  RzDebug *dbg = (RzDebug *)user;
914  W32DbgWInst *wrap = dbg->plugin_data;
915  if (dbg->corebind.cfggeti(dbg->corebind.core, "dbg.threads")) {
916  w32_select(dbg, wrap->pi.dwProcessId, -1); // Suspend all threads
917  } else {
918  if (!DebugBreakProcess(wrap->pi.hProcess)) {
919  rz_sys_perror("DebugBreakProcess");
920  eprintf("Could not interrupt program, attempt to press Ctrl-C in the program's console.\n");
921  }
922  }
923 
924  breaked = true;
925 }
void * core
Definition: rz_bind.h:31
RzCoreConfigGetI cfggeti
Definition: rz_bind.h:43
RzCoreBind corebind
Definition: rz_debug.h:314
static bool breaked
int w32_select(RzDebug *dbg, int pid, int tid)

References breaked, rz_core_bind_t::cfggeti, rz_core_bind_t::core, rz_debug_t::corebind, dbg, eprintf, W32DbgWInst::pi, rz_debug_t::plugin_data, rz_sys_perror, and w32_select().

Referenced by w32_dbg_wait().

◆ w32_continue()

int w32_continue ( RzDebug dbg,
int  pid,
int  tid,
int  sig 
)

Definition at line 1144 of file windows_debug.c.

1144  {
1145  if (tid != dbg->tid) {
1146  dbg->tid = w32_select(dbg, pid, tid);
1147  }
1148  // Don't continue with a thread that wasn't requested
1149  if (dbg->tid != tid) {
1150  return -1;
1151  }
1152 
1153  if (breaked) {
1154  breaked = false;
1155  return -1;
1156  }
1157 
1158  PTHREAD_ITEM th = find_thread(dbg, tid);
1159  if (th && th->hThread != INVALID_HANDLE_VALUE && th->bSuspended) {
1160  continue_thread(th->hThread);
1161  th->bSuspended = false;
1162  }
1163 
1164  W32DbgWInst *wrap = dbg->plugin_data;
1165  wrap->params.type = W32_CONTINUE;
1166 
1167  /* Honor the Windows-specific signal that instructs threads to process exceptions */
1168  wrap->params.continue_status = (sig == DBG_EXCEPTION_NOT_HANDLED)
1169  ? DBG_EXCEPTION_NOT_HANDLED
1170  : DBG_EXCEPTION_HANDLED;
1171 
1172  w32dbg_wrap_wait_ret(wrap);
1173  if (!w32dbgw_ret(wrap)) {
1174  w32dbgw_err(wrap);
1175  rz_sys_perror("ContinueDebugEvent");
1176  return -1;
1177  }
1178 
1179  if (th && th->bFinished) {
1181  }
1182 
1183  return tid;
1184 }
DWORD continue_status
Definition: w32dbg_wrap.h:20
@ W32_CONTINUE
Definition: w32dbg_wrap.h:9
#define w32dbgw_ret(inst)
Definition: w32dbg_wrap.h:45
static void continue_thread(HANDLE th)

References THREAD_ITEM::bFinished, breaked, THREAD_ITEM::bSuspended, W32DbgWParams::continue_status, continue_thread(), dbg, find_thread(), THREAD_ITEM::hThread, INVALID_HANDLE_VALUE, W32DbgWInst::params, pid, rz_debug_t::plugin_data, rz_list_delete_data(), rz_sys_perror, rz_debug_t::threads, rz_debug_t::tid, W32DbgWParams::type, W32_CONTINUE, w32_select(), w32dbg_wrap_wait_ret(), w32dbgw_err, and w32dbgw_ret.

Referenced by w32_dbg_wait().

◆ w32_dbg_wait()

int w32_dbg_wait ( RzDebug dbg,
int  pid 
)

Definition at line 927 of file windows_debug.c.

927  {
928  W32DbgWInst *wrap = dbg->plugin_data;
929  DEBUG_EVENT de;
930  int tid, next_event = 0;
931  char *dllname = NULL;
932  int ret = RZ_DEBUG_REASON_UNKNOWN;
933  static int exited_already = 0;
934 
936 
937  /* handle debug events */
938  do {
939  /* do not continue when already exited but still open for examination */
940  if (exited_already == pid) {
941  return RZ_DEBUG_REASON_DEAD;
942  }
943  memset(&de, 0, sizeof(DEBUG_EVENT));
944  do {
945  wrap->params.type = W32_WAIT;
946  wrap->params.wait.de = &de;
947  wrap->params.wait.wait_time = wait_time;
948  void *bed = rz_cons_sleep_begin();
949  w32dbg_wrap_wait_ret(wrap);
950  rz_cons_sleep_end(bed);
951  if (!w32dbgw_ret(wrap)) {
952  if (w32dbgw_err(wrap) != ERROR_SEM_TIMEOUT) {
953  rz_sys_perror("WaitForDebugEvent");
954  ret = -1;
955  goto end;
956  }
957  if (!is_thread_alive(dbg, dbg->tid)) {
958  ret = w32_select(dbg, dbg->pid, dbg->tid);
959  if (ret == -1) {
960  ret = RZ_DEBUG_REASON_DEAD;
961  goto end;
962  }
963  }
964  } else {
965  break;
966  }
967  } while (!breaked);
968 
969  if (breaked) {
971  breaked = false;
972  }
973 
974  dbg->tid = tid = de.dwThreadId;
975  dbg->pid = pid = de.dwProcessId;
976 
977  /* TODO: DEBUG_CONTROL_C */
978  switch (de.dwDebugEventCode) {
979  case CREATE_PROCESS_DEBUG_EVENT:
980  CloseHandle(de.u.CreateProcessInfo.hFile);
981  add_thread(dbg, pid, tid, de.u.CreateProcessInfo.hThread, de.u.CreateProcessInfo.lpThreadLocalBase, de.u.CreateProcessInfo.lpStartAddress, FALSE);
982  wrap->pi.hProcess = de.u.CreateProcessInfo.hProcess;
983  wrap->pi.hThread = de.u.CreateProcessInfo.hThread;
984  wrap->winbase = (ULONG_PTR)de.u.CreateProcessInfo.lpBaseOfImage;
986  next_event = 0;
987  break;
988  case CREATE_THREAD_DEBUG_EVENT:
989  add_thread(dbg, pid, tid, de.u.CreateThread.hThread, de.u.CreateThread.lpThreadLocalBase, de.u.CreateThread.lpStartAddress, FALSE);
990  if (ret != RZ_DEBUG_REASON_USERSUSP) {
992  }
993  dbg->corebind.cmdf(dbg->corebind.core, "f teb.%d @ 0x%p", tid, de.u.CreateThread.lpThreadLocalBase);
994  next_event = 0;
995  break;
996  case EXIT_PROCESS_DEBUG_EVENT:
997  case EXIT_THREAD_DEBUG_EVENT: {
998  PTHREAD_ITEM th = find_thread(dbg, tid);
999  if (th) {
1000  th->bFinished = TRUE;
1001  th->dwExitCode = de.u.ExitThread.dwExitCode;
1002  } else {
1004  }
1005  dbg->corebind.cmdf(dbg->corebind.core, "f- teb.%d", tid);
1006  if (de.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) {
1007  exited_already = pid;
1008  w32_continue(dbg, pid, tid, DBG_CONTINUE);
1010  } else {
1012  }
1013  next_event = 0;
1014  break;
1015  }
1016  case LOAD_DLL_DEBUG_EVENT:
1017  dllname = resolve_path(wrap->pi.hProcess, de.u.LoadDll.hFile);
1018  if (dllname) {
1019  add_library(pid, de.u.LoadDll.lpBaseOfDll, de.u.LoadDll.hFile, dllname);
1020  free(dllname);
1021  }
1023  next_event = 0;
1024  break;
1025  case UNLOAD_DLL_DEBUG_EVENT: {
1026  PLIB_ITEM lib = (PLIB_ITEM)find_library(de.u.UnloadDll.lpBaseOfDll);
1027  if (lib) {
1028  remove_library(lib);
1029  }
1031  next_event = 0;
1032  break;
1033  }
1034  case OUTPUT_DEBUG_STRING_EVENT: {
1035  char *str = calloc(de.u.DebugString.nDebugStringLength, sizeof(WCHAR));
1036  ReadProcessMemory(wrap->pi.hProcess, de.u.DebugString.lpDebugStringData, str, de.u.DebugString.nDebugStringLength, NULL);
1037  char *tmp = de.u.DebugString.fUnicode
1038  ? rz_utf16_to_utf8((wchar_t *)str)
1039  : rz_acp_to_utf8(str);
1040  if (tmp) {
1041  free(str);
1042  str = tmp;
1043  }
1044  eprintf("(%d) Debug string: %s\n", pid, str);
1045  free(str);
1046  w32_continue(dbg, pid, tid, DBG_EXCEPTION_NOT_HANDLED);
1047  next_event = 1;
1048  break;
1049  }
1050  case RIP_EVENT:
1051  eprintf("(%d) RIP event\n", pid);
1052  w32_continue(dbg, pid, tid, -1);
1053  next_event = 1;
1054  // XXX unknown ret = RZ_DEBUG_REASON_TRAP;
1055  break;
1056  case EXCEPTION_DEBUG_EVENT:
1057  dbg->reason.signum = DBG_EXCEPTION_NOT_HANDLED;
1058  switch (de.u.Exception.ExceptionRecord.ExceptionCode) {
1059  case DBG_CONTROL_C:
1060  eprintf("Received CTRL+C, suspending execution\n");
1061  ret = RZ_DEBUG_REASON_SIGNAL;
1062  next_event = 0;
1063  break;
1064 #if _WIN64
1065  case 0x4000001f: /* STATUS_WX86_BREAKPOINT */
1066 #endif
1067  case EXCEPTION_BREAKPOINT:
1069  next_event = 0;
1070  break;
1071 #if _WIN64
1072  case 0x4000001e: /* STATUS_WX86_SINGLE_STEP */
1073 #endif
1074  case EXCEPTION_SINGLE_STEP:
1075  ret = RZ_DEBUG_REASON_STEP;
1076  next_event = 0;
1077  break;
1078  default:
1079  if (rz_bp_get_at(dbg->bp, (size_t)de.u.Exception.ExceptionRecord.ExceptionAddress)) {
1081  next_event = 0;
1082  break;
1083  }
1084  EXCEPTION_DEBUG_INFO *exp = &de.u.Exception;
1085  windows_print_exception_event(de.dwProcessId, de.dwThreadId, exp->ExceptionRecord.ExceptionCode, exp->dwFirstChance);
1086  if (windows_is_exception_fatal(de.u.Exception.ExceptionRecord.ExceptionCode)) {
1087  next_event = 0;
1088  dbg->reason.type = windows_exception_to_reason(de.u.Exception.ExceptionRecord.ExceptionCode);
1089  dbg->reason.tid = de.dwThreadId;
1090  dbg->reason.addr = (size_t)de.u.Exception.ExceptionRecord.ExceptionAddress;
1092  ret = dbg->reason.type;
1093  } else {
1094  w32_continue(dbg, pid, tid, DBG_EXCEPTION_NOT_HANDLED);
1095  next_event = 1;
1096  }
1097  }
1098  break;
1099  default:
1100  // This case might be reached if break doesn't trigger an event
1101  if (ret != RZ_DEBUG_REASON_USERSUSP) {
1102  eprintf("(%d) unknown event: %lu\n", pid, de.dwDebugEventCode);
1103  ret = -1;
1104  }
1105  next_event = 0;
1106  }
1107  } while (next_event);
1108 
1109  if (ret != RZ_DEBUG_REASON_DEAD) {
1110  PTHREAD_ITEM th = find_thread(dbg, tid);
1111  if (th) {
1112  wrap->pi.hThread = th->hThread;
1113  } else {
1115  }
1116  }
1117 #if __arm__ || __arm64__
1118  if (ret != RZ_DEBUG_REASON_EXIT_TID) {
1119  CONTEXT ctx;
1120  suspend_thread(wrap->pi.hThread);
1121  get_thread_context(wrap->pi.hThread, (ut8 *)&ctx, sizeof(ctx), CONTEXT_CONTROL);
1122  resume_thread(wrap->pi.hThread);
1123  if (ctx.Cpsr & 0x20) {
1124  dbg->bits = RZ_SYS_BITS_16;
1125  } else {
1126 #if __arm__
1127  dbg->bits = RZ_SYS_BITS_32;
1128 #else
1129  dbg->bits = RZ_SYS_BITS_64;
1130 #endif
1131  }
1132  }
1133 #endif
1134 end:
1135  if (ret == RZ_DEBUG_REASON_DEAD) {
1136  w32_detach(dbg, dbg->pid);
1139  }
1141  return ret;
1142 }
RZ_API RZ_BORROW RzBreakpointItem * rz_bp_get_at(RZ_NONNULL RzBreakpoint *bp, ut64 addr)
Get the breakpoint at exactly addr.
Definition: bp.c:102
#define EXCEPTION_SINGLE_STEP
Definition: common_windows.c:9
RzDebugReasonType windows_exception_to_reason(ut32 exception_code)
#define EXCEPTION_BREAKPOINT
Definition: common_windows.c:8
void windows_print_exception_event(ut32 pid, ut32 tid, ut32 exception_code, bool second_chance)
bool windows_is_exception_fatal(ut32 exception_code)
RZ_API void * rz_cons_sleep_begin(void)
Definition: cons.c:443
RZ_API void rz_cons_break_pop(void)
Definition: cons.c:361
RZ_API void rz_cons_break_push(RzConsBreak cb, void *user)
Definition: cons.c:357
RZ_API void rz_cons_sleep_end(void *user)
Definition: cons.c:450
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
RZ_API void rz_list_purge(RZ_NONNULL RzList *list)
Empties the list without freeing the list pointer.
Definition: list.c:120
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
#define TRUE
Definition: mybfd.h:103
#define rz_warn_if_reached()
Definition: rz_assert.h:29
@ RZ_DEBUG_REASON_NEW_TID
Definition: rz_debug.h:106
@ RZ_DEBUG_REASON_DEAD
Definition: rz_debug.h:90
@ RZ_DEBUG_REASON_STEP
Definition: rz_debug.h:98
@ RZ_DEBUG_REASON_UNKNOWN
Definition: rz_debug.h:103
@ RZ_DEBUG_REASON_BREAKPOINT
Definition: rz_debug.h:94
@ RZ_DEBUG_REASON_USERSUSP
Definition: rz_debug.h:115
@ RZ_DEBUG_REASON_NEW_LIB
Definition: rz_debug.h:107
@ RZ_DEBUG_REASON_EXIT_LIB
Definition: rz_debug.h:110
@ RZ_DEBUG_REASON_NEW_PID
Definition: rz_debug.h:105
@ RZ_DEBUG_REASON_EXIT_PID
Definition: rz_debug.h:108
@ RZ_DEBUG_REASON_EXIT_TID
Definition: rz_debug.h:109
@ RZ_DEBUG_REASON_SIGNAL
Definition: rz_debug.h:92
@ RZ_SYS_BITS_32
Definition: rz_sys.h:20
@ RZ_SYS_BITS_64
Definition: rz_sys.h:21
@ RZ_SYS_BITS_16
Definition: rz_sys.h:19
RZ_API ut64 rz_time_now(void)
Returns the current time in microseconds.
Definition: time.c:88
int size_t
Definition: sftypes.h:40
DWORD dwExitCode
ULONG_PTR winbase
Definition: w32dbg_wrap.h:39
struct W32DbgWParams::@606::@608 wait
RzCoreCmdF cmdf
Definition: rz_bind.h:33
RzDebugReason reason
Definition: rz_debug.h:276
int bits
Definition: rz_debug.h:243
RzBreakpoint * bp
Definition: rz_debug.h:288
@ W32_WAIT
Definition: w32dbg_wrap.h:12
static void add_library(DWORD pid, LPVOID lpBaseOfDll, HANDLE hFile, char *dllname)
const DWORD wait_time
Definition: windows_debug.c:11
void w32_break_process(void *user)
static void remove_library(PLIB_ITEM library)
static int get_thread_context(HANDLE th, ut8 *buf, int size, DWORD context_flags)
static PTHREAD_ITEM add_thread(RzDebug *dbg, DWORD pid, DWORD tid, HANDLE hThread, LPVOID lpThreadLocalBase, LPVOID lpStartAddress, BOOL bFinished)
static bool is_thread_alive(RzDebug *dbg, int tid)
int w32_continue(RzDebug *dbg, int pid, int tid, int sig)
static int suspend_thread(HANDLE th)
static void * find_library(void *BaseOfDll)

References add_library(), add_thread(), rz_debug_reason_t::addr, THREAD_ITEM::bFinished, rz_debug_t::bits, rz_debug_t::bp, breaked, calloc(), rz_core_bind_t::cmdf, rz_core_bind_t::core, rz_debug_t::corebind, dbg, THREAD_ITEM::dwExitCode, test_evm::end, eprintf, EXCEPTION_BREAKPOINT, EXCEPTION_SINGLE_STEP, FALSE, find_library(), find_thread(), free(), get_thread_context(), THREAD_ITEM::hThread, is_thread_alive(), lib_list, rz_debug_t::main_pid, memset(), NULL, W32DbgWInst::params, W32DbgWInst::pi, rz_debug_t::pid, pid, rz_debug_t::plugin_data, rz_debug_t::reason, remove_library(), resolve_path(), resume_thread(), rz_bp_get_at(), rz_cons_break_pop(), rz_cons_break_push(), rz_cons_sleep_begin(), rz_cons_sleep_end(), RZ_DEBUG_REASON_BREAKPOINT, RZ_DEBUG_REASON_DEAD, RZ_DEBUG_REASON_EXIT_LIB, RZ_DEBUG_REASON_EXIT_PID, RZ_DEBUG_REASON_EXIT_TID, RZ_DEBUG_REASON_NEW_LIB, RZ_DEBUG_REASON_NEW_PID, RZ_DEBUG_REASON_NEW_TID, RZ_DEBUG_REASON_SIGNAL, RZ_DEBUG_REASON_STEP, RZ_DEBUG_REASON_UNKNOWN, RZ_DEBUG_REASON_USERSUSP, rz_list_purge(), RZ_SYS_BITS_16, RZ_SYS_BITS_32, RZ_SYS_BITS_64, rz_sys_perror, rz_time_now(), rz_warn_if_reached, rz_debug_reason_t::signum, cmd_descs_generate::str, suspend_thread(), rz_debug_t::threads, rz_debug_reason_t::tid, rz_debug_t::tid, rz_debug_reason_t::timestamp, autogen_x86imm::tmp, TRUE, rz_debug_reason_t::type, W32DbgWParams::type, w32_break_process(), w32_continue(), w32_detach(), w32_select(), W32_WAIT, w32dbg_wrap_wait_ret(), w32dbgw_err, w32dbgw_ret, W32DbgWParams::wait, wait_time, W32DbgWInst::winbase, windows_exception_to_reason(), windows_is_exception_fatal(), and windows_print_exception_event().

◆ w32_desc_list()

RzList* w32_desc_list ( int  pid)

Definition at line 1471 of file windows_debug.c.

1471  {
1472  HANDLE ph;
1473  if (!(ph = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid))) {
1474  return NULL;
1475  }
1476  ULONG handleInfoSize = 0x10000;
1477  POBJECT_TYPE_INFORMATION objectTypeInfo = malloc(0x1000);
1478  if (!objectTypeInfo) {
1479  CloseHandle(ph);
1480  return NULL;
1481  }
1482  RzDebugDesc *desc;
1483  NTSTATUS status;
1484  PSYSTEM_HANDLE_INFORMATION handleInfo = NULL;
1485  PVOID objectNameInfo = NULL;
1487  if (!ret) {
1488  goto beach;
1489  }
1490  handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize);
1491  while ((status = w32_NtQuerySystemInformation(SystemHandleInformation, handleInfo, handleInfoSize, NULL)) == STATUS_INFO_LENGTH_MISMATCH) {
1492  handleInfoSize *= 2;
1493  void *tmp = realloc(handleInfo, (size_t)handleInfoSize);
1494  if (tmp) {
1495  handleInfo = (PSYSTEM_HANDLE_INFORMATION)tmp;
1496  } else {
1497  goto beach;
1498  }
1499  }
1500  if (status) {
1501  rz_sys_perror("NtQuerySystemInformation");
1502  goto beach;
1503  }
1504  size_t objectNameInfo_sz = 0x1000;
1505  objectNameInfo = malloc(objectNameInfo_sz);
1506  if (!objectNameInfo) {
1507  goto beach;
1508  }
1509  int i;
1510  for (i = 0; i < handleInfo->HandleCount; i++) {
1511  SYSTEM_HANDLE handle = handleInfo->Handles[i];
1512  HANDLE dupHandle = NULL;
1513  ULONG returnLength;
1514  int perms = 0;
1515  if (handle.ProcessId != pid) {
1516  continue;
1517  }
1518  if (w32_NtDuplicateObject(ph, (HANDLE)(size_t)handle.Handle, GetCurrentProcess(), &dupHandle, 0, 0, 0)) {
1519  continue;
1520  }
1521  if (w32_NtQueryObject(dupHandle, 2, objectTypeInfo, 0x1000, NULL)) {
1522  CloseHandle(dupHandle);
1523  continue;
1524  }
1525  if (wcscmp(objectTypeInfo->Name.Buffer, L"File")) {
1526  CloseHandle(dupHandle);
1527  continue;
1528  }
1529  GENERIC_MAPPING *gm = &objectTypeInfo->GenericMapping;
1530  if ((handle.GrantedAccess & gm->GenericRead) == gm->GenericRead) {
1531  perms |= RZ_PERM_R;
1532  }
1533  if ((handle.GrantedAccess & gm->GenericWrite) == gm->GenericWrite) {
1534  perms |= RZ_PERM_W;
1535  }
1536  if ((handle.GrantedAccess & gm->GenericExecute) == gm->GenericExecute) {
1537  perms |= RZ_PERM_X;
1538  }
1539  if (w32_NtQueryObject(dupHandle, 1, objectNameInfo, objectNameInfo_sz, &returnLength)) {
1540  void *tmp = realloc(objectNameInfo, returnLength);
1541  if (tmp) {
1542  objectNameInfo = tmp;
1543  objectNameInfo_sz = returnLength;
1544  }
1545  if (w32_NtQueryObject(dupHandle, 1, objectNameInfo, objectNameInfo_sz, NULL)) {
1546  CloseHandle(dupHandle);
1547  continue;
1548  }
1549  }
1550  PUNICODE_STRING objectName = objectNameInfo;
1551  if (objectName->Length) {
1552  char *name = rz_utf16_to_utf8_l(objectName->Buffer, objectName->Length / 2);
1553  desc = rz_debug_desc_new(handle.Handle, name, perms, '?', 0);
1554  if (!desc) {
1555  free(name);
1556  break;
1557  }
1558  rz_list_append(ret, desc);
1559  free(name);
1560  } else {
1561  char *name = rz_utf16_to_utf8_l(objectTypeInfo->Name.Buffer, objectTypeInfo->Name.Length / 2);
1562  desc = rz_debug_desc_new(handle.Handle, name, perms, '?', 0);
1563  if (!desc) {
1564  free(name);
1565  break;
1566  }
1567  rz_list_append(ret, desc);
1568  free(name);
1569  }
1570  CloseHandle(dupHandle);
1571  }
1572 beach:
1573  free(objectNameInfo);
1574  free(objectTypeInfo);
1575  free(handleInfo);
1576  CloseHandle(ph);
1577  return ret;
1578 }
lzma_index ** i
Definition: index.h:629
static mcore_handle handle
Definition: asm_mcore.c:8
const char * desc
Definition: bin_vsf.c:19
RZ_API RzDebugDesc * rz_debug_desc_new(int fd, char *path, int perm, int type, int off)
Definition: ddesc.c:8
RZ_API void rz_debug_desc_free(RzDebugDesc *p)
Definition: ddesc.c:20
void * realloc(void *ptr, size_t size)
Definition: malloc.c:144
static const char struct stat static buf struct stat static buf static vhangup int status
Definition: sflib.h:145
GENERIC_MAPPING GenericMapping
Definition: windows_debug.h:86
SYSTEM_HANDLE Handles[1]
Definition: windows_debug.h:57
USHORT Length
Definition: winapi.h:4116
PWSTR Buffer
Definition: winapi.h:4118
LONG NTSTATUS
Definition: win.h:198
#define STATUS_INFO_LENGTH_MISMATCH
Definition: winapi.h:692
#define SystemHandleInformation
Definition: windows_debug.c:14
struct _SYSTEM_HANDLE_INFORMATION * PSYSTEM_HANDLE_INFORMATION
ULONG
PVOID

References _UNICODE_STRING::Buffer, desc, FALSE, free(), _OBJECT_TYPE_INFORMATION::GenericMapping, handle, HANDLE, _SYSTEM_HANDLE_INFORMATION::HandleCount, _SYSTEM_HANDLE_INFORMATION::Handles, i, L, _UNICODE_STRING::Length, malloc(), _OBJECT_TYPE_INFORMATION::Name, NULL, ph, pid, PVOID, realloc(), rz_debug_desc_free(), rz_debug_desc_new(), rz_list_append(), rz_list_newf(), RZ_PERM_R, RZ_PERM_W, RZ_PERM_X, rz_sys_perror, status, STATUS_INFO_LENGTH_MISMATCH, SystemHandleInformation, autogen_x86imm::tmp, and ULONG.

◆ w32_detach()

int w32_detach ( RzDebug dbg,
int  pid 
)

Definition at line 622 of file windows_debug.c.

622  {
623  if (pid == -1 || dbg->pid != pid) {
624  return false;
625  }
626 
627  // Resume suspended threads
628  RzListIter *it;
629  PTHREAD_ITEM th;
630  rz_list_foreach (dbg->threads, it, th) {
631  if (th->bSuspended && !th->bFinished) {
632  resume_thread(th->hThread);
633  }
634  }
636  if (lib_list) {
638  }
639  W32DbgWInst *wrap = dbg->plugin_data;
640  bool ret = false;
641  wrap->pi.dwProcessId = pid;
642  wrap->params.type = W32_DETACH;
643  w32dbg_wrap_wait_ret(wrap);
644  ret = wrap->params.ret;
645  memset(&wrap->pi, 0, sizeof(wrap->pi));
646  return ret;
647 }
@ W32_DETACH
Definition: w32dbg_wrap.h:11

References THREAD_ITEM::bFinished, THREAD_ITEM::bSuspended, dbg, THREAD_ITEM::hThread, lib_list, memset(), W32DbgWInst::params, W32DbgWInst::pi, rz_debug_t::pid, pid, rz_debug_t::plugin_data, resume_thread(), W32DbgWParams::ret, rz_list_purge(), rz_debug_t::threads, W32DbgWParams::type, W32_DETACH, and w32dbg_wrap_wait_ret().

Referenced by w32_attach_new_process(), and w32_dbg_wait().

◆ w32_findthread_cmp()

static int w32_findthread_cmp ( int tid,
PTHREAD_ITEM  th 
)
static

Definition at line 95 of file windows_debug.c.

95  {
96  return (int)!(*tid == th->tid);
97 }

References THREAD_ITEM::tid.

Referenced by find_thread().

◆ w32_hwbp_arm_add()

int w32_hwbp_arm_add ( RzDebug dbg,
RzBreakpoint bp,
RzBreakpointItem b 
)

Definition at line 438 of file windows_debug.c.

438  {
439  rz_return_val_if_fail(dbg && bp && b, 0);
440  W32DbgWInst *wrap = dbg->plugin_data;
441  CONTEXT ctx;
442  const bool alive = is_thread_alive(dbg, wrap->pi.dwThreadId);
443  if (alive && suspend_thread(wrap->pi.hThread) == -1) {
444  return 0;
445  }
446  get_thread_context(wrap->pi.hThread, (ut8 *)&ctx, sizeof(CONTEXT), CONTEXT_DEBUG_REGISTERS);
447  ut32 control;
448  ut64 value;
449  int i;
450  if (is_watchpoint(b)) {
451  get_arm64_hwwp_values(b->addr, b->size, b->perm, &control, &value);
452  for (i = 0; i < ARM64_MAX_WATCHPOINTS; i++) {
453  if (!ctx.Wvr[i] || ctx.Wvr[i] == value) {
454  break;
455  }
456  }
457  if (i < ARM64_MAX_WATCHPOINTS) {
458  ctx.Wcr[i] = control;
459  ctx.Wvr[i] = value;
460  } else {
461  eprintf("Too many hardware watchpoints\n");
462  }
463  }
464  if (is_breakpoint(b)) {
465  get_arm_hwbp_values(b->addr, &control, &value);
466  for (i = 0; i < ARM64_MAX_BREAKPOINTS; i++) {
467  if (!ctx.Bvr[i] || ctx.Bvr[i] == value) {
468  break;
469  }
470  }
471  if (i < ARM64_MAX_BREAKPOINTS) {
472  ctx.Bcr[i] = control;
473  ctx.Bvr[i] = value;
474  } else {
475  eprintf("Too many hardware breakpoints\n");
476  }
477  }
478  set_thread_context(wrap->pi.hThread, (ut8 *)&ctx, sizeof(CONTEXT));
479  if (alive && resume_thread(wrap->pi.hThread) == -1) {
480  return 0;
481  }
482  return 1;
483 }
#define ARM64_MAX_WATCHPOINTS
Definition: mdmp_windefs.h:17
#define ARM64_MAX_BREAKPOINTS
Definition: mdmp_windefs.h:16
static bool is_breakpoint(RzBreakpointItem *b)
static int set_thread_context(HANDLE th, const ut8 *buf, int size)
static bool is_watchpoint(RzBreakpointItem *b)
static void get_arm_hwbp_values(ut64 address, ut32 *control, ut64 *value)
static void get_arm64_hwwp_values(ut64 address, int size, int rw, ut32 *control, ut64 *value)
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References ARM64_MAX_BREAKPOINTS, ARM64_MAX_WATCHPOINTS, b, control, dbg, eprintf, get_arm64_hwwp_values(), get_arm_hwbp_values(), get_thread_context(), i, is_breakpoint(), is_thread_alive(), is_watchpoint(), W32DbgWInst::pi, rz_debug_t::plugin_data, resume_thread(), rz_return_val_if_fail, set_thread_context(), suspend_thread(), ut64(), and value.

◆ w32_hwbp_arm_del()

int w32_hwbp_arm_del ( RzDebug dbg,
RzBreakpoint bp,
RzBreakpointItem b 
)

Definition at line 485 of file windows_debug.c.

485  {
486  W32DbgWInst *wrap = dbg->plugin_data;
487  CONTEXT ctx;
488  const bool alive = is_thread_alive(dbg, wrap->pi.dwThreadId);
489  if (alive && suspend_thread(wrap->pi.hThread) == -1) {
490  return 0;
491  }
492  get_thread_context(wrap->pi.hThread, (ut8 *)&ctx, sizeof(CONTEXT), CONTEXT_DEBUG_REGISTERS);
493  ut32 control;
494  ut64 value;
495  int i;
496  if (is_watchpoint(b)) {
497  get_arm64_hwwp_values(b->addr, b->size, b->perm, &control, &value);
498  for (i = 0; i < ARM64_MAX_WATCHPOINTS; i++) {
499  if (ctx.Wcr[i] == control && ctx.Wvr[i] == value) {
500  break;
501  }
502  }
503  if (i < ARM64_MAX_WATCHPOINTS) {
504  ctx.Wcr[i] = 0;
505  ctx.Wvr[i] = 0;
506  }
507  }
508  if (is_breakpoint(b)) {
509  get_arm_hwbp_values(b->addr, &control, &value);
510  for (i = 0; i < ARM64_MAX_BREAKPOINTS; i++) {
511  if (ctx.Bvr[i] == value) {
512  break;
513  }
514  }
515  if (i < ARM64_MAX_BREAKPOINTS) {
516  ctx.Bcr[i] = 0;
517  ctx.Bvr[i] = 0;
518  }
519  }
520  set_thread_context(wrap->pi.hThread, (ut8 *)&ctx, sizeof(CONTEXT));
521  if (alive && resume_thread(wrap->pi.hThread, dbg->bits) == -1) {
522  return 0;
523  }
524  return 1;
525 }

References ARM64_MAX_BREAKPOINTS, ARM64_MAX_WATCHPOINTS, b, rz_debug_t::bits, control, dbg, get_arm64_hwwp_values(), get_arm_hwbp_values(), get_thread_context(), i, is_breakpoint(), is_thread_alive(), is_watchpoint(), W32DbgWInst::pi, rz_debug_t::plugin_data, resume_thread(), set_thread_context(), suspend_thread(), ut64(), and value.

◆ w32_info()

RzDebugInfo* w32_info ( RzDebug dbg,
const char *  arg 
)

Definition at line 1404 of file windows_debug.c.

1404  {
1406  if (!rdi) {
1407  return NULL;
1408  }
1409  rdi->status = RZ_DBG_PROC_SLEEP; // TODO: Fix this
1410  rdi->pid = dbg->pid;
1411  rdi->tid = dbg->tid;
1412  rdi->lib = last_library();
1413  rdi->thread = find_thread(dbg, dbg->tid);
1414  rdi->uid = -1;
1415  rdi->gid = -1;
1416  rdi->cwd = NULL;
1417  rdi->exe = NULL;
1418  rdi->cmdline = NULL;
1419  rdi->libname = NULL;
1420  w32_info_user(dbg, rdi);
1421  w32_info_exe(dbg, rdi);
1422  return rdi;
1423 }
@ RZ_DBG_PROC_SLEEP
Definition: rz_debug.h:62
static void w32_info_exe(RzDebug *dbg, RzDebugInfo *rdi)
static void * last_library(void)
static void w32_info_user(RzDebug *dbg, RzDebugInfo *rdi)

References dbg, find_thread(), last_library(), NULL, rz_debug_t::pid, rdi, RZ_DBG_PROC_SLEEP, RZ_NEW0, rz_debug_t::tid, w32_info_exe(), and w32_info_user().

◆ w32_info_exe()

static void w32_info_exe ( RzDebug dbg,
RzDebugInfo rdi 
)
static

Definition at line 1396 of file windows_debug.c.

1396  {
1397  W32DbgWInst *wrap = dbg->plugin_data;
1398  if (!wrap) {
1399  return;
1400  }
1401  rdi->exe = resolve_path(wrap->pi.hProcess, NULL);
1402 }

References dbg, NULL, W32DbgWInst::pi, rz_debug_t::plugin_data, rdi, and resolve_path().

Referenced by w32_info().

◆ w32_info_user()

static void w32_info_user ( RzDebug dbg,
RzDebugInfo rdi 
)
static

Definition at line 1339 of file windows_debug.c.

1339  {
1340  HANDLE h_tok = NULL;
1341  DWORD tok_len = 0;
1342  PTOKEN_USER tok_usr = NULL;
1343  LPWSTR usr = NULL, usr_dom = NULL;
1344  DWORD usr_len = 512;
1345  DWORD usr_dom_len = 512;
1346  SID_NAME_USE snu = { 0 };
1347  W32DbgWInst *wrap = dbg->plugin_data;
1348 
1349  if (!wrap || !wrap->pi.hProcess) {
1350  return;
1351  }
1352  if (!OpenProcessToken(wrap->pi.hProcess, TOKEN_QUERY, &h_tok)) {
1353  rz_sys_perror("OpenProcessToken");
1354  goto err_w32_info_user;
1355  }
1356  if (!GetTokenInformation(h_tok, TokenUser, (LPVOID)&tok_usr, 0, &tok_len) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
1357  rz_sys_perror("GetTokenInformation");
1358  goto err_w32_info_user;
1359  }
1360  tok_usr = (PTOKEN_USER)malloc(tok_len);
1361  if (!tok_usr) {
1362  goto err_w32_info_user;
1363  }
1364  if (!GetTokenInformation(h_tok, TokenUser, (LPVOID)tok_usr, tok_len, &tok_len)) {
1365  rz_sys_perror("GetTokenInformation");
1366  goto err_w32_info_user;
1367  }
1368  usr = (LPWSTR)malloc(usr_len * sizeof(WCHAR));
1369  if (!usr) {
1370  goto err_w32_info_user;
1371  }
1372  *usr = '\0';
1373  usr_dom = (LPWSTR)malloc(usr_dom_len * sizeof(WCHAR));
1374  if (!usr_dom) {
1375  goto err_w32_info_user;
1376  }
1377  *usr_dom = '\0';
1378  if (!LookupAccountSidW(NULL, tok_usr->User.Sid, usr, &usr_len, usr_dom, &usr_dom_len, &snu)) {
1379  rz_sys_perror("LookupAccountSid");
1380  goto err_w32_info_user;
1381  }
1382  if (*usr_dom) {
1383  rdi->usr = rz_str_newf("%S\\%S", usr_dom, usr);
1384  } else {
1385  rdi->usr = rz_utf16_to_utf8(usr);
1386  }
1387 err_w32_info_user:
1388  if (h_tok) {
1389  CloseHandle(h_tok);
1390  }
1391  free(usr);
1392  free(usr_dom);
1393  free(tok_usr);
1394 }
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1

References dbg, DWORD, free(), HANDLE, LPWSTR, malloc(), NULL, W32DbgWInst::pi, rz_debug_t::plugin_data, rdi, rz_str_newf(), and rz_sys_perror.

Referenced by w32_info().

◆ w32_init()

int w32_init ( RzDebug dbg)

Definition at line 37 of file windows_debug.c.

37  {
38  if (!dbg->plugin_data) {
39  dbg->plugin_data = dbg->iob.get_w32dbg_wrap(dbg->iob.io);
40  if (!dbg->plugin_data) {
41  return 0;
42  }
43  }
44  // escalate privs (required for win7/vista)
46 
47  HMODULE lib = GetModuleHandleW(L"kernel32"); // Always loaded
48  if (!lib) {
49  return false;
50  }
51  // lookup function pointers for portability
52  // only windows vista :(
53  w32_ProcessIdToSessionId = (BOOL(WINAPI *)(DWORD, DWORD *))
54  GetProcAddress(lib, "ProcessIdToSessionId");
55 
56  w32_QueryFullProcessImageNameW = (BOOL(WINAPI *)(HANDLE, DWORD, LPWSTR, PDWORD))
57  GetProcAddress(lib, "QueryFullProcessImageNameW");
58 
59  // api to retrieve YMM from w7 sp1
60  w32_GetEnabledXStateFeatures = (ut64(WINAPI *)())
61  GetProcAddress(lib, "GetEnabledXStateFeatures");
62 
63  w32_InitializeContext = (BOOL(WINAPI *)(PVOID, DWORD, PCONTEXT *, PDWORD))
64  GetProcAddress(lib, "InitializeContext");
65 
66  w32_GetXStateFeaturesMask = (BOOL(WINAPI *)(PCONTEXT Context, PDWORD64))
67  GetProcAddress(lib, "GetXStateFeaturesMask");
68 
69  w32_LocateXStateFeature = (PVOID(WINAPI *)(PCONTEXT Context, DWORD, PDWORD))
70  GetProcAddress(lib, "LocateXStateFeature");
71 
72  w32_SetXStateFeaturesMask = (BOOL(WINAPI *)(PCONTEXT Context, DWORD64))
73  GetProcAddress(lib, "SetXStateFeaturesMask");
74 
75  lib = GetModuleHandleW(L"ntdll.dll");
76  if (!lib) {
77  eprintf("Cannot load ntdll.dll. Aborting\n");
78  return false;
79  }
80  w32_NtQuerySystemInformation = (NTSTATUS(WINAPI *)(ULONG, PVOID, ULONG, PULONG))
81  GetProcAddress(lib, "NtQuerySystemInformation");
82 
83  w32_NtDuplicateObject = (NTSTATUS(WINAPI *)(HANDLE, HANDLE, HANDLE, PHANDLE, ACCESS_MASK, ULONG, ULONG))
84  GetProcAddress(lib, "NtDuplicateObject");
85 
86  w32_NtQueryObject = (NTSTATUS(WINAPI *)(HANDLE, ULONG, PVOID, ULONG, PULONG))
87  GetProcAddress(lib, "NtQueryObject");
88 
89  w32_NtQueryInformationThread = (NTSTATUS(WINAPI *)(HANDLE, ULONG, PVOID, ULONG, PULONG))
90  GetProcAddress(lib, "NtQueryInformationThread");
91 
92  return true;
93 }
struct dwarf_parse_context_t Context
RzIOBind iob
Definition: rz_debug.h:293
RzIO * io
Definition: rz_io.h:232
bool setup_debug_privileges(bool b)
Definition: windows_debug.c:16
ACCESS_MASK
DWORD PDWORD
PHANDLE
PCONTEXT PDWORD64
PCONTEXT DWORD64
PULONG

References ACCESS_MASK, dbg, DWORD, DWORD64, eprintf, HANDLE, rz_io_bind_t::io, rz_debug_t::iob, L, LPWSTR, PDWORD, PDWORD64, PHANDLE, rz_debug_t::plugin_data, PULONG, PVOID, setup_debug_privileges(), ULONG, and ut64().

◆ w32_kill()

int w32_kill ( RzDebug dbg,
int  pid,
int  tid,
int  sig 
)

Definition at line 890 of file windows_debug.c.

890  {
891  W32DbgWInst *wrap = dbg->plugin_data;
892 
893  if (sig == 0) {
894  if (rz_list_empty(dbg->threads)) {
895  if (lib_list) {
897  }
898  return false;
899  }
900  return true;
901  }
902 
903  bool ret = false;
904  if (TerminateProcess(wrap->pi.hProcess, 1)) {
905  ret = true;
906  }
907  wrap->pi.hProcess = NULL;
908  wrap->pi.hThread = NULL;
909  return ret;
910 }

References dbg, lib_list, NULL, W32DbgWInst::pi, rz_debug_t::plugin_data, rz_list_purge(), and rz_debug_t::threads.

◆ w32_map_alloc()

RzDebugMap* w32_map_alloc ( RzDebug dbg,
ut64  addr,
int  size 
)

Definition at line 1186 of file windows_debug.c.

1186  {
1187  W32DbgWInst *wrap = dbg->plugin_data;
1188  LPVOID base = VirtualAllocEx(wrap->pi.hProcess, (LPVOID)addr, (SIZE_T)size, MEM_COMMIT, PAGE_READWRITE);
1189  if (!base) {
1190  rz_sys_perror("VirtualAllocEx");
1191  return NULL;
1192  }
1194  return rz_debug_map_get(dbg, (ut64)base);
1195 }
RZ_API RzDebugMap * rz_debug_map_get(RzDebug *dbg, ut64 addr)
Definition: dmap.c:65
RZ_API bool rz_debug_map_sync(RzDebug *dbg)
Definition: dmap.c:33
static int addr
Definition: z80asm.c:58

References addr, dbg, NULL, W32DbgWInst::pi, rz_debug_t::plugin_data, rz_debug_map_get(), rz_debug_map_sync(), rz_sys_perror, and ut64().

◆ w32_map_dealloc()

int w32_map_dealloc ( RzDebug dbg,
ut64  addr,
int  size 
)

Definition at line 1197 of file windows_debug.c.

1197  {
1198  W32DbgWInst *wrap = dbg->plugin_data;
1199  if (!VirtualFreeEx(wrap->pi.hProcess, (LPVOID)addr, 0, MEM_RELEASE)) {
1200  rz_sys_perror("VirtualFreeEx");
1201  return false;
1202  }
1203  return true;
1204 }

References addr, dbg, W32DbgWInst::pi, rz_debug_t::plugin_data, and rz_sys_perror.

◆ w32_map_protect()

int w32_map_protect ( RzDebug dbg,
ut64  addr,
int  size,
int  perms 
)

Definition at line 1229 of file windows_debug.c.

1229  {
1230  DWORD old;
1231  W32DbgWInst *wrap = dbg->plugin_data;
1232  return VirtualProtectEx(wrap->pi.hProcess, (LPVOID)(size_t)addr,
1233  size, io_perms_to_prot(perms), &old);
1234 }
static int io_perms_to_prot(int io_perms)

References addr, dbg, DWORD, io_perms_to_prot(), W32DbgWInst::pi, and rz_debug_t::plugin_data.

◆ w32_pid_list()

RzList* w32_pid_list ( RzDebug dbg,
int  pid,
RzList list 
)

Definition at line 1443 of file windows_debug.c.

1443  {
1444  W32DbgWInst *wrap = dbg->plugin_data;
1445  HANDLE sh = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, pid);
1446  if (sh == INVALID_HANDLE_VALUE) {
1447  rz_sys_perror("CreateToolhelp32Snapshot");
1448  return list;
1449  }
1450  PROCESSENTRY32W pe;
1451  pe.dwSize = sizeof(pe);
1452  if (Process32FirstW(sh, &pe)) {
1453  bool all = pid == 0;
1454  do {
1455  if (all || pe.th32ProcessID == pid || pe.th32ParentProcessID == pid) {
1456  // Returns NULL if process is inaccessible unless if its a child process of debugged process
1457  RzDebugPid *dbg_pid = build_debug_pid(pe.th32ProcessID, pe.th32ParentProcessID,
1458  dbg->pid == pe.th32ProcessID ? wrap->pi.hProcess : NULL, pe.szExeFile);
1459  if (dbg_pid) {
1460  rz_list_append(list, dbg_pid);
1461  }
1462  }
1463  } while (Process32NextW(sh, &pe));
1464  } else {
1465  rz_sys_perror("Process32First");
1466  }
1467  CloseHandle(sh);
1468  return list;
1469 }
static void list(RzEgg *egg)
Definition: rz-gg.c:52
static RzDebugPid * build_debug_pid(int pid, int ppid, HANDLE ph, const WCHAR *name)

References test_group_name::all, build_debug_pid(), dbg, HANDLE, INVALID_HANDLE_VALUE, list(), NULL, W32DbgWInst::pi, rz_debug_t::pid, pid, rz_debug_t::plugin_data, rz_list_append(), and rz_sys_perror.

◆ w32_reg_read()

int w32_reg_read ( RzDebug dbg,
int  type,
ut8 buf,
int  size 
)

Definition at line 544 of file windows_debug.c.

544  {
545  bool showfpu = false;
546  if (type < -1) {
547  showfpu = true; // hack for debugging
548  type = -type;
549  }
550  bool alive = is_thread_alive(dbg, dbg->tid);
552  if (!th || th == INVALID_HANDLE_VALUE) {
553  return 0;
554  }
555  // Always suspend
556  if (alive && suspend_thread(th) == -1) {
557  return 0;
558  }
560  if (showfpu) {
561  print_fpu_context(th, (CONTEXT *)buf);
562  }
563  // Always resume
564  if (alive && resume_thread(th) == -1) {
565  size = 0;
566  }
567  return size;
568 }
static HANDLE get_thread_handle_from_tid(RzDebug *dbg, int tid)
static void print_fpu_context(HANDLE th, CONTEXT *buf)
#define CONTEXT_ALL
Definition: windows_debug.h:43

References CONTEXT_ALL, dbg, get_thread_context(), get_thread_handle_from_tid(), HANDLE, INVALID_HANDLE_VALUE, is_thread_alive(), print_fpu_context(), resume_thread(), suspend_thread(), rz_debug_t::tid, and type.

Referenced by w32_thread_list().

◆ w32_reg_write()

int w32_reg_write ( RzDebug dbg,
int  type,
const ut8 buf,
int  size 
)

Definition at line 570 of file windows_debug.c.

570  {
571  bool alive = is_thread_alive(dbg, dbg->tid);
572  if (!alive) {
573  return false;
574  }
576  if (!th || th == INVALID_HANDLE_VALUE) {
577  return 0;
578  }
579  // Always suspend
580  if (suspend_thread(th) == -1) {
581  return false;
582  }
583  if (type == RZ_REG_TYPE_DRX) {
584  transfer_drx(dbg, buf);
585  }
586  bool ret = set_thread_context(th, buf, size);
587  // Always resume
588  if (resume_thread(th) == -1) {
589  ret = false;
590  }
591  return ret;
592 }
@ RZ_REG_TYPE_DRX
Definition: rz_reg.h:22
static void transfer_drx(RzDebug *dbg, const ut8 *buf)

References dbg, get_thread_handle_from_tid(), HANDLE, INVALID_HANDLE_VALUE, is_thread_alive(), resume_thread(), RZ_REG_TYPE_DRX, set_thread_context(), suspend_thread(), rz_debug_t::tid, transfer_drx(), and type.

◆ w32_select()

int w32_select ( RzDebug dbg,
int  pid,
int  tid 
)

Definition at line 837 of file windows_debug.c.

837  {
838  RzListIter *it;
839  W32DbgWInst *wrap = dbg->plugin_data;
840 
841  // Re-attach to a different pid
842  if (dbg->pid > -1 && dbg->pid != pid) {
843  return w32_attach_new_process(dbg, pid);
844  }
845 
846  if (dbg->tid == -1) {
847  return tid;
848  }
849 
850  if (!dbg->threads) {
852  return tid;
853  }
854 
855  if (rz_list_empty(dbg->threads)) {
856  return tid;
857  }
858 
859  PTHREAD_ITEM th = find_thread(dbg, tid);
860 
861  int selected = 0;
862  if (th && is_thread_alive(dbg, th->tid)) {
863  wrap->pi.hThread = th->hThread;
864  selected = tid;
865  } else if (tid) {
866  // If thread is dead, search for another one
867  rz_list_foreach (dbg->threads, it, th) {
868  if (!is_thread_alive(dbg, th->tid)) {
869  continue;
870  }
871  wrap->pi.hThread = th->hThread;
872  selected = th->tid;
873  break;
874  }
875  }
876 
877  if (dbg->corebind.cfggeti(dbg->corebind.core, "dbg.threads")) {
878  // Suspend all other threads
879  rz_list_foreach (dbg->threads, it, th) {
880  if (!th->bFinished && !th->bSuspended && th->tid != selected) {
881  suspend_thread(th->hThread);
882  th->bSuspended = true;
883  }
884  }
885  }
886 
887  return selected;
888 }
int w32_attach_new_process(RzDebug *dbg, int pid)

References THREAD_ITEM::bFinished, THREAD_ITEM::bSuspended, rz_core_bind_t::cfggeti, rz_core_bind_t::core, rz_debug_t::corebind, dbg, find_thread(), free(), THREAD_ITEM::hThread, is_thread_alive(), W32DbgWInst::pi, rz_debug_t::pid, pid, rz_debug_t::plugin_data, rz_list_newf(), suspend_thread(), rz_debug_t::threads, THREAD_ITEM::tid, rz_debug_t::tid, and w32_attach_new_process().

Referenced by w32_break_process(), w32_continue(), and w32_dbg_wait().

◆ w32_step()

int w32_step ( RzDebug dbg)

Definition at line 395 of file windows_debug.c.

395  {
396  // Do nothing (not supported)
397  return 0;
398 }

◆ w32_thread_list()

RzList* w32_thread_list ( RzDebug dbg,
int  pid,
RzList list 
)

Definition at line 1280 of file windows_debug.c.

1280  {
1281  // pid is not respected for TH32CS_SNAPTHREAD flag
1282  HANDLE th = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
1283  if (th == INVALID_HANDLE_VALUE) {
1284  rz_sys_perror("CreateToolhelp32Snapshot");
1285  return list;
1286  }
1287  THREADENTRY32 te;
1288  te.dwSize = sizeof(te);
1289  HANDLE ph = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
1290  if (Thread32First(th, &te)) {
1291  // TODO: export this code to its own function?
1292  char *path = NULL;
1293  int uid = -1;
1294  if (!te.th32ThreadID) {
1296  DWORD sid;
1297  if (w32_ProcessIdToSessionId && w32_ProcessIdToSessionId(pid, &sid)) {
1298  uid = sid;
1299  }
1300  }
1301  if (!path) {
1302  // TODO: enum processes to get binary's name
1303  path = strdup("???");
1304  }
1305  int saved_tid = dbg->tid;
1306  do {
1307  char status = RZ_DBG_PROC_SLEEP;
1308  if (te.th32OwnerProcessID == pid) {
1309  ut64 pc = 0;
1310  if (dbg->pid == pid) {
1311  CONTEXT ctx = { 0 };
1312  dbg->tid = te.th32ThreadID;
1313  w32_reg_read(dbg, RZ_REG_TYPE_GPR, (ut8 *)&ctx, sizeof(ctx));
1314  // TODO: is needed check context for x32 and x64??
1315  pc = pc_from_context(&ctx);
1316  PTHREAD_ITEM pthread = find_thread(dbg, te.th32ThreadID);
1317  if (pthread) {
1318  if (pthread->bFinished) {
1320  } else if (pthread->bSuspended) {
1322  } else {
1323  status = RZ_DBG_PROC_RUN; // TODO: Get more precise thread status
1324  }
1325  }
1326  }
1327  rz_list_append(list, rz_debug_pid_new(path, te.th32ThreadID, uid, status, pc));
1328  }
1329  } while (Thread32Next(th, &te));
1330  dbg->tid = saved_tid;
1331  free(path);
1332  } else {
1333  rz_sys_perror("Thread32First");
1334  }
1335  CloseHandle(th);
1336  return list;
1337 }
@ RZ_DBG_PROC_RUN
Definition: rz_debug.h:61
@ RZ_DBG_PROC_DEAD
Definition: rz_debug.h:64
@ RZ_REG_TYPE_GPR
Definition: rz_reg.h:21
static ut64 pc_from_context(CONTEXT *ctx)
int w32_reg_read(RzDebug *dbg, int type, ut8 *buf, int size)

References THREAD_ITEM::bFinished, THREAD_ITEM::bSuspended, dbg, DWORD, FALSE, find_thread(), free(), get_process_path(), HANDLE, INVALID_HANDLE_VALUE, list(), NULL, path, pc, pc_from_context(), ph, rz_debug_t::pid, pid, RZ_DBG_PROC_DEAD, RZ_DBG_PROC_RUN, RZ_DBG_PROC_SLEEP, rz_debug_pid_new(), rz_list_append(), RZ_REG_TYPE_GPR, rz_sys_perror, status, strdup(), rz_debug_t::tid, ut64(), and w32_reg_read().

Variable Documentation

◆ breaked

◆ lib_list

RzList* lib_list = NULL
static

◆ wait_time

const DWORD wait_time = 1000

Definition at line 11 of file windows_debug.c.

Referenced by w32_dbg_wait().