R_API int r_socket_spawn (RSocket *s, const char *cmd, unsigned int timeout) { // XXX TODO: dont use sockets, we can achieve the same with pipes const int port = 2000 + r_num_rand (2000); int childPid = r_sys_fork(); if (childPid == 0) { char *a = r_str_replace (strdup (cmd), "\\", "\\\\", true); r_sys_cmdf ("rarun2 system=\"%s\" listen=%d", a, port); free (a); #if 0 // TODO: use the api char *profile = r_str_newf ( "system=%s\n" "listen=%d\n", cmd, port); RRunProfile *rp = r_run_new (profile); r_run_start (rp); r_run_free (rp); free (profile); #endif eprintf ("r_socket_spawn: %s is dead\n", cmd); exit (0); } r_sys_sleep (1); r_sys_usleep (timeout); char aport[32]; sprintf (aport, "%d", port); // redirect stdin/stdout/stderr return r_socket_connect (s, "127.0.0.1", aport, R_SOCKET_PROTO_TCP, 2000); }
int main(int argc, char **argv) { char *file; RRunProfile *p; int i, ret; if (argc==1 || !strcmp (argv[1], "-h")) { eprintf ("Usage: rarun2 [-v] [script.rr2] [directive ..]\n"); printf ("%s", r_run_help ()); return 1; } if (!strcmp (argv[1], "-v")) { printf ("rarun2 "R2_VERSION"\n"); return 0; } file = argv[1]; if (*file && !strchr (file, '=')) { p = r_run_new (file); } else { p = r_run_new (NULL); for (i = *file?1:2; i<argc; i++) r_run_parseline (p, argv[i]); } if (!p) return 1; ret = r_run_start (p); r_run_free (p); return ret; }
static RRunProfile* _get_run_profile(RIO *io, int bits, char **argv) { char *expr = NULL; int i; RRunProfile *rp = r_run_new (NULL); if (!rp) { return NULL; } for (i = 0; argv[i]; i++) { rp->_args[i] = argv[i]; } rp->_args[i] = NULL; if (!argv[0]) { r_run_free (rp); return NULL; } rp->_program = strdup (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); r_run_free (rp); return NULL; } if (strstr (io->runprofile, R_SYS_DIR ".rarun2.")) { (void)r_file_rm (io->runprofile); } } 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"); r_run_free (rp); return NULL; } return rp; }
int main(int argc, char **argv) { char *file; RRunProfile *p; int i, ret; if (argc == 1 || !strcmp (argv[1], "-h")) { eprintf ("Usage: rarun2 [-v] [script.rr2] [directive ..]\n"); printf ("%s", r_run_help ()); return 1; } if (!strcmp (argv[1], "-v")) { printf ("rarun2 "R2_VERSION"\n"); return 0; } file = argv[1]; if (*file && !strchr (file, '=')) { p = r_run_new (file); } else { bool noMoreDirectives = false; int directiveIndex = 0; p = r_run_new (NULL); for (i = *file ? 1 : 2; i < argc; i++) { if (!strcmp (argv[i], "--")) { noMoreDirectives = true; continue; } if (noMoreDirectives) { const char *word = argv[i]; char *line = directiveIndex ? r_str_newf ("arg%d=%s", directiveIndex, word) : r_str_newf ("program=%s", word); r_run_parseline (p, line); directiveIndex ++; free (line); } else { r_run_parseline (p, argv[i]); } } } if (!p) return 1; ret = r_run_config_env (p); if (ret) { printf("error while configuring the environment.\n"); return 1; } ret = r_run_start (p); r_run_free (p); return ret; }
R_API bool r_socket_spawn(RSocket *s, const char *cmd, unsigned int timeout) { // XXX TODO: dont use sockets, we can achieve the same with pipes const int port = 2000 + r_num_rand (2000); int childPid = r_sys_fork (); if (childPid == 0) { char *a = r_str_replace (strdup (cmd), "\\", "\\\\", true); int res = r_sys_cmdf ("rarun2 system=\"%s\" listen=%d", a, port); free (a); #if 0 // TODO: use the api char *profile = r_str_newf ( "system=%s\n" "listen=%d\n", cmd, port); RRunProfile *rp = r_run_new (profile); r_run_start (rp); r_run_free (rp); free (profile); #endif if (res != 0) { eprintf ("r_socket_spawn: rarun2 failed\n"); exit (1); } eprintf ("r_socket_spawn: %s is dead\n", cmd); exit (0); } r_sys_sleep (1); r_sys_usleep (timeout); char aport[32]; sprintf (aport, "%d", port); // redirect stdin/stdout/stderr bool sock = r_socket_connect (s, "127.0.0.1", aport, R_SOCKET_PROTO_TCP, 2000); if (!sock) { return false; } #if __UNIX__ r_sys_sleep (4); r_sys_usleep (timeout); int status = 0; int ret = waitpid (childPid, &status, WNOHANG); if (ret != 0) { r_socket_close (s); return false; } #endif return true; }
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); } }
// __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 ? }
// __UNIX__ (not windows) static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) { char **argv; int ret, status, pid = r_sys_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 r_sys_perror ("ptrace-traceme"); exit (MAGIC_EXIT); } if (io->runprofile && *(io->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]; 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); r_run_start (rp); r_run_free (rp); // double free wtf // r_str_argv_free (argv); exit (1); } else { // TODO: Add support to redirect filedescriptors // TODO: Configure process environment char *_cmd = strdup (cmd); argv = r_str_argv (_cmd, NULL); if (!argv) { free (_cmd); return -1; } #if __APPLE__ { #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 ut32 ps_flags = POSIX_SPAWN_SETEXEC; posix_spawnattr_t attr = {0}; size_t copied = 1; cpu_type_t cpu; pid_t p = -1; int ret; int useASLR = 1; posix_spawnattr_init (&attr); if (useASLR != -1) { if (useASLR) { // enable aslr if not enabled? really? } else { ps_flags |= _POSIX_SPAWN_DISABLE_ASLR; } } (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); 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 if (argv && *argv) { execvp (argv[0], argv); } else { eprintf ("Invalid execvp\n"); } #endif 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 != pid) eprintf ("Wait event received by different pid %d\n", ret); } while (ret!=pid); 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, ut8 many) { if (!strncmp (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, 0)) { const char *pidfile = file + 6; char *endptr; int pid = (int)strtol (pidfile, &endptr, 10); if (endptr == pidfile || pid < 0) pid = -1; if (pid == -1) { pid = fork_and_ptraceme (io, 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 my_io_redirect (io, file, uri); } else { sprintf (uri, "attach://%d", pid); my_io_redirect (io, file, uri); } return NULL; } my_io_redirect (io, file, NULL); return NULL; }
// __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; }
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); } } void handle_posix_error(int err) { switch (err) { case 0: // eprintf ("Success\n"); break; case 22: eprintf ("posix_spawnp: Invalid argument\n"); break; case 86: eprintf ("Unsupported architecture. Please specify -b 32\n"); break; default: eprintf ("posix_spawnp: unknown error %d\n", err); perror ("posix_spawnp"); break; } } static RRunProfile* _get_run_profile(RIO *io, int bits, char **argv) { char *expr = NULL; int i; RRunProfile *rp = r_run_new (NULL); if (!rp) { return NULL; } for (i = 0; argv[i]; i++) { rp->_args[i] = argv[i]; } rp->_args[i] = NULL; rp->_program = strdup (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); r_run_free (rp); return NULL; } if (strstr (io->runprofile, R_SYS_DIR ".rarun2.")) { (void)r_file_rm (io->runprofile); } } 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"); r_run_free (rp); return NULL; } return rp; }
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; }
// __UNIX__ (not windows) static int fork_and_ptraceme(RIO *io, 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 r_sys_perror ("ptrace-traceme"); exit (MAGIC_EXIT); } { 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]; 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); r_run_start (rp); r_run_free (rp); // double free wtf // r_str_argv_free (argv); exit (1); } 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, ut8 many) { if (!strncmp (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, 0)) { int pid = atoi (file+6); if (pid == 0) { pid = fork_and_ptraceme (io, 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 my_io_redirect (io, uri); } else { sprintf (uri, "attach://%d", pid); my_io_redirect (io, uri); } return NULL; } my_io_redirect (io, NULL); return NULL; }
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 }