Example #1
0
static void fork_child_callback(void *user) {
	fork_child_data *data = user;
	if (data->runprofile) {
		char **argv = r_str_argv (data->cmd, NULL);
		if (!argv) {
			exit (1);
		}
		RRunProfile *rp = _get_run_profile (data->io, data->bits, argv);
		if (!rp) {
			r_str_argv_free (argv);
			exit (1);
		}
		trace_me ();
		r_run_start (rp);
		r_run_free (rp);
		r_str_argv_free (argv);
		exit (1);
	} else {
		char *_cmd = data->io->args ?
					 r_str_appendf (strdup (data->cmd), " %s", data->io->args) :
					 strdup (data->cmd);
		trace_me ();
		char **argv = r_str_argv (_cmd, NULL);
		if (!argv) {
			free (_cmd);
			return;
		}
		if (argv && *argv) {
			int i;
			for (i = 3; i < 1024; i++) {
				(void)close (i);
			}
			for (i = 0; argv[i]; i++) {
				r_str_arg_unescape (argv[i]);
			}
			if (execvp (argv[0], argv) == -1) {
				eprintf ("Could not execvp: %s\n", strerror (errno));
				exit (MAGIC_EXIT);
			}
		} else {
			eprintf ("Invalid execvp\n");
		}
		r_str_argv_free (argv);
		free (_cmd);
	}
}
Example #2
0
R_API int r_sandbox_system (const char *x, int n) {
	if (enabled) {
		eprintf ("sandbox: system call disabled\n");
		return -1;
	}
#if LIBC_HAVE_FORK
#if LIBC_HAVE_SYSTEM
	if (n) return system (x);
	return execl ("/bin/sh", "sh", "-c", x, (const char*)NULL);
#else
	#include <spawn.h>
	if (n && !strchr (x, '|')) {
		char **argv, *cmd = strdup (x);
		int rc, pid, argc;
		char *isbg = strchr (cmd, '&');
		// XXX this is hacky
		if (isbg) {
			*isbg = 0;
		}
		argv = r_str_argv (cmd, &argc);
		if (argv) {
			char *argv0 = r_file_path (argv[0]);
			if (!argv0) {
				eprintf ("Cannot find '%s'\n", argv[0]);
				return -1;
			}
			pid = 0;
			posix_spawn (&pid, argv0, NULL, NULL, argv, NULL);
			if (isbg) {
				// XXX. wait for children
				rc = 0;
			} else {
				rc = waitpid (pid, NULL, 0);
			}
			r_str_argv_free (argv);
			free (argv0);
			return rc;
		}
		eprintf ("Error parsing command arguments\n");
		return -1;
	}
	int child = fork();
	if (child == -1) return -1;
	if (child) {
		return waitpid (child, NULL, 0);
	}
	execl ("/bin/sh", "sh", "-c", x, (const char*)NULL);
	exit (1);
#endif
#endif
	return -1;
}
Example #3
0
static int fork_and_ptraceme(const char *cmd) {
	char **argv;
	int ret, status, pid = vfork ();
	switch (pid) {
	case -1:
		perror ("fork_and_ptraceme");
		break;
	case 0:
#if __APPLE__
		signal (SIGTRAP, SIG_IGN); //NEED BY STEP 
#endif
#if __APPLE__ || __BSD__
/* we can probably remove this #if..as long as PT_TRACE_ME is redefined for OSX in r_debug.h */
		signal (SIGABRT, inferior_abort_handler);
		if (ptrace (PT_TRACE_ME, 0, 0, 0) != 0) {
#else
		if (ptrace (PTRACE_TRACEME, 0, NULL, NULL) != 0) {
#endif
			eprintf ("ptrace-traceme failed\n");
			exit (MAGIC_EXIT);
		}
		// TODO: Add support to redirect filedescriptors
		// TODO: Configure process environment
		argv = r_str_argv (cmd, NULL);
		execvp (argv[0], argv);
		r_str_argv_free (argv);

		perror ("fork_and_attach: execv");
		//printf(stderr, "[%d] %s execv failed.\n", getpid(), ps.filename);
		exit (MAGIC_EXIT); /* error */
		return 0; // invalid pid // if exit is overriden.. :)
	default:
		/* XXX: clean this dirty code */
                ret = wait (&status);
		if (ret != pid)
			eprintf ("Wait event received by different pid %d\n", ret);
                if (WIFSTOPPED (status))
                        eprintf ("Process with PID %d started...\n", (int)pid);
		if (WEXITSTATUS (status) == MAGIC_EXIT)
			pid = -1;
		// XXX kill (pid, SIGSTOP);
		break;
	}
	eprintf ("PID = %d\n", pid);
	return pid;
}
#endif

static int __plugin_open(struct r_io_t *io, const char *file) {
	if (!memcmp (file, "dbg://", 6) && file[6])
		return R_TRUE;
	return R_FALSE;
}

static RIODesc *__open(RIO *io, const char *file, int rw, int mode) {
	char uri[128];
	if (__plugin_open (io, file)) {
		int pid = atoi (file+6);
		if (pid == 0) {
			pid = fork_and_ptraceme (file+6);
			if (pid==-1)
				return NULL;
#if __WINDOWS__
			sprintf (uri, "w32dbg://%d", pid);
#elif __APPLE__
			sprintf (uri, "mach://%d", pid);
#else
			// TODO: use io_procpid here? faster or what?
			sprintf (uri, "ptrace://%d", pid);
#endif
			eprintf ("io_redirect: %s\n", uri);
			r_io_redirect (io, uri);
			return NULL;
		} else {
			sprintf (uri, "attach://%d", pid);
			r_io_redirect (io, uri);
			return NULL;
		}
	}
	r_io_redirect (io, NULL);
	return NULL;
}
Example #4
0
// __UNIX__ (not windows)
static int fork_and_ptraceme_for_mac(RIO *io, int bits, const char *cmd) {
	bool runprofile = io->runprofile && *(io->runprofile);
	pid_t p = -1;
	char **argv;
	posix_spawn_file_actions_t fileActions;
	ut32 ps_flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
	sigset_t no_signals;
	sigset_t all_signals;
	size_t copied = 1;
	cpu_type_t cpu = CPU_TYPE_ANY;
	posix_spawnattr_t attr = {0};
	posix_spawnattr_init (&attr);

	sigemptyset (&no_signals);
	sigfillset (&all_signals);
	posix_spawnattr_setsigmask (&attr, &no_signals);
	posix_spawnattr_setsigdefault (&attr, &all_signals);

	posix_spawn_file_actions_init (&fileActions);
	posix_spawn_file_actions_addinherit_np (&fileActions, STDIN_FILENO);
	posix_spawn_file_actions_addinherit_np (&fileActions, STDOUT_FILENO);
	posix_spawn_file_actions_addinherit_np (&fileActions, STDERR_FILENO);

	ps_flags |= POSIX_SPAWN_CLOEXEC_DEFAULT;
	ps_flags |= POSIX_SPAWN_START_SUSPENDED;
#define _POSIX_SPAWN_DISABLE_ASLR 0x0100
	if (!runprofile) {
		int ret, useASLR = io->aslr;
		char *_cmd = io->args
			? r_str_appendf (strdup (cmd), " %s", io->args)
			: strdup (cmd);
		argv = r_str_argv (_cmd, NULL);
		if (!argv) {
			free (_cmd);
			return -1;
		}
		if (!*argv) {
			r_str_argv_free (argv);
			free (_cmd);
			eprintf ("Invalid execvp\n");
			return -1;
		}
		if (useASLR != -1) {
			if (!useASLR) {
				ps_flags |= _POSIX_SPAWN_DISABLE_ASLR;
			}
		}
		(void)posix_spawnattr_setflags (&attr, ps_flags);
#if __x86_64__
		if (bits == 32) {
			cpu = CPU_TYPE_I386;
			// cpu |= CPU_ARCH_ABI64;
		}
#endif
		posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &copied);
		{
			char *dst = r_file_readlink (argv[0]);
			if (dst) {
				argv[0] = dst;
			}
		}
		// XXX: this is a workaround to fix spawning programs with spaces in path
		if (strstr (argv[0], "\\ ")) {
			argv[0] = r_str_replace (argv[0], "\\ ", " ", true);
		}

		ret = posix_spawnp (&p, argv[0], &fileActions, &attr, argv, NULL);
		handle_posix_error (ret);
		posix_spawn_file_actions_destroy (&fileActions);
		r_str_argv_free (argv);
		free (_cmd);
		return p;
	}
	int ret;
	argv = r_str_argv (cmd, NULL);
	if (!argv) {
		posix_spawn_file_actions_destroy (&fileActions);
		return -1;
	}
	RRunProfile *rp = _get_run_profile (io, bits, argv);
	if (!rp) {
		r_str_argv_free (argv);
		posix_spawn_file_actions_destroy (&fileActions);
		return -1;
	}
	handle_posix_redirection (rp, &fileActions);
	if (rp->_args[0]) {
		if (!rp->_aslr) {
			ps_flags |= _POSIX_SPAWN_DISABLE_ASLR;
		}
#if __x86_64__
		if (rp->_bits == 32) {
			cpu = CPU_TYPE_I386;
		}
#endif
		(void)posix_spawnattr_setflags (&attr, ps_flags);
		posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &copied);
		ret = posix_spawnp (&p, rp->_args[0], &fileActions, &attr, rp->_args, NULL);
		handle_posix_error (ret);
	}
	r_str_argv_free (argv);
	r_run_free (rp);
	posix_spawn_file_actions_destroy (&fileActions);
	return p; // -1 ?
}
Example #5
0
static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) {
	PROCESS_INFORMATION pi;
	STARTUPINFO si = { 0 } ;
	DEBUG_EVENT de;
	int pid, tid;
	HANDLE th = INVALID_HANDLE_VALUE;
	if (!*cmd) {
		return -1;
	}
	setup_tokens ();
	char *_cmd = io->args ? r_str_appendf (strdup (cmd), " %s", io->args) :
		strdup (cmd);
	char **argv = r_str_argv (_cmd, NULL);
	// We need to build a command line with quoted argument and escaped quotes
	int cmd_len = 0;
	int i = 0;

	si.cb = sizeof (si);
	while (argv[i]) {
		char *current = argv[i];
		int quote_count = 0;
		while ((current = strchr (current, '"'))) {
			quote_count ++;
		}
		cmd_len += strlen (argv[i]);
		cmd_len += quote_count; // The quotes will add one backslash each
		cmd_len += 2; // Add two enclosing quotes;
		i++;
	}
	cmd_len += i-1; // Add argc-1 spaces

	char *cmdline = malloc ((cmd_len + 1) * sizeof (char));
	int cmd_i = 0; // Next character to write in cmdline
	i = 0;
	while (argv[i]) {
		if (i != 0) {
			cmdline[cmd_i++] = ' ';
		}
		cmdline[cmd_i++] = '"';

		int arg_i = 0; // Index of current character in orginal argument
		while (argv[i][arg_i]) {
			char c = argv[i][arg_i];
			if (c == '"') {
				cmdline[cmd_i++] = '\\';
			}
			cmdline[cmd_i++] = c;
			arg_i++;
		}

		cmdline[cmd_i++] = '"';
		i++;
	}
	cmdline[cmd_i] = '\0';

	LPTSTR appname_ = r_sys_conv_utf8_to_utf16 (argv[0]);
	LPTSTR cmdline_ = r_sys_conv_utf8_to_utf16 (cmdline);
	if (!CreateProcess (appname_, cmdline_, NULL, NULL, FALSE,
						 CREATE_NEW_CONSOLE | DEBUG_ONLY_THIS_PROCESS,
						 NULL, NULL, &si, &pi)) {
		r_sys_perror ("fork_and_ptraceme/CreateProcess");
		free (appname_);
		free (cmdline_);
		return -1;
	}
	free (appname_);
	free (cmdline_);
	free (cmdline);
	r_str_argv_free (argv);
	/* get process id and thread id */
	pid = pi.dwProcessId;
	tid = pi.dwThreadId;

	/* catch create process event */
	if (!WaitForDebugEvent (&de, 10000)) goto err_fork;

	/* check if is a create process debug event */
	if (de.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT) {
		eprintf ("exception code 0x%04x\n", (ut32)de.dwDebugEventCode);
		goto err_fork;
	}

	if (th != INVALID_HANDLE_VALUE) {
		CloseHandle (th);
	}
	eprintf ("Spawned new process with pid %d, tid = %d\n", pid, tid);
	winbase = (ut64)de.u.CreateProcessInfo.lpBaseOfImage;
	wintid = tid;
	return pid;

err_fork:
	eprintf ("ERRFORK\n");
	TerminateProcess (pi.hProcess, 1);
	if (th != INVALID_HANDLE_VALUE) CloseHandle (th);
	return -1;
}
Example #6
0
static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) {
	PROCESS_INFORMATION pi;
        STARTUPINFO si = { sizeof (si) };
        DEBUG_EVENT de;
	int pid, tid;
	HANDLE th = INVALID_HANDLE_VALUE;
	if (!*cmd)
		return -1;
	setup_tokens ();

	char **argv = r_str_argv (cmd, NULL);
	// We need to build a command line with quoted argument and escaped quotes
	int cmd_len = 0;
	int i = 0;
	while (argv[i]) {
		char *current = argv[i];
		int quote_count = 0;
		while ((current = strchr (current, '"')))
			quote_count ++;
		cmd_len += strlen (argv[i]);
		cmd_len += quote_count; // The quotes will add one backslash each
		cmd_len += 2; // Add two enclosing quotes;
		i++;
	}
	cmd_len += i-1; // Add argc-1 spaces

	char *cmdline = malloc ((cmd_len + 1) * sizeof (char));
	int cmd_i = 0; // Next character to write in cmdline
	i = 0;
	while (argv[i]) {
		if (i != 0)
			cmdline[cmd_i++] = ' ';

		cmdline[cmd_i++] = '"';
		
		int arg_i = 0; // Index of current character in orginal argument
		while (argv[i][arg_i]) {
			char c = argv[i][arg_i];
			if (c == '"') {
				cmdline[cmd_i++] = '\\';
			}
			cmdline[cmd_i++] = c;
			arg_i++;
		}

		cmdline[cmd_i++] = '"';
		i++;
	}
	cmdline[cmd_i] = '\0';

        if (!CreateProcess (argv[0], cmdline,
                        NULL, NULL, FALSE,
                        CREATE_NEW_CONSOLE | DEBUG_ONLY_THIS_PROCESS,
                        NULL, NULL, &si, &pi)) {
                r_sys_perror ("CreateProcess");
                return -1;
        }
	free (cmdline);
	r_str_argv_free (argv);

        /* get process id and thread id */
        pid = pi.dwProcessId;
        tid = pi.dwThreadId;

#if 0
        /* load thread list */
	{
		HANDLE h;
		THREADENTRY32 te32;
		HANDLE WINAPI (*win32_openthread)(DWORD, BOOL, DWORD) = NULL;
		win32_openthread = (HANDLE WINAPI (*)(DWORD, BOOL, DWORD))
			GetProcAddress (GetModuleHandle ("kernel32"), "OpenThread");

		th = CreateToolhelp32Snapshot (TH32CS_SNAPTHREAD, pid);
		if (th == INVALID_HANDLE_VALUE || !Thread32First(th, &te32))
			r_sys_perror ("CreateToolhelp32Snapshot");

		do {
			if (te32.th32OwnerProcessID == pid) {
				h = win32_openthread (THREAD_ALL_ACCESS, 0, te32.th32ThreadID);
				if (h == NULL) r_sys_perror ("OpenThread");
				else eprintf ("HANDLE=%p\n", h);
			}
		} while (Thread32Next (th, &te32));
	}
#endif

#if 0
	// Access denied here :?
	if (ContinueDebugEvent (pid, tid, DBG_CONTINUE) == 0) {
		r_sys_perror ("ContinueDebugEvent");
		goto err_fork;
	}
#endif

        /* catch create process event */
        if (!WaitForDebugEvent (&de, 10000))
                goto err_fork;

        /* check if is a create process debug event */
        if (de.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT) {
                eprintf ("exception code 0x%04x\n", (ut32)de.dwDebugEventCode);
                goto err_fork;
        }

	if (th != INVALID_HANDLE_VALUE)
		CloseHandle (th);

	eprintf ("PID=%d\n", pid);
	eprintf ("TID=%d\n", tid);
        return pid;

err_fork:
	eprintf ("ERRFORK\n");
        TerminateProcess (pi.hProcess, 1);
	if (th != INVALID_HANDLE_VALUE)
		CloseHandle (th);
        return -1;
}
Example #7
0
// __UNIX__ (not windows)
static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) {
	bool runprofile = io->runprofile && *(io->runprofile);
	char **argv;
#if __APPLE__ && !__POWERPC__
	pid_t p = -1;
	posix_spawn_file_actions_t fileActions;
	ut32 ps_flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
	sigset_t no_signals;
	sigset_t all_signals;
	size_t copied = 1;
	cpu_type_t cpu = CPU_TYPE_ANY;
	posix_spawnattr_t attr = {0};
	posix_spawnattr_init (&attr);

	sigemptyset (&no_signals);
	sigfillset (&all_signals);
	posix_spawnattr_setsigmask (&attr, &no_signals);
	posix_spawnattr_setsigdefault (&attr, &all_signals);

	posix_spawn_file_actions_init (&fileActions);
	posix_spawn_file_actions_addinherit_np (&fileActions, STDIN_FILENO);
	posix_spawn_file_actions_addinherit_np (&fileActions, STDOUT_FILENO);
	posix_spawn_file_actions_addinherit_np (&fileActions, STDERR_FILENO);

	ps_flags |= POSIX_SPAWN_CLOEXEC_DEFAULT;
	ps_flags |= POSIX_SPAWN_START_SUSPENDED;
#define _POSIX_SPAWN_DISABLE_ASLR 0x0100
	if (!runprofile) {
		int ret, useASLR = io->aslr;
		char *_cmd = io->args
			? r_str_appendf (strdup (cmd), " %s", io->args)
			: strdup (cmd);
		argv = r_str_argv (_cmd, NULL);
		if (!argv) {
			free (_cmd);
			return -1;
		}
		if (!*argv) {
			r_str_argv_free (argv);
			free (_cmd);
			eprintf ("Invalid execvp\n");
			return -1;
		}
		if (useASLR != -1) {
			if (!useASLR) {
				ps_flags |= _POSIX_SPAWN_DISABLE_ASLR;
			}
		}
		(void)posix_spawnattr_setflags (&attr, ps_flags);
#if __x86_64__
		if (bits == 32) {
			cpu = CPU_TYPE_I386;
			// cpu |= CPU_ARCH_ABI64;
		}
#endif
		posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &copied);
		{
			char *dst = r_file_readlink (argv[0]);
			if (dst) {
				argv[0] = dst;
			}
		}
		ret = posix_spawnp (&p, argv[0], NULL, &attr, argv, NULL);
		handle_posix_error (ret);
		posix_spawn_file_actions_destroy (&fileActions);
		r_str_argv_free (argv);
		free (_cmd);
		return p;
	} else {
		int ret;
		argv = r_str_argv (cmd, NULL);
		if (!argv) {
			posix_spawn_file_actions_destroy (&fileActions);
			return -1;
		}
		RRunProfile *rp = _get_run_profile (io, bits, argv);
		if (!rp) {
			r_str_argv_free (argv);
			posix_spawn_file_actions_destroy (&fileActions);
			return -1;
		}
		handle_posix_redirection (rp, &fileActions);
		if (rp->_args[0]) {
			if (!rp->_aslr) {
				ps_flags |= _POSIX_SPAWN_DISABLE_ASLR;
			}
#if __x86_64__
			if (rp->_bits == 32) {
				cpu = CPU_TYPE_I386;
			}
#endif
			(void)posix_spawnattr_setflags (&attr, ps_flags);
			posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &copied);
			ret = posix_spawnp (&p, rp->_args[0], &fileActions, &attr, rp->_args, NULL);
			handle_posix_error (ret);
		}
		r_str_argv_free (argv);
		r_run_free (rp);
		posix_spawn_file_actions_destroy (&fileActions);
		return p;
	}
	posix_spawn_file_actions_destroy (&fileActions);
	return -1;
