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