static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) { if (__plugin_open (io, pathname, 0)) { const char *hostport = pathname + 6; RIOKdp *mal = R_NEW (RIOKdp); mal->fd = -2; /* causes r_io_desc_new() to set the correct fd */ eprintf ("HOST:PORT = %s", hostport); //mal->sock = r_socket_new(); mal->size = strlen (pathname); mal->buf = malloc (mal->size+1); mal->offset = 0; memset (mal->buf, 0, mal->size); mal->size = r_hex_str2bin (hostport, mal->buf); if ((int)mal->size<1) { free (mal->buf); mal->buf = NULL; } if (mal->buf != NULL) { RETURN_IO_DESC_NEW (&r_io_plugin_kdp, mal->fd, pathname, rw, mode,mal); } eprintf ("Cannot connect to %s\n", hostport); free (mal); } return NULL; }
static RIODesc *__open(struct r_io_t *io, const char *file, int rw, int mode) { RIOMach *riom; int pid; task_t task; if (!__plugin_open (io, file)) return NULL; pid = atoi (file+(file[0]=='a'?9:7)); if (pid<1) return NULL; task = debug_attach (pid); if ((int)task == -1) { switch (errno) { case EPERM: eprintf ("Operation not permitted\n"); break; case EINVAL: perror ("ptrace: Cannot attach"); eprintf ("ERRNO: %d (EINVAL)\n", errno); break; default: eprintf ("unknown error in debug_attach\n"); break; } return NULL; } riom = R_NEW (RIOMach); riom->pid = pid; riom->task = task; return r_io_desc_new (&r_io_plugin_mach, riom->pid, file, 1, mode, riom); }
static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) { if (__plugin_open (io, pathname,0)) { RIOSparse *mal = R_NEW0 (RIOSparse); mal->fd = -2; /* causes r_io_desc_new() to set the correct fd */ int size = (int)r_num_math (NULL, pathname+9); mal->buf = r_buf_new_sparse (); if (size>0) { ut8 *data = malloc (size); if (!data) { eprintf ("Cannot allocate (%s) %d bytes\n", pathname+9, size); mal->offset = 0; } else { memset (data, 0x00, size); r_buf_write_at (mal->buf, 0, data, size); free (data); } } if (mal->buf) { RETURN_IO_DESC_NEW (&r_io_plugin_sparse, mal->fd, pathname, rw, mode, mal); } r_buf_free (mal->buf); free (mal); } return NULL; }
static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) { if (__plugin_open (io, pathname,0)) { RIOMalloc *mal = R_NEW (RIOMalloc); mal->fd = -2; /* causes r_io_desc_new() to set the correct fd */ if (!strncmp (pathname, "hex://", 6)) { mal->size = strlen (pathname); mal->buf = malloc (mal->size+1); mal->offset = 0; memset (mal->buf, 0, mal->size); mal->size = r_hex_str2bin (pathname+6, mal->buf); if ((int)mal->size<1) { free (mal->buf); mal->buf = NULL; } } else { mal->size = r_num_math (NULL, pathname+9); if (((int)mal->size) <= 0) { free (mal); eprintf ("Cannot allocate (%s) 0 bytes\n", pathname+9); return NULL; } mal->offset = 0; mal->buf = calloc (1, mal->size+1); } if (mal->buf != NULL) { RETURN_IO_DESC_NEW (&r_io_plugin_malloc, mal->fd, pathname, rw, mode,mal); } eprintf ("Cannot allocate (%s) %d bytes\n", pathname+9, mal->size); free (mal); } return NULL; }
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; }
static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) { char *out; int rlen, code; if (__plugin_open (io, pathname, 0)) { RIOR2Web *mal = R_NEW0 (RIOR2Web); if (!mal) return NULL; char *url = r_str_newf ("http://%s/?V", pathname+8); //eprintf ("URL:(%s)\n", url); out = r_socket_http_get (url, &code, &rlen); //eprintf ("RES %d %d\n", code, rlen); //eprintf ("OUT(%s)\n", out); if (out && rlen>0) { mal->fd = getmalfd (mal); mal->url = r_str_newf ("http://%s", pathname+8); free (out); free (url); return r_io_desc_new (&r_io_plugin_r2web, mal->fd, pathname, rw, mode, mal); } free (url); free (mal); free (out); } return NULL; }
static RIODesc *__open(RIO *io, const char *file, int rw, int mode) { void *io_ctx; WindCtx *ctx; if (!__plugin_open (io, file, 0)) return NULL; if (!iob_select ("pipe")) { eprintf("Could not initialize the IO backend\n"); return NULL; } io_ctx = iob_open (file + 9); if (!io_ctx) { eprintf ("Could not open the pipe\n"); return NULL; } ctx = wind_ctx_new (io_ctx); if (!ctx) return NULL; return r_io_desc_new (&r_io_plugin_windbg, -1, file, R_TRUE, mode, ctx); }
static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) { if (__plugin_open (io, pathname,0)) { RIOSparse *mal = R_NEW0 (RIOSparse); int size = (int)r_num_math (NULL, pathname + 9); mal->buf = r_buf_new_sparse (io->Oxff); if (!mal->buf) { free (mal); return NULL; } if (size > 0) { ut8 *data = malloc (size); if (!data) { eprintf ("Cannot allocate (%s) %d byte(s)\n", pathname+9, size); mal->offset = 0; } else { memset (data, 0x00, size); r_buf_write_at (mal->buf, 0, data, size); free (data); } } if (mal->buf) { return r_io_desc_new (io, &r_io_plugin_sparse, pathname, rw, mode, mal); } r_buf_free (mal->buf); free (mal); } return NULL; }
static RIODesc *__open(struct r_io_t *io, const char *pathname, int rw, int mode) { if (__plugin_open (io, pathname)) { RIOMalloc *mal = R_NEW (RIOMalloc); mal->fd = -2; /* causes r_io_desc_new() to set the correct fd */ if (!memcmp (pathname, "hex://", 6)) { mal->size = strlen (pathname); mal->buf = malloc (mal->size); memset (mal->buf, 0, mal->size); mal->size = r_hex_str2bin (pathname+6, mal->buf); } else { mal->size = r_num_math (NULL, pathname+9); if ((mal->size)>0) { mal->buf = malloc (mal->size); memset (mal->buf, '\0', mal->size); } else { eprintf ("Cannot allocate (%s) 0 bytes\n", pathname+9); return NULL; } } if (mal->buf != NULL) { RETURN_IO_DESC_NEW(&r_io_plugin_malloc, mal->fd, pathname, rw, mode,mal); //return r_io_desc_new (&r_io_plugin_malloc, mal->fd, pathname, rw, mode, mal); } eprintf ("Cannot allocate (%s) %d bytes\n", pathname+9, mal->size); free (mal); } return NULL; }
static RIODesc *__open(RIO *io, const char *file, int rw, int mode) { char host[128], *port, *p; if (!__plugin_open (io, file, 0)) return NULL; RIOGdb *riog; strncpy (host, file+6, sizeof (host)-1); port = strchr (host , ':'); if (!port) { eprintf ("Port not specified. Please use gdb://[host]:[port]\n"); return NULL; } *port = '\0'; port++; p = strchr (port, '/'); if (p) *p=0; if (r_sandbox_enable (0)) { eprintf ("sandbox: Cannot use network\n"); return NULL; } riog = R_NEW (RIOGdb); gdbr_init(&riog->desc); int i_port = atoi(port); if (gdbr_connect(&riog->desc, host, i_port) == 0) { desc = &riog->desc; return r_io_desc_new (&r_io_plugin_gdb, riog->desc.fd, file, rw, mode, riog); } eprintf ("gdb.io.open: Cannot connect to host.\n"); free (riog); return NULL; }
static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) { char *out; int rlen, code; if (__plugin_open (io, pathname, 0)) { out = r_socket_http_get (pathname, &code, &rlen); if (out && rlen>0) { RIOMalloc *mal = R_NEW0 (RIOMalloc); if (!mal) return NULL; mal->size = rlen; mal->buf = malloc (mal->size+1); if (!mal->buf) { free (mal); return NULL; } if (mal->buf != NULL) { mal->fd = getmalfd (mal); memcpy (mal->buf, out, mal->size); free (out); return r_io_desc_new (io, &r_io_plugin_http, pathname, rw, mode, mal); } eprintf ("Cannot allocate (%s) %d bytes\n", pathname+9, mal->size); free (mal); } free (out); } return NULL; }
static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) { char *out; int rlen; if (__plugin_open (io, pathname, 0)) { RIOBind iob; RIOBfdbg *mal = R_NEW0 (RIOBfdbg); r_io_bind (io, &iob); mal->fd = getmalfd (mal); mal->bfvm = bfvm_new (&iob); out = r_file_slurp (pathname+8, &rlen); if (!out || rlen < 1) { free (mal); free (out); return NULL; } mal->size = rlen; mal->buf = malloc (mal->size+1); if (mal->buf != NULL) { memcpy (mal->buf, out, rlen); free (out); return r_io_desc_new (&r_io_plugin_bfdbg, mal->fd, pathname, rw, mode, mal); } eprintf ("Cannot allocate (%s) %d bytes\n", pathname+9, mal->size); free (mal); free (out); } return NULL; }
static RIODesc *__open(struct r_io_t *io, const char *file, int rw, int mode) { int ret = -1; if (__plugin_open (io, file)) { int pid = atoi (file+9); ret = ptrace (PTRACE_ATTACH, pid, 0, 0); if (file[0]=='p') //ptrace ret = 0; else if (ret == -1) { #ifdef __ANDROID__ eprintf ("ptrace_attach: Operation not permitted\n"); #else switch (errno) { case EPERM: ret = pid; eprintf ("ptrace_attach: Operation not permitted\n"); break; case EINVAL: perror ("ptrace: Cannot attach"); eprintf ("ERRNO: %d (EINVAL)\n", errno); break; } #endif } else if (__waitpid (pid)) ret = pid; else eprintf ("Error in waitpid\n"); if (ret != -1) { RIOPtrace *riop = R_NEW (RIOPtrace); riop->pid = riop->tid = pid; return r_io_desc_new (&r_io_plugin_ptrace, -1, file, R_TRUE, 0, riop); } } return NULL; }
static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) { R2Pipe *r2p = NULL; if (__plugin_open (io, pathname, 0)) { r2p = r2p_open (pathname+9); } return r2p? r_io_desc_new (&r_io_plugin_r2pipe, r2p->child, pathname, rw, mode, r2p): NULL; }
static RIODesc* __open(RIO* io, const char* pathname, int rw, int mode) { RIONull* null; if (__plugin_open (io, pathname,0)) { if (!strncmp (pathname, "null://", 7) && strlen (pathname + 7)) { null = R_NEW0 (RIONull); null->size = r_num_math (NULL, pathname + 7) + 1; //??? null->offset = 0LL; return r_io_desc_new (io, &r_io_plugin_null, pathname, rw, mode, null); } } return NULL; }
static RIODesc *__open(RIO *io, const char *file, int rw, int mode) { RIODesc *ret = NULL; RIOMach *riom; const char *pidfile; char *pidpath, *endptr; int pid; task_t task; if (!__plugin_open (io, file, 0)) { return NULL; } pidfile = file + (file[0] == 'a' ? 9 : 7); pid = (int)strtol (pidfile, &endptr, 10); if (endptr == pidfile || pid < 0) { return NULL; } task = pid_to_task (pid); if (task == -1) { return NULL; } if (!task) { if (pid > 0 && io->referer && !strncmp (io->referer, "dbg://", 6)) { eprintf ("Child killed\n"); kill (pid, 9); } switch (errno) { case EPERM: eprintf ("Operation not permitted\n"); break; case EINVAL: perror ("ptrace: Cannot attach"); eprintf ("Possibly unsigned r2. Please see doc/osx.md\n"); eprintf ("ERRNO: %d (EINVAL)\n", errno); break; default: eprintf ("unknown error in debug_attach\n"); break; } return NULL; } riom = R_NEW0 (RIOMach); riom->pid = pid; riom->task = task; // sleep 1s to get proper path (program name instead of ls) (racy) pidpath = pid ? r_sys_pid_to_path (pid) : strdup ("kernel"); ret = r_io_desc_new (&r_io_plugin_mach, riom->pid, pidpath, rw | R_IO_EXEC, mode, riom); free (pidpath); return ret; }
static RIODesc *__open(struct r_io_t *io, const char *file, int rw, int mode) { if (__plugin_open (io, file, 0)) { char *pidpath; RIOW32Dbg *dbg = R_NEW (RIOW32Dbg); if (dbg == NULL) return NULL; dbg->pid = atoi (file+9); if (__attach (dbg) == -1) { free (dbg); return NULL; } pidpath = r_sys_pid_to_path (dbg->pid); RETURN_IO_DESC_NEW (&r_io_plugin_w32dbg, -1, pidpath, rw | R_IO_EXEC, mode, dbg); } return NULL; }
static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) { if (__plugin_open (io, pathname, 0)) { RIOGzip *mal = R_NEW0 (RIOGzip); if (!mal) return NULL; int len; ut8 *data = (ut8*)r_file_slurp (pathname+7, &len); mal->buf = r_inflate (data, len, NULL, &mal->size); if (mal->buf) { RETURN_IO_DESC_NEW (&r_io_plugin_malloc, mal->fd, pathname, rw, mode, mal); } free (data); eprintf ("Cannot allocate (%s) %d bytes\n", pathname+9, mal->size); free (mal); } return NULL; }
static RIODesc *__open(RIO *io, const char *file, int rw, int mode) { RIODesc *ret = NULL; RIOMach *riom; const char *pidfile; char *pidpath; int pid; task_t task; if (!__plugin_open (io, file, 0)) return NULL; pidfile = file+(file[0]=='a'?9:7); if (!strcmp (pidfile, "0")) { /* tfp0 */ pid = 0; } else { pid = atoi (pidfile); if (pid<1) return NULL; } task = debug_attach (pid); if ((int)task == -1) { switch (errno) { case EPERM: eprintf ("Operation not permitted\n"); break; case EINVAL: perror ("ptrace: Cannot attach"); eprintf ("ERRNO: %d (EINVAL)\n", errno); break; default: eprintf ("unknown error in debug_attach\n"); break; } return NULL; } riom = R_NEW0 (RIOMach); riom->pid = pid; riom->task = task; // sleep 1s to get proper path (program name instead of ls) (racy) pidpath = r_sys_pid_to_path (pid); ret = r_io_desc_new (&r_io_plugin_mach, riom->pid, pidpath, rw | R_IO_EXEC, mode, riom); free (pidpath); return ret; }
static RIODesc *__open(RIO *io, const char *file, int rw, int mode) { char host[128], *port, *p; RSocket *_fd; RIOGdb *riog; if (!__plugin_open (io, file, 0)) return NULL; strncpy (host, file+6, sizeof (host)-1); port = strchr (host , ':'); if (!port) { eprintf ("Port not specified. Please use gdb://[host]:[port]\n"); return NULL; } *port = '\0'; port++; p = strchr (port, '/'); if (p) *p=0; if (r_sandbox_enable (0)) { eprintf ("sandbox: Cannot use network\n"); return NULL; } _fd = r_socket_new (R_FALSE); if (_fd && r_socket_connect_tcp (_fd, host, port, 3)) { riog = R_NEW (RIOGdb); riog->fd = _fd; riog->desc = gdbwrap_init (_fd->fd, NUM_REGS, 4); if (!riog->desc) { r_socket_free (_fd); free (riog); return NULL; } #if __WINDOWS__ // XXX: bypass lazylinking RETURN_IO_DESC_NEW (&r_io_plugin_gdb, _fd->fd, file, rw, mode, riog); #else return r_io_desc_new (&r_io_plugin_gdb, _fd->fd, file, rw, mode, riog); #endif } eprintf ("gdb.io.open: Cannot connect to host.\n"); return NULL; }
static RIODesc *__open(RIO *io, const char *file, int rw, int mode) { if (__plugin_open (io, file, 0)) { char *pidpath; RIODesc *ret; RIOW32Dbg *dbg = R_NEW0 (RIOW32Dbg); if (!dbg) { return NULL; } dbg->pid = atoi (file + 9); if (__open_proc (dbg, !strncmp (file, "attach://", 9)) == -1) { free (dbg); return NULL; } pidpath = r_sys_pid_to_path (dbg->pid); ret = r_io_desc_new (io, &r_io_plugin_w32dbg, file, rw | R_PERM_X, mode, dbg); ret->name = pidpath; return ret; } return NULL; }
static RIODesc *__open(struct r_io_t *io, const char *file, int rw, int mode) { char procpidpath[64]; int fd, ret = -1; if (__plugin_open (io, file,0)) { int pid = atoi (file+10); if (file[0]=='a') { ret = ptrace (PTRACE_ATTACH, pid, 0, 0); if (ret == -1) { switch (errno) { case EPERM: ret = pid; eprintf ("Operation not permitted\n"); break; case EINVAL: perror ("ptrace: Cannot attach"); eprintf ("ERRNO: %d (EINVAL)\n", errno); break; } } else if (__waitpid(pid)) ret = pid; else eprintf ("Error in waitpid\n"); } else ret = pid; fd = ret;//TODO: use r_io_fd api snprintf (procpidpath, sizeof (procpidpath), "/proc/%d/mem", pid); fd = open (procpidpath, O_RDWR); if (fd != -1) { RIOProcpid *riop = R_NEW (RIOProcpid); riop->pid = pid; riop->fd = fd; return r_io_desc_new (&r_io_plugin_procpid, -1, file, R_TRUE, 0, riop); } /* kill children */ eprintf ("Cannot open /proc/%d/mem of already attached process\n", pid); ptrace (PTRACE_DETACH, pid, 0, 0); } return NULL; }
static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) { if (__plugin_open (io, pathname, 0)) { if (gs) { return NULL; } gs = r_socket_new (0); char *cmd = r_str_newf ("winedbg '%s'", pathname + 10); int res = r_socket_spawn (gs, cmd, 1000); free (cmd); if (!res) { return NULL; } char *reply = runcmd (NULL); if (reply) { int rw = 7; free (reply); eprintf ("Wine-dbg is ready to go!\n"); return r_io_desc_new (io, &r_io_plugin_winedbg, pathname, rw, mode, gs); } eprintf ("Can't find the Wine-dbg prompt\n"); } return NULL; }
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; }
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; }
static RIODesc *__open(RIO *io, const char *file, int rw, int mode) { RIODesc *ret = NULL; RIOMach *riom = NULL; const char *pidfile; char *pidpath, *endptr; int pid; task_t task; if (!__plugin_open (io, file, false) && !__plugin_open (io, (const char *)&file[1], false)) { return NULL; } pidfile = file + (file[0] == 'a' ? 9 : (file[0] == 's' ? 8 : 7)); pid = (int)strtol (pidfile, &endptr, 10); if (endptr == pidfile || pid < 0) { return NULL; } task = pid_to_task (NULL, pid); if (task == -1) { return NULL; } if (!task) { if (pid > 0 && !strncmp (file, "smach://", 8)) { kill (pid, SIGKILL); eprintf ("Child killed\n"); } #if 0 /* this is broken, referer gets set in the riodesc after this function returns the riodesc * the pid > 0 check doesn't seem to be reasonable to me too * what was this intended to check anyway ? */ if (pid > 0 && io->referer && !strncmp (io->referer, "dbg://", 6)) { eprintf ("Child killed\n"); kill (pid, SIGKILL); } #endif switch (errno) { case EPERM: eprintf ("Operation not permitted\n"); break; case EINVAL: perror ("ptrace: Cannot attach"); eprintf ("Possibly unsigned r2. Please see doc/macos.md\n"); eprintf ("ERRNO: %d (EINVAL)\n", errno); break; default: eprintf ("unknown error in debug_attach\n"); break; } return NULL; } RIODescData *iodd = R_NEW0 (RIODescData); if (iodd) { iodd->pid = pid; iodd->tid = pid; iodd->data = NULL; } riom = R_NEW0 (RIOMach); if (!riom) { return NULL; } riom->task = task; iodd->magic = r_str_hash ("mach"); iodd->data = riom; // sleep 1s to get proper path (program name instead of ls) (racy) pidpath = pid ? r_sys_pid_to_path (pid) : strdup ("kernel"); if (!strncmp (file, "smach://", 8)) { ret = r_io_desc_new (io, &r_io_plugin_mach, &file[1], rw | R_PERM_X, mode, iodd); } else { ret = r_io_desc_new (io, &r_io_plugin_mach, file, rw | R_PERM_X, mode, iodd); } ret->name = pidpath; return ret; }
// __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; }
// __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; }