#endif
	int ret, status, child_pid;
	child_pid = r_sys_fork ();
	switch (child_pid) {
	case -1:
		perror ("fork_and_ptraceme");
		break;
	case 0:
		if (runprofile) {
			argv = r_str_argv (cmd, NULL);
			if (!argv) {
				exit(1);
			}
			RRunProfile *rp = _get_run_profile (io, bits, argv);
			if (!rp) {
				r_str_argv_free (argv);
				exit (1);
			}
			trace_me ();
			r_run_start (rp);
			r_run_free (rp);
			r_str_argv_free (argv);
			exit (1);
		} else {
			char *_cmd = io->args ?
				r_str_appendf (strdup (cmd), " %s", io->args) :
				strdup (cmd);

			trace_me ();
			argv = r_str_argv (_cmd, NULL);
			if (!argv) {
				free (_cmd);
				return -1;
			}
			if (argv && *argv) {
				int i;
				for (i = 3; i < 1024; i++)
					(void)close (i);
				execvp (argv[0], argv);
			} else {
				eprintf ("Invalid execvp\n");
			}
			r_str_argv_free (argv);
			free (_cmd);
		}
		perror ("fork_and_attach: execv");
		//printf(stderr, "[%d] %s execv failed.\n", getpid(), ps.filename);
		exit (MAGIC_EXIT); /* error */
		return 0; // invalid pid // if exit is overriden.. :)
	default:
		/* XXX: clean this dirty code */
		do {
			ret = wait (&status);
			if (ret == -1) return -1;
			if (ret != child_pid) {
				eprintf ("Wait event received by "
					"different pid %d\n", ret);
			}
		} while (ret != child_pid);
		if (WIFSTOPPED (status)) {
			eprintf ("Process with PID %d started...\n", (int)child_pid);
		}
		if (WEXITSTATUS (status) == MAGIC_EXIT) {
			child_pid = -1;
		}
		// XXX kill (pid, SIGSTOP);
		break;
	}
	return child_pid;
}
Example #8
0
static void trace_me () {
#if __APPLE__
	signal (SIGTRAP, SIG_IGN); //NEED BY STEP
#endif
#if __APPLE__ || __BSD__
/* we can probably remove this #if..as long as PT_TRACE_ME is redefined for OSX in r_debug.h */
	signal (SIGABRT, inferior_abort_handler);
	if (ptrace (PT_TRACE_ME, 0, 0, 0) != 0) {
#else
	if (ptrace (PTRACE_TRACEME, 0, NULL, NULL) != 0) {
#endif
		r_sys_perror ("ptrace-traceme");
		exit (MAGIC_EXIT);
	}
}

// __UNIX__ (not windows)
static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) {
	bool runprofile = io->runprofile && *(io->runprofile);
	char **argv;
#if __APPLE__ && !__POWERPC__
	if (!runprofile) {
#define _POSIX_SPAWN_DISABLE_ASLR 0x0100
		posix_spawn_file_actions_t fileActions;
		ut32 ps_flags = POSIX_SPAWN_SETSIGDEF |
				POSIX_SPAWN_SETSIGMASK;
   		sigset_t no_signals;
    		sigset_t all_signals;
    		sigemptyset (&no_signals);
    		sigfillset (&all_signals);
		posix_spawnattr_t attr = {0};
		size_t copied = 1;
		cpu_type_t cpu;
		pid_t p = -1;
		int ret, useASLR = io->aslr;
		char *_cmd = io->args ?
				r_str_concatf (strdup (cmd), " %s", io->args) :
				strdup (cmd);
		argv = r_str_argv (_cmd, NULL);
		if (!argv) {
			free (_cmd);
			return -1;
		}
		if (!*argv) {
			r_str_argv_free (argv);
			free (_cmd);
			eprintf ("Invalid execvp\n");
			return -1;
		}
		posix_spawnattr_init (&attr);
		if (useASLR != -1) {
			if (!useASLR) ps_flags |= _POSIX_SPAWN_DISABLE_ASLR;
		}

		posix_spawn_file_actions_init (&fileActions);
		posix_spawn_file_actions_addinherit_np (&fileActions, STDIN_FILENO);
		posix_spawn_file_actions_addinherit_np (&fileActions, STDOUT_FILENO);
		posix_spawn_file_actions_addinherit_np (&fileActions, STDERR_FILENO);
		ps_flags |= POSIX_SPAWN_CLOEXEC_DEFAULT;
		ps_flags |= POSIX_SPAWN_START_SUSPENDED;

   		posix_spawnattr_setsigmask(&attr, &no_signals);
    		posix_spawnattr_setsigdefault(&attr, &all_signals);

		(void)posix_spawnattr_setflags (&attr, ps_flags);
#if __i386__ || __x86_64__
		cpu = CPU_TYPE_I386;
		if (bits == 64) cpu |= CPU_ARCH_ABI64;
#else
		cpu = CPU_TYPE_ANY;
#endif
		posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &copied);
		{
			char *dst = r_file_readlink (argv[0]);
			if (dst) {
				argv[0] = dst;
			}
		}
		ret = posix_spawnp (&p, argv[0], &fileActions, &attr, argv, NULL);
		switch (ret) {
		case 0:
			// eprintf ("Success\n");
			break;
		case 22:
			eprintf ("posix_spawnp: Invalid argument\n");
			break;
		case 86:
			eprintf ("Unsupported architecture\n");
			break;
		default:
			eprintf ("posix_spawnp: unknown error %d\n", ret);
			perror ("posix_spawnp");
			break;
		}
		posix_spawn_file_actions_destroy (&fileActions);
		r_str_argv_free (argv);
		free (_cmd);
		return p;
	}
