Rizin
unix-like reverse engineering framework and cli tools
io_winedbg.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2017-2019 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_io.h>
5 #include <rz_lib.h>
6 #include <rz_socket.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <sys/types.h>
10 
11 static RzSocket *gs = NULL;
12 
13 RZ_PACKED(struct winedbg_x86_32 {
14  ut16 cs;
15  ut16 ss;
16  ut16 ds;
17  ut16 es;
18  ut16 fs;
19  ut16 gs;
20  ut32 eip;
21  ut32 esp;
22  ut32 ebp;
23  ut32 eflags;
24  ut32 eax;
25  ut32 ebx;
26  ut32 ecx;
27  ut32 edx;
28  ut32 esi;
29  ut32 edi;
30 });
31 
32 // TODO: make it vargarg...
33 static char *runcmd(const char *cmd) {
34  char buf[4096] = { 0 };
35  if (cmd) {
36  rz_socket_printf(gs, "%s\n", cmd);
37  }
38  int timeout = 1000000;
39  char *str = NULL;
41  while (true) {
42  memset(buf, 0, sizeof(buf));
43  int rc = rz_socket_read(gs, (ut8 *)buf, sizeof(buf) - 1); // NULL-terminate the string always
44  if (rc == -1) {
45  break;
46  }
47  char *promptFound = strstr(buf, "Wine-dbg>");
48  if (promptFound) {
49  *promptFound = 0;
50  return rz_str_append(str, buf);
51  }
53  }
54  free(str);
55  return NULL;
56 }
57 
58 static int __write(RzIO *io, RzIODesc *fd, const ut8 *buf, int count) {
59  if (!fd || !fd->data) {
60  return -1;
61  }
62  int wordSize = 4;
63  ut32 *w = (ut32 *)buf;
64  int i;
65  int words = count / wordSize; // XXX must pad align to 4
66  for (i = 0; i < words; i++) {
67  ut64 addr = io->off + (i * wordSize);
68  char *cmd = rz_str_newf("set *0x%" PFMT64x " = 0x%x", addr, w[i]);
69  free(runcmd(cmd));
70  free(cmd);
71  }
72 
73  int left = count % wordSize;
74  if (left > 0) {
75  ut32 leftW = -1;
76  memcpy(&leftW, w + words, left);
77  ut64 addr = io->off + (words * wordSize);
78  char *cmd = rz_str_newf("set *0x%" PFMT64x " = 0x%x", addr, leftW);
79  free(runcmd(cmd));
80  free(cmd);
81  }
82  return count;
83 }
84 
85 static int __read(RzIO *io, RzIODesc *fd, ut8 *buf, int count) {
86  if (!fd || !fd->data) {
87  return -1;
88  }
89  if (count > (1024 * 128)) {
90  // cannot read that much
91  return -1;
92  }
93 #if 0
94 // TODO: use x/${count}b for performance and solve alignment issues
95 Wine-dbg>x/128b 0x7b444730
96 0x7b444730 _start_process+0x10a: cc 83 ec 08 57 56 e8 b5 fe ff ff 83 c4 04 50 e8
97 0x7b444740 _start_process+0x11a: 24 2f 01 00 83 c4 0c 8b 44 24 68 83 ec 08 ff 70
98 0x7b444750 _start_process+0x12a: 5c 6a fe e8 27 2f 01 00 83 c4 08 e8 34 de 01 00
99 0x7b444760 _debugstr_w: 55 89 e5 83 ec 08 83 ec 08 6a ff 51 e8 45 e0 01
100 0x7b444770 _debugstr_w+0x10: 00 83 c4 18 5d c3 55 89 e5 53 57 56 83 e4 f0 81
101 0x7b444780 ___wine_kernel_init+0xa: ec e0 0e 00 00 e8 00 00 00 00 5e 64 a1 18 00 00
102 0x7b444790 ___wine_kernel_init+0x1a: 00 89 44 24 40 8b 40 30 89 44 24 44 8b 78 10 8b
103 0x7b4447a0 ___wine_kernel_init+0x2a: 86 ca 48 1b 00 83 ec 08 31 db 53 ff 30 e8 e4 de
104 Wine-dbg>
105 #endif
106  int wordSize = 4;
107  ut32 *w = (ut32 *)buf;
108  int i;
109  memset(buf, 0xff, count);
110  int words = count / wordSize; // XXX must pad align to 4
111  for (i = 0; i < words; i++) {
112  ut64 addr = io->off + (i * wordSize);
113  char *cmd = rz_str_newf("x 0x%" PFMT64x, addr);
114  char *res = runcmd(cmd);
115  if (res) {
116  sscanf(res, "%x", &w[i]);
117  free(res);
118  }
119  free(cmd);
120  }
121 
122  int left = count % wordSize;
123  if (left > 0) {
124  ut32 n = 0xff;
125  ut8 *wn = (ut8 *)&n;
126  ut64 addr = io->off + (i * wordSize);
127  char *cmd = rz_str_newf("x 0x%" PFMT64x, addr);
128  char *res = runcmd(cmd);
129  sscanf(res, "%x", &n);
130  free(res);
131  free(cmd);
132  memcpy(buf + (words * wordSize), wn, left);
133  }
134  return count;
135 }
136 
137 static int __close(RzIODesc *fd) {
138  if (!fd || !fd->data) {
139  return -1;
140  }
141  // XXX
142  rz_sys_cmdf("pkill rz-run");
143  return 0;
144 }
145 
146 static ut64 __lseek(RzIO *io, RzIODesc *fd, ut64 offset, int whence) {
147  switch (whence) {
148  case RZ_IO_SEEK_SET:
149  io->off = offset;
150  break;
151  case RZ_IO_SEEK_CUR:
152  io->off += offset;
153  break;
154  case RZ_IO_SEEK_END:
155  io->off = ST64_MAX;
156  }
157  io->off = offset;
158  return offset;
159 }
160 
161 static bool __plugin_open(RzIO *io, const char *pathname, bool many) {
162  return (!strncmp(pathname, "winedbg://", 10));
163 }
164 
165 static RzIODesc *__open(RzIO *io, const char *pathname, int rw, int mode) {
166  if (__plugin_open(io, pathname, 0)) {
167  if (gs) {
168  return NULL;
169  }
170  gs = rz_socket_new(0);
171  char *cmd = rz_str_newf("winedbg '%s'", pathname + 10);
172  int res = rz_socket_spawn(gs, cmd, 1000);
173  free(cmd);
174  if (!res) {
175  return NULL;
176  }
177  char *reply = runcmd(NULL);
178  if (reply) {
179  int rw = 7;
180  free(reply);
181  eprintf("Wine-dbg is ready to go!\n");
182  return rz_io_desc_new(io, &rz_io_plugin_winedbg, pathname, rw, mode, gs);
183  }
184  eprintf("Can't find the Wine-dbg prompt\n");
185  }
186  return NULL;
187 }
188 
189 static void printcmd(RzIO *io, const char *cmd) {
190  char *res = runcmd(cmd);
191  io->cb_printf("%s\n", res);
192  free(res);
193 }
194 
195 static struct winedbg_x86_32 regState(void) {
196  struct winedbg_x86_32 r = { 0 };
197  char *res = runcmd("info reg");
198  if (res) {
199  char *line = strstr(res, "EIP:");
200  if (line) {
201  ut32 eip, esp, ebp, eflags;
202  (void)sscanf(line, "EIP:%08x ESP:%08x EBP:%08x EFLAGS:%08x",
203  &eip, &esp, &ebp, &eflags);
204  r.eip = eip;
205  r.esp = esp;
206  r.ebp = ebp;
207  r.eflags = eflags;
208  line = strstr(line, "EAX:");
209  if (line) {
210  ut32 eax, ebx, ecx, edx;
211  (void)sscanf(line, "EAX:%08x EBX:%08x ECX:%08x EDX:%08x",
212  &eax, &ebx, &ecx, &edx);
213  r.eax = eax;
214  r.ebx = ebx;
215  r.ecx = ecx;
216  r.edx = edx;
217  line = strstr(line, "ESI:");
218  if (line) {
219  ut32 esi, edi;
220  (void)sscanf(line, "ESI:%08x EDI:%08x", &esi, &edi);
221  r.esi = esi;
222  r.edi = edi;
223  }
224  }
225  }
226  free(res);
227  }
228  return r;
229 }
230 
231 static char *__system(RzIO *io, RzIODesc *fd, const char *cmd) {
232  if (!strcmp(cmd, "")) {
233  return NULL;
234  }
235  if (!strncmp(cmd, "?", 1)) {
236  eprintf("dr : show registers\n");
237  eprintf("dr* : show registers as flags\n");
238  eprintf("drp : show reg profile\n");
239  eprintf("dr8 : show hexpairs with regstate\n");
240  eprintf("ds : step into\n");
241  eprintf("dp : show process info\n");
242  eprintf("dc : continue\n");
243  eprintf("dm : show maps\n");
244  eprintf("pid : show current process id\n");
245  } else if (!strncmp(cmd, "dr8", 3)) {
246  struct winedbg_x86_32 r = regState();
247  struct winedbg_x86_32 *arena = RZ_NEWS0(struct winedbg_x86_32, 3);
248  if (arena) {
249  rz_hex_bin2str((ut8 *)&r, sizeof(r), (char *)arena);
250  return (char *)arena;
251  }
252  } else if (!strncmp(cmd, "drp", 3)) {
253  const char *msg =
254  "=PC eip\n"
255  "=SP esp\n"
256  "=BP ebp\n"
257  "=A0 eax\n"
258  "=A1 ebx\n"
259  "=A2 ecx\n"
260  "=A3 edx\n"
261  "=A4 esi\n"
262  "=A5 edi\n"
263  "=SN eax\n"
264 
265  "seg cs .16 0 0\n"
266  "seg ss .16 2 0\n"
267  "seg ds .16 4 0\n"
268  "seg es .16 6 0\n"
269  "seg fs .16 8 0\n"
270  "seg gs .16 10 0\n"
271 
272  "gpr eip .32 12 0\n"
273  "gpr esp .32 16 0\n"
274  "gpr ebp .32 20 0\n"
275  "gpr eflags .32 24 0\n"
276 
277  "gpr eax .32 28 0\n"
278  "gpr ebx .32 32 0\n"
279  "gpr ecx .32 36 0\n"
280  "gpr edx .32 40 0\n"
281  "gpr esi .32 44 0\n"
282  "gpr edi .32 48 0\n"
283 
284  "flg flags .16 24 0\n"
285  "flg cf .1 .192 0\n"
286  "flg pf .1 .193 0\n"
287  "flg af .1 .194 0\n"
288  "flg zf .1 .195 0\n"
289  "flg sf .1 .196 0\n"
290  "flg tf .1 .197 0\n"
291  "flg if .1 .198 0\n"
292  "flg df .1 .199 0\n"
293  "flg of .1 .200 0\n"
294  "flg nt .1 .201 0\n"
295  "flg rf .1 .202 0\n"
296  "flg vm .1 .203 0\n";
297  return strdup(msg);
298  } else if (!strncmp(cmd, "dr*", 3)) {
299  struct winedbg_x86_32 r = regState();
300  io->cb_printf("f eip @ 0x%08x\n", r.eip);
301  io->cb_printf("f esp @ 0x%08x\n", r.esp);
302  io->cb_printf("f ebp @ 0x%08x\n", r.ebp);
303  io->cb_printf("f eax @ 0x%08x\n", r.eax);
304  io->cb_printf("f ebx @ 0x%08x\n", r.ebx);
305  io->cb_printf("f ecx @ 0x%08x\n", r.ecx);
306  io->cb_printf("f edx @ 0x%08x\n", r.edx);
307  io->cb_printf("f esi @ 0x%08x\n", r.esi);
308  io->cb_printf("f edi @ 0x%08x\n", r.edi);
309  io->cb_printf("f eflags @ 0x%08x\n", r.eflags);
310  io->cb_printf("f cs @ 0x%08x\n", r.cs);
311  io->cb_printf("f ss @ 0x%08x\n", r.ss);
312  io->cb_printf("f ds @ 0x%08x\n", r.ds);
313  io->cb_printf("f es @ 0x%08x\n", r.es);
314  io->cb_printf("f fs @ 0x%08x\n", r.fs);
315  io->cb_printf("f gs @ 0x%08x\n", r.gs);
316  } else if (!strncmp(cmd, "dr", 2)) {
317  printcmd(io, "info reg");
318  } else if (!strncmp(cmd, "db ", 3)) {
319  free(runcmd(sdb_fmt("break *%x", rz_num_get(NULL, cmd + 3) || io->off)));
320  } else if (!strncmp(cmd, "ds", 2)) {
321  free(runcmd("stepi"));
322  } else if (!strncmp(cmd, "dc", 2)) {
323  free(runcmd("cont"));
324  } else if (!strncmp(cmd, "dso", 3)) {
325  eprintf("TODO: dso\n");
326  } else if (!strncmp(cmd, "dp", 3)) {
327  printcmd(io, "info thread");
328  } else if (!strncmp(cmd, "dm", 3)) {
329  char *wineDbgMaps = runcmd("info maps");
330  char *res = NULL;
331  if (wineDbgMaps) {
332  const char *perm;
333  char *ptr = wineDbgMaps;
334  for (;;) {
335  char *nl = strchr(ptr, '\n');
336  if (!nl) {
337  break;
338  }
339  *nl++ = 0;
340  perm = "r-x";
341  ut64 from = 0, to = 0;
342  if (strstr(ptr, " commit ")) {
343  if (strstr(ptr, "RW")) {
344  perm = "rw-";
345  }
346  sscanf(ptr, "%08" PFMT64x " %08" PFMT64x, &from, &to);
347  }
348  char *row = rz_str_newf("0x%08" PFMT64x " - 0x%08" PFMT64x " %s %s\n", from, to, perm, "");
349  ptr = nl;
350  if (row) {
351  res = rz_str_append(res, row);
352  free(row);
353  }
354  }
355  free(wineDbgMaps);
356  return res;
357  }
358  } else if (!strncmp(cmd, "pid", 3)) {
359  return rz_str_newf("%d", fd->fd);
360  } else {
361  printcmd(io, cmd);
362  }
363  return NULL;
364 }
365 
367  .name = "winedbg",
368  .desc = "Wine-dbg io and debug.io plugin",
369  .uris = "winedbg://",
370  .license = "MIT",
371  .open = __open,
372  .close = __close,
373  .read = __read,
374  .check = __plugin_open,
375  .lseek = __lseek,
376  .write = __write,
377  .system = __system,
378  .isdbg = true
379 };
380 
381 #ifndef RZ_PLUGIN_INCORE
383  .type = RZ_LIB_TYPE_IO,
384  .data = &rz_io_plugin_winedbg,
386 };
387 #endif
esi
#define e(frag)
lzma_index ** i
Definition: index.h:629
lsl lsr asr ror lsl lsr asr ror lsl lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror c3
lsl lsr asr ror lsl lsr asr ror lsl lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror c4
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
#define w
Definition: crypto_rc6.c:13
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 count
Definition: sflib.h:98
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
uint16_t ut16
uint32_t ut32
RzDebug * dbg
Definition: desil.c:30
RZ_API char * sdb_fmt(const char *fmt,...)
Definition: fmt.c:26
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
static void printcmd(RzIO *io, const char *cmd)
Definition: io_winedbg.c:189
static int __read(RzIO *io, RzIODesc *fd, ut8 *buf, int count)
Definition: io_winedbg.c:85
static char * runcmd(const char *cmd)
Definition: io_winedbg.c:33
static bool __plugin_open(RzIO *io, const char *pathname, bool many)
Definition: io_winedbg.c:161
static RzIODesc * __open(RzIO *io, const char *pathname, int rw, int mode)
Definition: io_winedbg.c:165
RZ_API RzLibStruct rizin_plugin
Definition: io_winedbg.c:382
RZ_PACKED(struct winedbg_x86_32 { ut16 cs;ut16 ss;ut16 ds;ut16 es;ut16 fs;ut16 gs;ut32 eip;ut32 esp;ut32 ebp;ut32 eflags;ut32 eax;ut32 ebx;ut32 ecx;ut32 edx;ut32 esi;ut32 edi;})
static int __write(RzIO *io, RzIODesc *fd, const ut8 *buf, int count)
Definition: io_winedbg.c:58
static RzSocket * gs
Definition: io_winedbg.c:11
static ut64 __lseek(RzIO *io, RzIODesc *fd, ut64 offset, int whence)
Definition: io_winedbg.c:146
static int __close(RzIODesc *fd)
Definition: io_winedbg.c:137
RzIOPlugin rz_io_plugin_winedbg
Definition: io_winedbg.c:366
static char * __system(RzIO *io, RzIODesc *fd, const char *cmd)
Definition: io_winedbg.c:231
static struct winedbg_x86_32 regState(void)
Definition: io_winedbg.c:195
voidpf uLong offset
Definition: ioapi.h:144
const char int mode
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
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 static sig const char pathname
Definition: sflib.h:66
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")
int x
Definition: mipsasm.c:20
int n
Definition: mipsasm.c:19
line
Definition: setup.py:34
#define eprintf(x, y...)
Definition: rlcc.c:7
RZ_API int rz_hex_bin2str(const ut8 *in, int len, char *out)
Definition: hex.c:382
#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 ut64 rz_num_get(RzNum *num, const char *str)
Definition: unum.c:172
RZ_API bool rz_socket_spawn(RzSocket *s, const char *cmd, unsigned int timeout)
Definition: socket.c:208
RZ_API bool rz_socket_block_time(RzSocket *s, bool block, int sec, int usec)
Definition: socket.c:649
RZ_API void RZ_API int rz_socket_read(RzSocket *s, ut8 *read, int len)
Definition: socket.c:783
RZ_API void rz_socket_printf(RzSocket *s, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API RzSocket * rz_socket_new(bool is_ssl)
Definition: socket.c:179
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API char * rz_str_append(char *ptr, const char *string)
Definition: str.c:1063
RZ_API int rz_sys_cmdf(const char *fmt,...) RZ_PRINTF_CHECK(1
#define RZ_NEWS0(x, y)
Definition: rz_types.h:282
#define PFMT64x
Definition: rz_types.h:393
#define ST64_MAX
Definition: rz_types_base.h:84
#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
static struct sockaddr static addrlen static backlog const void msg
Definition: sfsocketcall.h:119
#define d(i)
Definition: sha256.c:44
#define b(i)
Definition: sha256.c:42
#define f(i)
Definition: sha256.c:46
#define c(i)
Definition: sha256.c:43
#define a(i)
Definition: sha256.c:41
const char * name
Definition: rz_io.h:115
const char * version
Definition: rz_io.h:117
Definition: rz_io.h:59
ut64 off
Definition: rz_io.h:61
PrintfCallback cb_printf
Definition: rz_io.h:91
uv_timer_t timeout
Definition: main.c:9
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
eax
Definition: x86-32-avx.s.cs:79
ecx
Definition: x86-32-avx.s.cs:85
ebx
Definition: x86-32-avx.s.cs:85
static const z80_opcode fd[]
Definition: z80_tab.h:997
static int addr
Definition: z80asm.c:58