1 /* radare - LGPL - Copyright 2007-2020 - pancake */
2
3 #include <errno.h>
4 #include <r_io.h>
5 #include <r_lib.h>
6 #include <r_util.h>
7 #include <r_cons.h>
8 #include <r_debug.h> /* only used for BSD PTRACE redefinitions */
9 #include <string.h>
10
11 #define USE_RARUN 0
12
13 #if __linux__ || __APPLE__ || __WINDOWS__ || __NetBSD__ || __KFBSD__ || __OpenBSD__
14 #define DEBUGGER_SUPPORTED 1
15 #else
16 #define DEBUGGER_SUPPORTED 0
17 #endif
18
19 #if DEBUGGER && DEBUGGER_SUPPORTED
20 #define MAGIC_EXIT 123
21
22 #include <signal.h>
23 #if __UNIX__
24 #include <sys/ptrace.h>
25 #include <sys/types.h>
26 #include <sys/wait.h>
27 #endif
28
29 #if __APPLE__
30 #if !__POWERPC__
31 #include <spawn.h>
32 #endif
33 #include <sys/types.h>
34 #include <sys/wait.h>
35 #include <mach/exception_types.h>
36 #include <mach/mach_init.h>
37 #include <mach/mach_port.h>
38 #include <mach/mach_traps.h>
39 #include <mach/task.h>
40 #include <mach/task_info.h>
41 #include <mach/thread_act.h>
42 #include <mach/thread_info.h>
43 #include <mach/vm_map.h>
44 #include <mach-o/loader.h>
45 #include <mach-o/nlist.h>
46 #endif
47
48 #if __WINDOWS__
49 #include <windows.h>
50 #include <tlhelp32.h>
51 #include <winbase.h>
52 #include <psapi.h>
53 #include <w32dbg_wrap.h>
54 #endif
55
56 /*
57 * Creates a new process and returns the result:
58 * -1 : error
59 * 0 : ok
60 */
61
62 #if __WINDOWS__
63 typedef struct {
64 HANDLE hnd;
65 ut64 winbase;
66 } RIOW32;
67
setup_tokens(void)68 static int setup_tokens(void) {
69 HANDLE tok = NULL;
70 TOKEN_PRIVILEGES tp;
71 DWORD err = -1;
72
73 if (!OpenProcessToken (GetCurrentProcess (), TOKEN_ADJUST_PRIVILEGES, &tok)) {
74 goto err_enable;
75 }
76 tp.PrivilegeCount = 1;
77 if (!LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid)) {
78 goto err_enable;
79 }
80 // tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
81 tp.Privileges[0].Attributes = 0; //SE_PRIVILEGE_ENABLED;
82 if (!AdjustTokenPrivileges (tok, 0, &tp, sizeof (tp), NULL, NULL)) {
83 goto err_enable;
84 }
85 err = 0;
86 err_enable:
87 if (tok) {
88 CloseHandle (tok);
89 }
90 if (err) {
91 r_sys_perror ("setup_tokens");
92 }
93 return err;
94 }
95
96 struct __createprocess_params {
97 LPCTSTR appname;
98 LPTSTR cmdline;
99 PROCESS_INFORMATION *pi;
100 };
101
__createprocess_wrap(void * params)102 static int __createprocess_wrap(void *params) {
103 STARTUPINFO si = { 0 };
104 // TODO: Add DEBUG_PROCESS to support child process debugging
105 struct __createprocess_params *p = params;
106 return CreateProcess (p->appname, p->cmdline, NULL, NULL, FALSE,
107 CREATE_NEW_CONSOLE | DEBUG_ONLY_THIS_PROCESS,
108 NULL, NULL, &si, p->pi);
109 }
110
fork_and_ptraceme(RIO * io,int bits,const char * cmd)111 static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) {
112 PROCESS_INFORMATION pi;
113 STARTUPINFO si = { 0 };
114 si.cb = sizeof (si);
115 DEBUG_EVENT de;
116 int pid, tid;
117 if (!*cmd) {
118 return -1;
119 }
120 setup_tokens ();
121 if (!io->w32dbg_wrap) {
122 io->w32dbg_wrap = (struct w32dbg_wrap_instance_t *)w32dbg_wrap_new ();
123 }
124 char *_cmd = io->args ? r_str_appendf (strdup (cmd), " %s", io->args) :
125 strdup (cmd);
126 char **argv = r_str_argv (_cmd, NULL);
127 char *cmdline = NULL;
128 // We need to build a command line with quoted argument and escaped quotes
129 int i = 0;
130 while (argv[i]) {
131 r_str_arg_unescape (argv[i]);
132 cmdline = r_str_appendf (cmdline, "\"%s\" ", argv[i]);
133 i++;
134 }
135
136 LPTSTR appname_ = r_sys_conv_utf8_to_win (argv[0]);
137 LPTSTR cmdline_ = r_sys_conv_utf8_to_win (cmdline);
138 free (cmdline);
139 struct __createprocess_params p = {appname_, cmdline_, &pi};
140 W32DbgWInst *wrap = (W32DbgWInst *)io->w32dbg_wrap;
141 wrap->params.type = W32_CALL_FUNC;
142 wrap->params.func.func = __createprocess_wrap;
143 wrap->params.func.user = &p;
144 w32dbg_wrap_wait_ret (wrap);
145 if (!w32dbgw_ret (wrap)) {
146 w32dbgw_err (wrap);
147 r_sys_perror ("fork_and_ptraceme/CreateProcess");
148 free (appname_);
149 free (cmdline_);
150 return -1;
151 }
152 free (appname_);
153 free (cmdline_);
154 r_str_argv_free (argv);
155
156 /* get process id and thread id */
157 pid = pi.dwProcessId;
158 tid = pi.dwThreadId;
159
160 /* catch create process event */
161 wrap->params.type = W32_WAIT;
162 wrap->params.wait.wait_time = 10000;
163 wrap->params.wait.de = &de;
164 w32dbg_wrap_wait_ret (wrap);
165 if (!w32dbgw_ret (wrap)) goto err_fork;
166
167 /* check if is a create process debug event */
168 if (de.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT) {
169 eprintf ("exception code 0x%04x\n", (ut32)de.dwDebugEventCode);
170 goto err_fork;
171 }
172
173 CloseHandle (de.u.CreateProcessInfo.hFile);
174
175 wrap->pi.hProcess = pi.hProcess;
176 wrap->pi.hThread = pi.hThread;
177 wrap->winbase = (ut64)de.u.CreateProcessInfo.lpBaseOfImage;
178
179 eprintf ("Spawned new process with pid %d, tid = %d\n", pid, tid);
180 return pid;
181
182 err_fork:
183 eprintf ("ERRFORK\n");
184 TerminateProcess (pi.hProcess, 1);
185 w32dbg_wrap_fini ((W32DbgWInst *)io->w32dbg_wrap);
186 io->w32dbg_wrap = NULL;
187 CloseHandle (pi.hThread);
188 CloseHandle (pi.hProcess);
189 return -1;
190 }
191 #else // windows
192
193 #if (__APPLE__ && __POWERPC__) || !__APPLE__
194
195 #if __APPLE__ || __BSD__
inferior_abort_handler(int pid)196 static void inferior_abort_handler(int pid) {
197 eprintf ("Inferior received signal SIGABRT. Executing BKPT.\n");
198 }
199 #endif
200
trace_me(void)201 static void trace_me(void) {
202 #if __APPLE__
203 r_sys_signal (SIGTRAP, SIG_IGN); //NEED BY STEP
204 #endif
205 #if __APPLE__ || __BSD__
206 /* we can probably remove this #if..as long as PT_TRACE_ME is redefined for OSX in r_debug.h */
207 r_sys_signal (SIGABRT, inferior_abort_handler);
208 if (ptrace (PT_TRACE_ME, 0, 0, 0) != 0) {
209 r_sys_perror ("ptrace-traceme");
210 }
211 #if __APPLE__
212 ptrace (PT_SIGEXC, getpid(), NULL, 0);
213 #endif
214 #else
215 if (ptrace (PTRACE_TRACEME, 0, NULL, NULL) != 0) {
216 r_sys_perror ("ptrace-traceme");
217 exit (MAGIC_EXIT);
218 }
219 #endif
220 }
221 #endif
222
223 #if __APPLE__ && !__POWERPC__
handle_posix_error(int err)224 static void handle_posix_error(int err) {
225 switch (err) {
226 case 0:
227 // eprintf ("Success\n");
228 break;
229 case 22:
230 eprintf ("posix_spawnp: Invalid argument\n");
231 break;
232 case 86:
233 eprintf ("Unsupported architecture. Please specify -b 32\n");
234 break;
235 default:
236 eprintf ("posix_spawnp: unknown error %d\n", err);
237 perror ("posix_spawnp");
238 break;
239 }
240 }
241 #endif
242
_get_run_profile(RIO * io,int bits,char ** argv)243 static RRunProfile* _get_run_profile(RIO *io, int bits, char **argv) {
244 char *expr = NULL;
245 int i;
246 RRunProfile *rp = r_run_new (NULL);
247 if (!rp) {
248 return NULL;
249 }
250 for (i = 0; argv[i]; i++) {
251 rp->_args[i] = argv[i];
252 }
253 rp->_args[i] = NULL;
254 if (!argv[0]) {
255 r_run_free (rp);
256 return NULL;
257 }
258 rp->_program = strdup (argv[0]);
259
260 rp->_dodebug = true;
261 if (io->runprofile && *io->runprofile) {
262 if (!r_run_parsefile (rp, io->runprofile)) {
263 eprintf ("Can't find profile '%s'\n", io->runprofile);
264 r_run_free (rp);
265 return NULL;
266 }
267 if (strstr (io->runprofile, R_SYS_DIR ".rarun2.")) {
268 (void)r_file_rm (io->runprofile);
269 }
270 } else if (io->envprofile) {
271 if (!r_run_parse (rp, io->envprofile)) {
272 eprintf ("Can't parse default rarun2 profile\n");
273 r_run_free (rp);
274 return NULL;
275 }
276 }
277 if (bits == 64) {
278 r_run_parseline (rp, expr=strdup ("bits=64"));
279 } else if (bits == 32) {
280 r_run_parseline (rp, expr=strdup ("bits=32"));
281 }
282 free (expr);
283 if (r_run_config_env (rp)) {
284 eprintf ("Can't config the environment.\n");
285 r_run_free (rp);
286 return NULL;
287 }
288 return rp;
289 }
290
291 #if __APPLE__ && !__POWERPC__
292
handle_posix_redirection(RRunProfile * rp,posix_spawn_file_actions_t * fileActions)293 static void handle_posix_redirection(RRunProfile *rp, posix_spawn_file_actions_t *fileActions) {
294 const int mode = S_IRUSR | S_IWUSR;
295 if (rp->_stdin) {
296 posix_spawn_file_actions_addopen (fileActions, STDIN_FILENO, rp->_stdin, O_RDONLY, mode);
297 }
298 if (rp->_stdout) {
299 posix_spawn_file_actions_addopen (fileActions, STDOUT_FILENO, rp->_stdout, O_WRONLY, mode);
300 }
301 if (rp->_stderr) {
302 posix_spawn_file_actions_addopen (fileActions, STDERR_FILENO, rp->_stderr, O_WRONLY, mode);
303 }
304 }
305
306 // __UNIX__ (not windows)
fork_and_ptraceme_for_mac(RIO * io,int bits,const char * cmd)307 static int fork_and_ptraceme_for_mac(RIO *io, int bits, const char *cmd) {
308 pid_t p = -1;
309 char **argv;
310 posix_spawn_file_actions_t fileActions;
311 ut32 ps_flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
312 sigset_t no_signals;
313 sigset_t all_signals;
314 size_t copied = 1;
315 cpu_type_t cpu = CPU_TYPE_ANY;
316 posix_spawnattr_t attr = {0};
317 posix_spawnattr_init (&attr);
318
319 sigemptyset (&no_signals);
320 sigfillset (&all_signals);
321 posix_spawnattr_setsigmask (&attr, &no_signals);
322 posix_spawnattr_setsigdefault (&attr, &all_signals);
323
324 posix_spawn_file_actions_init (&fileActions);
325 posix_spawn_file_actions_addinherit_np (&fileActions, STDIN_FILENO);
326 posix_spawn_file_actions_addinherit_np (&fileActions, STDOUT_FILENO);
327 posix_spawn_file_actions_addinherit_np (&fileActions, STDERR_FILENO);
328
329 ps_flags |= POSIX_SPAWN_CLOEXEC_DEFAULT;
330 ps_flags |= POSIX_SPAWN_START_SUSPENDED;
331 #define _POSIX_SPAWN_DISABLE_ASLR 0x0100
332 int ret;
333 argv = r_str_argv (cmd, NULL);
334 if (!argv) {
335 posix_spawn_file_actions_destroy (&fileActions);
336 return -1;
337 }
338 RRunProfile *rp = _get_run_profile (io, bits, argv);
339 if (!rp) {
340 r_str_argv_free (argv);
341 posix_spawn_file_actions_destroy (&fileActions);
342 return -1;
343 }
344 handle_posix_redirection (rp, &fileActions);
345 if (rp->_args[0]) {
346 if (!rp->_aslr) {
347 ps_flags |= _POSIX_SPAWN_DISABLE_ASLR;
348 }
349 #if __x86_64__
350 if (rp->_bits == 32) {
351 cpu = CPU_TYPE_I386;
352 }
353 #endif
354 (void)posix_spawnattr_setflags (&attr, ps_flags);
355 posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &copied);
356 ret = posix_spawnp (&p, rp->_args[0], &fileActions, &attr, rp->_args, NULL);
357 handle_posix_error (ret);
358 }
359 r_str_argv_free (argv);
360 r_run_free (rp);
361 posix_spawn_file_actions_destroy (&fileActions);
362 return p; // -1 ?
363 }
364 #endif // __APPLE__ && !__POWERPC__
365
366 #if (!(__APPLE__ && !__POWERPC__))
367 typedef struct fork_child_data_t {
368 RIO *io;
369 int bits;
370 const char *cmd;
371 } fork_child_data;
372
fork_child_callback(void * user)373 static void fork_child_callback(void *user) {
374 fork_child_data *data = user;
375 char **argv = r_str_argv (data->cmd, NULL);
376 if (!argv) {
377 exit (1);
378 }
379 r_sys_clearenv ();
380 RRunProfile *rp = _get_run_profile (data->io, data->bits, argv);
381 if (!rp) {
382 r_str_argv_free (argv);
383 exit (1);
384 }
385 trace_me ();
386 r_run_start (rp);
387 r_run_free (rp);
388 r_str_argv_free (argv);
389 exit (1);
390 }
391
fork_and_ptraceme_for_unix(RIO * io,int bits,const char * cmd)392 static int fork_and_ptraceme_for_unix(RIO *io, int bits, const char *cmd) {
393 int ret, status, child_pid;
394 void *bed = NULL;
395 fork_child_data child_data;
396 child_data.io = io;
397 child_data.bits = bits;
398 child_data.cmd = cmd;
399 child_pid = r_io_ptrace_fork (io, fork_child_callback, &child_data);
400 switch (child_pid) {
401 case -1:
402 perror ("fork_and_ptraceme");
403 break;
404 case 0:
405 return -1;
406 default:
407 /* XXX: clean this dirty code */
408 do {
409 ret = waitpid (child_pid, &status, WNOHANG);
410 if (ret == -1) {
411 perror ("waitpid");
412 return -1;
413 }
414 bed = r_cons_sleep_begin ();
415 usleep (100000);
416 r_cons_sleep_end (bed);
417 } while (ret != child_pid && !r_cons_is_breaked ());
418 if (WIFSTOPPED (status)) {
419 eprintf ("Process with PID %d started...\n", (int)child_pid);
420 } else if (WEXITSTATUS (status) == MAGIC_EXIT) {
421 child_pid = -1;
422 } else if (r_cons_is_breaked ()) {
423 kill (child_pid, SIGSTOP);
424 } else {
425 eprintf ("Killing child process %d due to an error\n", (int)child_pid);
426 kill (child_pid, SIGSTOP);
427 }
428 break;
429 }
430 return child_pid;
431 }
432 #endif
433
fork_and_ptraceme(RIO * io,int bits,const char * cmd)434 static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) {
435 // Before calling the platform implementation, append arguments to the command if they have been provided
436 char *_eff_cmd = io->args ? r_str_appendf (strdup (cmd), " %s", io->args) : strdup(cmd);
437 int r = 0;
438
439 #if __APPLE__ && !__POWERPC__
440 r = fork_and_ptraceme_for_mac (io, bits, _eff_cmd);
441 #else
442 r = fork_and_ptraceme_for_unix (io, bits, _eff_cmd);
443 #endif
444
445 free (_eff_cmd);
446 return r;
447 }
448 #endif
449
__plugin_open(RIO * io,const char * file,bool many)450 static bool __plugin_open(RIO *io, const char *file, bool many) {
451 if (!strncmp (file, "waitfor://", 10)) {
452 return true;
453 }
454 if (!strncmp (file, "pidof://", 8)) {
455 return true;
456 }
457 return (!strncmp (file, "dbg://", 6) && file[6]);
458 }
459
460 #include <r_core.h>
get_pid_of(RIO * io,const char * procname)461 static int get_pid_of(RIO *io, const char *procname) {
462 RCore *c = io->corebind.core;
463 if (c && c->dbg && c->dbg->h) {
464 RListIter *iter;
465 RDebugPid *proc;
466 RDebug *d = c->dbg;
467 RList *pids = d->h->pids (d, 0);
468 r_list_foreach (pids, iter, proc) {
469 if (strstr (proc->path, procname)) {
470 eprintf ("Matching PID %d %s\n", proc->pid, proc->path);
471 return proc->pid;
472 }
473 }
474 } else {
475 eprintf ("Cannot enumerate processes\n");
476 }
477 return -1;
478 }
479
__open(RIO * io,const char * file,int rw,int mode)480 static RIODesc *__open(RIO *io, const char *file, int rw, int mode) {
481 RIOPlugin *_plugin;
482 RIODesc *ret = NULL;
483 char uri[128];
484 if (!strncmp (file, "waitfor://", 10)) {
485 const char *procname = file + 10;
486 eprintf ("Waiting for %s\n", procname);
487 while (true) {
488 int target_pid = get_pid_of (io, procname);
489 if (target_pid != -1) {
490 snprintf (uri, sizeof (uri), "dbg://%d", target_pid);
491 file = uri;
492 break;
493 }
494 r_sys_usleep (100);
495 }
496 } else if (!strncmp (file, "pidof://", 8)) {
497 const char *procname = file + 8;
498 int target_pid = get_pid_of (io, procname);
499 if (target_pid == -1) {
500 eprintf ("Cannot find matching process for %s\n", file);
501 return NULL;
502 }
503 snprintf (uri, sizeof (uri), "dbg://%d", target_pid);
504 file = uri;
505 }
506 if (__plugin_open (io, file, 0)) {
507 const char *pidfile = file + 6;
508 char *endptr;
509 int pid = (int)strtol (pidfile, &endptr, 10);
510 if (endptr == pidfile || pid < 0) {
511 pid = -1;
512 }
513 if (pid == -1) {
514 pid = fork_and_ptraceme (io, io->bits, file + 6);
515 if (pid == -1) {
516 return NULL;
517 }
518 #if __WINDOWS__
519 sprintf (uri, "w32dbg://%d", pid);
520 _plugin = r_io_plugin_resolve (io, (const char *)uri, false);
521 if (!_plugin || !_plugin->open) {
522 return NULL;
523 }
524 if ((ret = _plugin->open (io, uri, rw, mode))) {
525 RCore *c = io->corebind.core;
526 W32DbgWInst *wrap = (W32DbgWInst *)ret->data;
527 c->dbg->user = wrap;
528 }
529 #elif __APPLE__
530 sprintf (uri, "smach://%d", pid); //s is for spawn
531 _plugin = r_io_plugin_resolve (io, (const char *)uri + 1, false);
532 if (!_plugin || !_plugin->open || !_plugin->close) {
533 return NULL;
534 }
535 ret = _plugin->open (io, uri, rw, mode);
536 #else
537 // TODO: use io_procpid here? faster or what?
538 sprintf (uri, "ptrace://%d", pid);
539 _plugin = r_io_plugin_resolve (io, (const char *)uri, false);
540 if (!_plugin || !_plugin->open) {
541 return NULL;
542 }
543 ret = _plugin->open (io, uri, rw, mode);
544 #endif
545 } else {
546 sprintf (uri, "attach://%d", pid);
547 _plugin = r_io_plugin_resolve (io, (const char *)uri, false);
548 if (!_plugin || !_plugin->open) {
549 return NULL;
550 }
551 ret = _plugin->open (io, uri, rw, mode);
552 #if __WINDOWS__
553 if (ret) {
554 RCore *c = io->corebind.core;
555 W32DbgWInst *wrap = (W32DbgWInst *)ret->data;
556 c->dbg->user = wrap;
557 }
558 #endif
559 }
560 if (ret) {
561 ret->plugin = _plugin;
562 ret->referer = strdup (file); //kill this
563 }
564 }
565 return ret;
566 }
567
__close(RIODesc * desc)568 static int __close (RIODesc *desc) {
569 int ret = -2;
570 eprintf ("something went wrong\n");
571 if (desc) {
572 eprintf ("trying to close %d with io_debug\n", desc->fd);
573 ret = -1;
574 }
575 r_sys_backtrace ();
576 return ret;
577 }
578
579 RIOPlugin r_io_plugin_debug = {
580 .name = "debug",
581 .desc = "Attach to native debugger instance",
582 .license = "LGPL3",
583 .uris = "dbg://,pidof://,waitfor://",
584 .author = "pancake",
585 .version = "0.2.0",
586 .open = __open,
587 .close = __close,
588 .check = __plugin_open,
589 .isdbg = true,
590 };
591 #else
592 RIOPlugin r_io_plugin_debug = {
593 .name = "debug",
594 .desc = "Debug a program or pid. (NOT SUPPORTED FOR THIS PLATFORM)",
595 };
596 #endif
597
598 #ifndef R2_PLUGIN_INCORE
599 R_API RLibStruct radare_plugin = {
600 .type = R_LIB_TYPE_IO,
601 .data = &r_io_plugin_debug,
602 .version = R2_VERSION
603 };
604 #endif
605