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