#endif
	int ret, status, child_pid;

	child_pid = r_sys_fork ();
	switch (child_pid) {
	case -1:
		perror ("fork_and_ptraceme");
		break;
	case 0:
		if (runprofile) {
			char *expr = NULL;
			int i;
			RRunProfile *rp = r_run_new (NULL);
			argv = r_str_argv (cmd, NULL);
			for (i = 0; argv[i]; i++) {
				rp->_args[i] = argv[i];
			}
			rp->_args[i] = NULL;
			rp->_program = argv[0];
			rp->_dodebug = true;
			if (io->runprofile && *io->runprofile) {
				if (!r_run_parsefile (rp, io->runprofile)) {
					eprintf ("Can't find profile '%s'\n",
						io->runprofile);
					exit (MAGIC_EXIT);
				}
			}
			if (bits == 64)
				r_run_parseline (rp, expr=strdup ("bits=64"));
			else if (bits == 32)
				r_run_parseline (rp, expr=strdup ("bits=32"));
			free (expr);
			if (r_run_config_env (rp)) {
				eprintf ("Can't config the environment.\n");
				exit (1);
			}
			trace_me ();
			r_run_start (rp);
			r_run_free (rp);
			r_str_argv_free (argv);
			exit (1);
		} else {
			char *_cmd = io->args ?
				r_str_concatf (strdup (cmd), " %s", io->args) :
				strdup (cmd);

			trace_me ();
			argv = r_str_argv (_cmd, NULL);
			if (!argv) {
				free (_cmd);
				return -1;
			}
			if (argv && *argv) {
				int i;
				for (i = 3; i < 1024; i++)
					(void)close (i);
				execvp (argv[0], argv);
			} else {
				eprintf ("Invalid execvp\n");
			}
			r_str_argv_free (argv);
			free (_cmd);
		}
		perror ("fork_and_attach: execv");
		//printf(stderr, "[%d] %s execv failed.\n", getpid(), ps.filename);
		exit (MAGIC_EXIT); /* error */
		return 0; // invalid pid // if exit is overriden.. :)
	default:
		/* XXX: clean this dirty code */
		do {
			ret = wait (&status);
			if (ret == -1) return -1;
			if (ret != child_pid) {
				eprintf ("Wait event received by "
					"different pid %d\n", ret);
			}
		} while (ret != child_pid);
		if (WIFSTOPPED (status))
			eprintf ("Process with PID %d started...\n", (int)child_pid);
		if (WEXITSTATUS (status) == MAGIC_EXIT)
			child_pid = -1;
		// XXX kill (pid, SIGSTOP);
		break;
	}
	return child_pid;
}
Example #9
0
static int cmd_eval(void *data, const char *input) {
	char *p;
	RCore *core = (RCore *)data;
	switch (input[0]) {
	case 't': // env
		if (input[1] == 'a') {
			r_cons_printf ("%s\n", (r_num_rand (10) % 2)? "wen": "son");
		} else if (input[1]==' ' && input[2]) {
			RConfigNode *node = r_config_node_get (core->config, input+2);
			if (node) {
				const char *type = r_config_node_type (node);
				if (type && *type) {
					r_cons_println (type);
				}
			}
		} else {
			eprintf ("Usage: et [varname]  ; show type of eval var\n");
		}
		break;
	case 'n': // env
		if (!strchr (input, '=')) {
			char *var, *p;
			var = strchr (input, ' ');
			if (var) while (*var==' ') var++;
			p = r_sys_getenv (var);
			if (p) {
				r_cons_println (p);
				free (p);
			} else {
				char **e = r_sys_get_environ ();
				while (e && *e) {
					r_cons_println (*e);
					e++;
				}
			}
		} else if (strlen (input)>3) {
			char *v, *k = strdup (input+3);
			if (!k) break;
			v = strchr (k, '=');
			if (v) {
				*v++ = 0;
				r_sys_setenv (k, v);
			}
			free (k);
		}
		return true;
	case 'x': // exit
		// XXX we need headers for the cmd_xxx files.
		return cmd_quit (data, "");
	case 'j': // json
		r_config_list (core->config, NULL, 'j');
		break;
	case 'v': // verbose
		r_config_list (core->config, input + 1, 'v');
		break;
	case 'q': // quiet list of eval keys
		r_config_list (core->config, NULL, 'q');
		break;
	case '\0': // "e"
		r_config_list (core->config, NULL, 0);
		break;
	case 'c': // "ec"
		switch (input[1]) {
		case 'd':
			r_cons_pal_init (NULL);
			break;
		case '?': {
			const char *helpmsg[] = {
			"Usage ec[s?] [key][[=| ]fg] [bg]","","",
			"ec","","list all color keys",
			"ec*","","same as above, but using r2 commands",
			"ecd","","set default palette",
			"ecr","","set random palette (see also scr.randpal)",
			"ecs","","show a colorful palette",
			"ecj","","show palette in JSON",
			"ecc"," [prefix]","show palette in CSS",
			"eco"," dark|white","load white color scheme template",
			"ecp","","load previous color theme",
			"ecn","","load next color theme",
			"ecH","[?]","highlight word or instruction",
			"ec"," prompt red","change color of prompt",
			"ec"," prompt red blue","change color and background of prompt",
			""," ","",
			"colors:","","rgb:000, red, green, blue, ...",
			"e scr.rgbcolor","=1|0","for 256 color cube (boolean)",
			"e scr.truecolor","=1|0","for 256*256*256 colors (boolean)",
			"$DATADIR/radare2/cons","","~/.config/radare2/cons ./",
			NULL};
			r_core_cmd_help (core, helpmsg);
			}
			break;
		case 'o': // "eco"
			if (input[2] == 'j') {
				nextpal (core, 'j');
			} else if (input[2] == ' ') {
				bool failed = false;
				char *home, path[512];
				snprintf (path, sizeof (path), ".config/radare2/cons/%s", input + 3);
				home = r_str_home (path);
				snprintf (path, sizeof (path), R2_DATDIR"/radare2/"
					R2_VERSION"/cons/%s", input + 3);
				if (!load_theme (core, home)) {
					if (load_theme (core, path)) {
						//curtheme = r_str_dup (curtheme, path);
						curtheme = r_str_dup (curtheme, input + 3);
					} else {
						if (load_theme (core, input + 3)) {
							curtheme = r_str_dup (curtheme, input + 3);
						} else {
							char *absfile = r_file_abspath (input + 3);
							eprintf ("eco: cannot open colorscheme profile (%s)\n", absfile);
							free (absfile);
							failed = true;
						}
					}
				}
				free (home);
				if (failed) {
					eprintf ("Something went wrong\n");
				}
			} else if (input[2] == '?') {
				eprintf ("Usage: eco [themename]  ;load theme from "R2_DATDIR"/radare2/"R2_VERSION"/cons/\n");

			} else {
				nextpal (core, 'l');
			}
			break;
		case 's': r_cons_pal_show (); break; // "ecs"
		case '*': r_cons_pal_list (1, NULL); break; // "ec*"
		case 'h': // echo
			if (( p = strchr (input, ' ') )) {
				r_cons_strcat (p+1);
				r_cons_newline ();
			} else {
				// "ech"
				r_cons_pal_list ('h', NULL);
			}
			break;
		case 'j': // "ecj"
			r_cons_pal_list ('j', NULL);
			break;
		case 'c': // "ecc"
			r_cons_pal_list ('c', input + 2);
			break;
		case '\0': // "ec"
			r_cons_pal_list (0, NULL);
			break;
		case 'r': // "ecr"
			r_cons_pal_random ();
			break;
		case 'n': // "ecn"
			nextpal (core, 'n');
			break;
		case 'p': // "ecp"
			nextpal (core, 'p');
			break;
		case 'H': { // "ecH"
			char *color_code = NULL;
			char *word = NULL;
			int argc = 0;
			char** argv = r_str_argv (input + 4, &argc);
			switch (input[2]) {
			case '?': {
				const char *helpmsg[] = {
					"Usage ecH[iw-?]","","",
					"ecHi","[color]","highlight current instruction with 'color' background",
					"ecHw","[word] [color]","highlight 'word ' in current instruction with 'color' background",
					"ecH-","","remove all highlights on current instruction",
					NULL
				};
				r_core_cmd_help (core, helpmsg);
				}
				break;
			case '-':
				r_meta_set_string (core->anal, R_META_TYPE_HIGHLIGHT, core->offset, "");
				return false;
			case '\0':
			case 'i': // "ecHi
				if (argc) {
					char *dup = r_str_newf ("bgonly %s", argv[0]);
					color_code = r_cons_pal_parse (dup);
					R_FREE (dup);
				}
				break;
			case 'w': // "ecHw"
				if (!argc) {
					eprintf ("Usage: echw word [color]\n");
					r_str_argv_free (argv);
					return true;
				}
				word = strdup (argv[0]);
				if (argc > 1) {
					char *dup = r_str_newf ("bgonly %s", argv[1]);
					color_code = r_cons_pal_parse (dup);
					if (!color_code) {
						eprintf ("Unknown color %s\n", argv[1]);
						r_str_argv_free (argv);
						free (dup);
						free (word);
						return true;
					}
					R_FREE (dup);
				}
				break;
			default:
				eprintf ("See ecH?\n");
				r_str_argv_free (argv);
				return true;
			}
			char *str = r_meta_get_string (core->anal, R_META_TYPE_HIGHLIGHT, core->offset);
			char *dup = r_str_newf ("%s \"%s%s\"", str?str:"", word?word:"", color_code?color_code:r_cons_pal_get ("highlight"));
			r_meta_set_string (core->anal, R_META_TYPE_HIGHLIGHT, core->offset, dup);
			r_str_argv_free (argv);
			R_FREE (word);
			R_FREE (dup);
			break;
		}
		default: {
			char *p = strdup (input + 2);
			char *q = strchr (p, '=');
			if (!q) {
				q = strchr (p, ' ');
			}
			if (q) {
				// set
				*q++ = 0;
				r_cons_pal_set (p, q);
			} else {
				const char *k = r_cons_pal_get (p);
				if (k) {
					eprintf ("(%s)(%sCOLOR"Color_RESET")\n", p, k);
				}
			}
			free (p);
		}
		}
		break;
	case 'e':
		if (input[1] == ' ') {
			char *p;
			const char *val, *input2 = strchr (input+2, ' ');
			if (input2) input2++; else input2 = input+2;
			val = r_config_get (core->config, input2);
			p = r_core_editor (core, NULL, val);
			if (p) {
				r_str_replace_char (p, '\n', ';');
				r_config_set (core->config, input2, p);
			}
		} else {
			eprintf ("Usage: ee varname\n");
		}
		break;
	case '!':
		input = r_str_chop_ro (input+1);
		if (!r_config_toggle (core->config, input))
			eprintf ("r_config: '%s' is not a boolean variable.\n", input);
		break;
	case 's':
		r_config_list (core->config, (input[1])? input + 1: NULL, 's');
		break;
	case '-':
		r_core_config_init (core);
		//eprintf ("BUG: 'e-' command locks the eval hashtable. patches are welcome :)\n");
		break;
	case '*': r_config_list (core->config, NULL, 1); break;
	case '?':
		switch (input[1]) {
		case '?': r_config_list (core->config, input+2, 2); break;
		default: r_config_list (core->config, input+1, 2); break;
		case 0:
			r_core_cmd_help (core, help_msg_e);
		}
		break;
	case 'r':
		if (input[1]) {
			const char *key = input+((input[1]==' ')?2:1);
			if (!r_config_readonly (core->config, key)) {
				eprintf ("cannot find key '%s'\n", key);
			}
		} else {
			eprintf ("Usage: er [key]\n");
		}
		break;
	case ' ': r_config_eval (core->config, input+1); break;
	default: r_config_eval (core->config, input); break;
	}
	return 0;
}
Example #10
0
static int fork_and_ptraceme(int bits, const char *cmd) {
	char **argv;
	int ret, status, pid = fork ();
	switch (pid) {
	case -1:
		perror ("fork_and_ptraceme");
		break;
	case 0:
#if __APPLE__
		signal (SIGTRAP, SIG_IGN); //NEED BY STEP 
#endif
#if __APPLE__ || __BSD__
/* we can probably remove this #if..as long as PT_TRACE_ME is redefined for OSX in r_debug.h */
		signal (SIGABRT, inferior_abort_handler);
		if (ptrace (PT_TRACE_ME, 0, 0, 0) != 0) {
#else
		if (ptrace (PTRACE_TRACEME, 0, NULL, NULL) != 0) {
#endif
			eprintf ("ptrace-traceme failed\n");
			exit (MAGIC_EXIT);
		}
		// TODO: Add support to redirect filedescriptors
		// TODO: Configure process environment
		argv = r_str_argv (cmd, NULL);
#if __APPLE__ 
		#include <spawn.h>
		{
			posix_spawnattr_t attr = {0};
			size_t copied = 1;
			cpu_type_t cpu;
			int ret;
			pid_t p = -1;

			posix_spawnattr_init (&attr);
			posix_spawnattr_setflags (&attr, POSIX_SPAWN_SETEXEC);
#if __i386__ || __x86_64__
			cpu = CPU_TYPE_I386;
			if (bits == 64) 
				cpu |= CPU_ARCH_ABI64;
#else
			cpu = CPU_TYPE_ANY;
#endif
			posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &copied);

			//ret = posix_spawnp (NULL, argv[0], NULL, &attr, argv, NULL);
			ret = posix_spawnp (&p, argv[0], NULL, &attr, argv, NULL);
			switch (ret) {
			case 0:
				eprintf ("Success\n");
				break;
			case 22:
				eprintf ("posix_spawnp: Invalid argument\n");
				break;
			case 86:
				eprintf ("Unsupported architecture\n");
				break;
			default:
				eprintf ("posix_spawnp: unknown error %d\n", ret);
				perror ("posix_spawnp");
				break;
			}
/* only required if no SETEXEC called
			if (p != -1)
				wait (p);
*/
			exit (MAGIC_EXIT); /* error */
		}
#else
		execvp (argv[0], argv);
#endif
		r_str_argv_free (argv);

		perror ("fork_and_attach: execv");
		//printf(stderr, "[%d] %s execv failed.\n", getpid(), ps.filename);
		exit (MAGIC_EXIT); /* error */
		return 0; // invalid pid // if exit is overriden.. :)
	default:
		/* XXX: clean this dirty code */
                ret = wait (&status);
		if (ret != pid)
			eprintf ("Wait event received by different pid %d\n", ret);
                if (WIFSTOPPED (status))
                        eprintf ("Process with PID %d started...\n", (int)pid);
		if (WEXITSTATUS (status) == MAGIC_EXIT)
			pid = -1;
		// XXX kill (pid, SIGSTOP);
		break;
	}
	eprintf ("PID = %d\n", pid);
	return pid;
}
#endif

