Rizin
unix-like reverse engineering framework and cli tools
io_w32dbg.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2008-2016 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_types.h>
5 
6 #if __WINDOWS__
7 #include <rz_windows.h>
8 #include <rz_core.h>
9 #include <w32dbg_wrap.h>
10 
11 static ut64 __find_next_valid_addr(HANDLE h, ut64 from, ut64 to) {
12  // Align to next page and try to get to next valid addr
13  const int page_size = 0x1000;
14  from = ((from + page_size) / page_size) * page_size;
15  ut8 buf;
16  while (from < to && !ReadProcessMemory(h, (void *)from, &buf, 1, NULL)) {
17  from += page_size;
18  }
19  return from < to ? from : UT64_MAX;
20 }
21 
22 static int debug_os_read_at(W32DbgWInst *dbg, ut8 *buf, int len, ut64 addr) {
23  SIZE_T ret = 0;
24  if (!ReadProcessMemory(dbg->pi.hProcess, (void *)(size_t)addr, buf, len, &ret) && GetLastError() == ERROR_PARTIAL_COPY) {
25  int skipped = 0;
26  if (!ReadProcessMemory(dbg->pi.hProcess, (void *)(size_t)addr, buf, 1, &ret)) {
27  // We are starting a read from invalid memory
28  ut64 valid_addr = __find_next_valid_addr(dbg->pi.hProcess, addr, addr + len);
29  if (valid_addr == UT64_MAX) {
30  return len;
31  }
32  skipped = valid_addr - addr;
33  memset(buf, '\xff', skipped);
34  addr = valid_addr;
35  buf += skipped;
36  }
37  // We are in a valid page now, try to read again
38  int read_len = len - skipped;
39  int totRead = skipped;
40  while (totRead < len) {
41  while (!ReadProcessMemory(dbg->pi.hProcess, (void *)(size_t)addr, buf, read_len, &ret)) {
42  // Maybe read_len is too big, we are reaching invalid memory
43  read_len /= 2;
44  if (!read_len) {
45  // Reached the end of valid memory, find another to continue reading if possible
46  ut64 valid_addr = __find_next_valid_addr(dbg->pi.hProcess, addr, addr + len - totRead);
47  if (valid_addr == UT64_MAX) {
48  return len;
49  }
50  skipped = valid_addr - addr;
51  addr = valid_addr;
52  memset(buf, '\xff', skipped);
53  buf += skipped;
54  totRead += skipped;
55  read_len = len - totRead;
56  }
57  }
58  buf += ret;
59  addr += ret;
60  totRead += ret;
61  read_len = RZ_MIN(read_len, len - totRead);
62  }
63  }
64  return len;
65 }
66 
67 static int __read(RzIO *io, RzIODesc *fd, ut8 *buf, int len) {
68  return debug_os_read_at(fd->data, buf, len, io->off);
69 }
70 
71 static int w32dbg_write_at(W32DbgWInst *dbg, const ut8 *buf, int len, ut64 addr) {
72  SIZE_T ret;
73  return 0 != WriteProcessMemory(dbg->pi.hProcess, (void *)(size_t)addr, buf, len, &ret) ? len : 0;
74 }
75 
76 static int __write(RzIO *io, RzIODesc *fd, const ut8 *buf, int len) {
77  return w32dbg_write_at(fd->data, buf, len, io->off);
78 }
79 
80 static bool __plugin_open(RzIO *io, const char *file, bool many) {
81  if (!strncmp(file, "attach://", 9)) {
82  return true;
83  }
84  return !strncmp(file, "w32dbg://", 9);
85 }
86 
87 static inline bool current_handle_valid(W32DbgWInst *wrap, int pid) {
88  return wrap->pi.dwProcessId == pid && wrap->pi.hProcess != INVALID_HANDLE_VALUE;
89 }
90 
91 static int __open_proc(RzIO *io, int pid, bool attach) {
92  W32DbgWInst *wrap = (W32DbgWInst *)rz_io_get_w32dbg_wrap(io);
93  if (!wrap) {
94  return -1;
95  }
96  if (current_handle_valid(wrap, pid)) {
97  if (!attach) {
98  return pid;
99  }
100  // We will get a new handle when we attach
101  CloseHandle(wrap->pi.hProcess);
102  }
103 
104  if (attach) {
105  RzCore *core = io->corebind.core;
106  core->dbg->plugin_data = wrap;
107  /* Attach to the process */
108  return core->dbg->cur->attach(core->dbg, pid);
109  }
110 
111  HANDLE h_proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
112  if (!h_proc) {
113  rz_sys_perror("OpenProcess");
114  return -1;
115  }
116  wrap->pi.dwProcessId = pid;
117  wrap->pi.hProcess = h_proc;
118  return pid;
119 }
120 
121 static RzIODesc *__open(RzIO *io, const char *file, int rw, int mode) {
122  if (__plugin_open(io, file, 0)) {
123  RzIODesc *ret;
124  W32DbgWInst *wrap = (W32DbgWInst *)rz_io_get_w32dbg_wrap(io);
125  if (!wrap) {
126  return NULL;
127  }
128  if (__open_proc(io, atoi(file + 9), !strncmp(file, "attach://", 9)) == -1) {
129  return NULL;
130  }
132  file, rw | RZ_PERM_X, mode, wrap);
133  ret->name = rz_sys_pid_to_path(wrap->pi.dwProcessId);
134  return ret;
135  }
136  return NULL;
137 }
138 
139 static ut64 __lseek(RzIO *io, RzIODesc *fd, ut64 offset, int whence) {
140  switch (whence) {
141  case RZ_IO_SEEK_SET:
142  io->off = offset;
143  break;
144  case RZ_IO_SEEK_CUR:
145  io->off += (st64)offset;
146  break;
147  case RZ_IO_SEEK_END:
148  io->off = UT64_MAX;
149  break;
150  }
151  return io->off;
152 }
153 
154 static int __close(RzIODesc *fd) {
155  if (rz_str_startswith(fd->uri, "attach://")) {
156  W32DbgWInst *wrap = fd->data;
157  wrap->params.type = W32_DETACH;
158  w32dbg_wrap_wait_ret(wrap);
159  }
160  return false;
161 }
162 
163 static char *__system(RzIO *io, RzIODesc *fd, const char *cmd) {
164  W32DbgWInst *wrap = fd->data;
165  if (!strcmp(cmd, "")) {
166  // do nothing
167  } else if (!strncmp(cmd, "pid", 3)) {
168  return rz_str_newf("%lu", wrap->pi.dwProcessId);
169  } else {
170  eprintf("Try: 'R!pid'\n");
171  }
172  return NULL;
173 }
174 
175 static int __getpid(RzIODesc *fd) {
176  W32DbgWInst *wrap = (W32DbgWInst *)(fd ? fd->data : NULL);
177  if (!wrap) {
178  return -1;
179  }
180  return wrap->pi.dwProcessId;
181 }
182 
183 static int __gettid(RzIODesc *fd) {
184  W32DbgWInst *wrap = (W32DbgWInst *)(fd ? fd->data : NULL);
185  return wrap ? wrap->pi.dwThreadId : -1;
186 }
187 
188 static bool __getbase(RzIODesc *fd, ut64 *base) {
189  W32DbgWInst *wrap = (W32DbgWInst *)(fd ? fd->data : NULL);
190  if (base && wrap) {
191  *base = wrap->winbase;
192  return true;
193  }
194  return false;
195 }
196 
198  .name = "w32dbg",
199  .desc = "w32 debugger io plugin",
200  .license = "LGPL3",
201  .uris = "w32dbg://,attach://",
202  .open = __open,
203  .close = __close,
204  .read = __read,
205  .check = __plugin_open,
206  .lseek = __lseek,
207  .system = __system,
208  .write = __write,
209  .getpid = __getpid,
210  .gettid = __gettid,
211  .getbase = __getbase,
212  .isdbg = true
213 };
214 #else
216  .name = NULL
217 };
218 #endif
219 
220 #ifndef RZ_PLUGIN_INCORE
222  .type = RZ_LIB_TYPE_IO,
223  .data = &rz_io_plugin_w32dbg,
225 };
226 #endif
size_t len
Definition: 6502dis.c:15
#define RZ_API
#define NULL
Definition: cris-opc.c:27
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 cmd
Definition: sflib.h:79
RzDebug * dbg
Definition: desil.c:30
static int __read(RzIO *io, RzIODesc *fd, ut8 *buf, int count)
Definition: io_bfdbg.c:84
static bool __plugin_open(RzIO *io, const char *pathname, bool many)
Definition: io_bfdbg.c:151
static RzIODesc * __open(RzIO *io, const char *pathname, int rw, int mode)
Definition: io_bfdbg.c:159
static int __write(RzIO *io, RzIODesc *fd, const ut8 *buf, int count)
Definition: io_bfdbg.c:38
static ut64 __lseek(RzIO *io, RzIODesc *fd, ut64 offset, int whence)
Definition: io_bfdbg.c:142
static int __close(RzIODesc *fd)
Definition: io_bfdbg.c:130
static char * __system(RzIO *io, RzIODesc *fd, const char *cmd)
Definition: io_bochs.c:90
static int __gettid(RzIODesc *fd)
Definition: io_gdb.c:196
static int __getpid(RzIODesc *fd)
Definition: io_gdb.c:177
RzIOPlugin rz_io_plugin_w32dbg
Definition: io_w32dbg.c:215
RZ_API RzLibStruct rizin_plugin
Definition: io_w32dbg.c:221
voidpf uLong offset
Definition: ioapi.h:144
const char int mode
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
#define INVALID_HANDLE_VALUE
Definition: iowin32.c:21
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
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
#define FALSE
Definition: mybfd.h:102
#define eprintf(x, y...)
Definition: rlcc.c:7
#define RZ_IO_SEEK_CUR
Definition: rz_io.h:16
RZ_API RzIODesc * rz_io_desc_new(RzIO *io, RzIOPlugin *plugin, const char *uri, int flags, int mode, void *data)
Definition: io_desc.c:11
#define RZ_IO_SEEK_SET
Definition: rz_io.h:15
#define RZ_IO_SEEK_END
Definition: rz_io.h:17
@ RZ_LIB_TYPE_IO
Definition: rz_lib.h:69
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API bool rz_str_startswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string starts with a specifc sequence of characters (case sensitive)
Definition: str.c:3286
RZ_API char * rz_sys_pid_to_path(int pid)
Definition: sys.c:920
#define rz_sys_perror(x)
Definition: rz_types.h:336
#define RZ_PERM_X
Definition: rz_types.h:95
#define RZ_MIN(x, y)
#define st64
Definition: rz_types_base.h:10
#define UT64_MAX
Definition: rz_types_base.h:86
#define RZ_VERSION
Definition: rz_version.h:8
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr from
Definition: sfsocketcall.h:123
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr socklen_t static fromlen const void const struct sockaddr to
Definition: sfsocketcall.h:125
#define h(i)
Definition: sha256.c:48
W32DbgWParams params
Definition: w32dbg_wrap.h:36
PROCESS_INFORMATION pi
Definition: w32dbg_wrap.h:40
ULONG_PTR winbase
Definition: w32dbg_wrap.h:39
w32dbg_wrap_req type
Definition: w32dbg_wrap.h:18
Definition: gzappend.c:170
void * core
Definition: rz_bind.h:31
RzDebug * dbg
Definition: rz_core.h:329
int(* attach)(RzDebug *dbg, int pid)
Definition: rz_debug.h:372
struct rz_debug_plugin_t * cur
Definition: rz_debug.h:295
void * plugin_data
Definition: rz_debug.h:296
char * name
Definition: rz_io.h:99
const char * name
Definition: rz_io.h:115
const char * version
Definition: rz_io.h:117
Definition: rz_io.h:59
RzCoreBind corebind
Definition: rz_io.h:92
ut64 off
Definition: rz_io.h:61
@ W32_DETACH
Definition: w32dbg_wrap.h:11
int w32dbg_wrap_wait_ret(W32DbgWInst *inst)
Definition: w32dbg_wrap.c:71
DWORD * HANDLE
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static const z80_opcode fd[]
Definition: z80_tab.h:997
static int addr
Definition: z80asm.c:58