static int __plugin_open(RIO *io, const char *file) {
	if (!memcmp (file, "dbg://", 6) && file[6])
		return R_TRUE;
	return R_FALSE;
}

static RIODesc *__open(RIO *io, const char *file, int rw, int mode) {
	char uri[128];
	if (__plugin_open (io, file)) {
		int pid = atoi (file+6);
		if (pid == 0) {
			// TODO: get bits from ELF?
			pid = fork_and_ptraceme (io->bits, file+6);
			if (pid==-1)
				return NULL;
#if __WINDOWS__
			sprintf (uri, "w32dbg://%d", pid);
#elif __APPLE__
			sprintf (uri, "mach://%d", pid);
#else
			// TODO: use io_procpid here? faster or what?
			sprintf (uri, "ptrace://%d", pid);
#endif
			eprintf ("io_redirect: %s\n", uri);
			r_io_redirect (io, uri);
			return NULL;
		} else {
			sprintf (uri, "attach://%d", pid);
			r_io_redirect (io, uri);
			return NULL;
		}
	}
	r_io_redirect (io, NULL);
	return NULL;
}
Example #11
0
static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) {
#if __APPLE__ && !__POWERPC__
	return fork_and_ptraceme_for_mac(io, bits, cmd);
#else
	int ret, status, child_pid;
	bool runprofile = io->runprofile && *(io->runprofile);
	char **argv;
	child_pid = r_sys_fork ();
	switch (child_pid) {
	case -1:
		perror ("fork_and_ptraceme");
		break;
	case 0:
		if (runprofile) {
			argv = r_str_argv (cmd, NULL);
			if (!argv) {
				exit(1);
			}
			RRunProfile *rp = _get_run_profile (io, bits, argv);
			if (!rp) {
				r_str_argv_free (argv);
				exit (1);
			}
			trace_me ();
			r_run_start (rp);
			r_run_free (rp);
			r_str_argv_free (argv);
			exit (1);
		} else {
			char *_cmd = io->args ?
				r_str_appendf (strdup (cmd), " %s", io->args) :
				strdup (cmd);

			trace_me ();
			argv = r_str_argv (_cmd, NULL);
			if (!argv) {
				free (_cmd);
				return -1;
			}
			if (argv && *argv) {
				int i;
				for (i = 3; i < 1024; i++) {
					(void)close (i);
				}
				if (execvp (argv[0], argv) == -1) {
					eprintf ("Could not execvp: %s\n", strerror (errno));
					exit (MAGIC_EXIT);
				}
			} else {
				eprintf ("Invalid execvp\n");
			}
			r_str_argv_free (argv);
			free (_cmd);
		}
		perror ("fork_and_attach: execv");
		//printf(stderr, "[%d] %s execv failed.\n", getpid(), ps.filename);
		exit (MAGIC_EXIT); /* error */
		return 0; // invalid pid // if exit is overriden.. :)
	default:
		/* XXX: clean this dirty code */
		do {
			ret = wait (&status);
			if (ret == -1) return -1;
			if (ret != child_pid) {
				eprintf ("Wait event received by "
					"different pid %d\n", ret);
			}
		} while (ret != child_pid);
		if (WIFSTOPPED (status)) {
			eprintf ("Process with PID %d started...\n", (int)child_pid);
		}
		if (WEXITSTATUS (status) == MAGIC_EXIT) {
			child_pid = -1;
		}
		// XXX kill (pid, SIGSTOP);
		break;
	}
	return child_pid;
#endif
}