static int rabin_extract(int all) { char outfile[512], outpath[512], *path, *ptr; int i = 0; if (all) { for (i=0; i<bin->narch; i++) { const char *arch; int bits; r_bin_select_idx (bin, i); if (bin->cur.o->info == NULL) { arch = "unknown"; bits = 0; // eprintf ("No extract info found.\n"); // continue; } else { arch = bin->cur.o->info->arch; bits = bin->cur.o->info->bits; } path = strdup (bin->cur.file); // XXX: Wrong for w32 (/) if ((ptr = strrchr (path, '/'))) { *ptr = '\0'; ptr++; } else ptr = bin->cur.file; /* if (output) snprintf (outpath, sizeof (outpath), "%s/%s", output, path); else snprintf (outpath, sizeof (outpath), "./%s", path); */ snprintf (outpath, sizeof (outpath), "%s.fat", ptr); if (!r_sys_rmkdir (outpath)) { eprintf ("Error creating dir structure\n"); return R_FALSE; } snprintf (outfile, sizeof (outfile), "%s/%s.%s_%i.%d", outpath, ptr, arch, bits, i); if (!r_file_dump (outfile, bin->cur.buf->buf, bin->cur.size)) { eprintf ("Error extracting %s\n", outfile); return R_FALSE; } else printf ("%s created (%i)\n", outfile, bin->cur.size); } } else { /* XXX: Use 'output' for filename? */ if (bin->cur.o->info == NULL) { eprintf ("No extract info found.\n"); } else { if ((ptr = strrchr (bin->cur.file, '/'))) ptr++; else ptr = bin->cur.file; snprintf (outfile, sizeof (outfile), "%s.%s_%i", ptr, bin->cur.o->info->arch, bin->cur.o->info->bits); if (!r_file_dump (outfile, bin->cur.buf->buf, bin->cur.size)) { eprintf ("Error extracting %s\n", outfile); return R_FALSE; } else printf ("%s created (%i)\n", outfile, bin->cur.size); } } return R_TRUE; }
// XXX: temporary files are R_API int r_diff_buffers_unified(RDiff *d, const ut8 *a, int la, const ut8 *b, int lb) { if (r_mem_is_printable (a, R_MIN (5, la))) { r_file_dump (".a", a, la, 0); r_file_dump (".b", b, lb, 0); } else { r_file_hexdump (".a", a, la, 0); r_file_hexdump (".b", b, lb, 0); } r_sys_cmd ("diff -ru .a .b"); r_file_rm (".a"); r_file_rm (".b"); return 0; }
static bool r_egg_Cfile_parseCompiled(const char *file) { char *fileExt = r_str_newf ("%s.tmp", file); char *buffer = r_file_slurp (fileExt, NULL); buffer = r_str_replace (buffer, "rdata", "text", false); buffer = r_str_replace (buffer, "rodata", "text", false); buffer = r_str_replace (buffer, "get_pc_thunk.bx", "__getesp__", true); const char *words[] = {".cstring", "size", "___main", "section", "__alloca", "zero", "cfi"}; size_t i; for (i = 0; i < 7; i++) { r_str_stripLine (buffer, words[i]); } free (fileExt); fileExt = r_str_newf ("%s.s", file); if (!r_file_dump (fileExt, (const ut8*) buffer, strlen (buffer), true)) { eprintf ("Error while opening %s.s\n", file); goto fail; } free (buffer); free (fileExt); return true; fail: free (buffer); free (fileExt); return false; }
static int rabin_dump_sections(char *scnname) { RList *sections; RListIter *iter; RBinSection *section; ut8 *buf; char *ret; if ((sections = r_bin_get_sections (bin)) == NULL) return R_FALSE; r_list_foreach (sections, iter, section) { if (!strcmp (scnname, section->name)) { if (!(buf = malloc (section->size))) return R_FALSE; if (!(ret = malloc (section->size*2+1))) { free (buf); return R_FALSE; } r_buf_read_at (bin->cur->buf, section->paddr, buf, section->size); if (output) { r_file_dump (output, buf, section->size); } else { r_hex_bin2str (buf, section->size, ret); printf ("%s\n", ret); } free (buf); free (ret); break; } } return R_TRUE; }
R_API int r_bin_wr_output(RBin *bin, const char *filename) { RBinFile *binfile = r_bin_cur (bin); if (!binfile || !binfile->buf) return R_FALSE; return r_file_dump (filename, binfile->buf->buf, binfile->buf->length); }
static void filesave () { char buf[128]; int i; if (!path) { eprintf ("File: "); buf[0] = 0; fgets (buf, sizeof(buf), stdin); i = strlen (buf); if (i>0) { buf[i-1] = 0; free (path); path = strdup (buf); } } if (lines) { for (i=0; i<bytes; i++) { if (lines[i]=='\0') lines[i]='\n'; } } r_file_dump (path, (const ut8*)lines, bytes); eprintf ("File '%s' saved (%d bytes)\n", path, bytes); // restore back zeroes nlines = r_str_split (lines, '\n'); }
// XXX: temporary files are R_API char *r_diff_buffers_unified(RDiff *d, const ut8 *a, int la, const ut8 *b, int lb) { r_file_dump (".a", a, la, 0); r_file_dump (".b", b, lb, 0); #if 0 if (r_mem_is_printable (a, R_MIN (5, la))) { r_file_dump (".a", a, la, 0); r_file_dump (".b", b, lb, 0); } else { r_file_hexdump (".a", a, la, 0); r_file_hexdump (".b", b, lb, 0); } #endif char* err = NULL; char* out = NULL; int out_len; (void)r_sys_cmd_str_full ("/usr/bin/diff -u .a .b", NULL, &out, &out_len, &err); r_file_rm (".a"); r_file_rm (".b"); free (err); return out; }
int main () { #define _BUFFER_SIZE 64 unsigned char code[64] = { 0x31, 0xc0, 0x40, 0x68, 0x2a, 0x00, 0x00, 0x00, 0x81, 0xec, 0x04, 0x00, 0x00, 0x00, 0xcd, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; RBuffer *b; RBin *bin = r_bin_new (); if (!r_bin_use_arch (bin, "x86", 32, "mach0")) { eprintf ("Cannot set arch\n"); return 1; } b = r_bin_create (bin, code, _BUFFER_SIZE, NULL, 0); if (b) { if (r_file_dump ("a.out", b->buf, b->length)) eprintf ("dumped %d bytes in a.out\n", b->length); else eprintf ("error dumping into a.out\n"); } else eprintf ("So f*****g oops\n"); r_bin_free (bin); r_buf_free (b); return 0; }
R_API int r_run_start(RRunProfile *p) { #if __APPLE__ posix_spawnattr_t attr = {0}; pid_t pid = -1; #endif int ret; if (!p->_program && !p->_system) { printf ("No program or system rule defined\n"); return 1; } if (p->_stdin) { int f = open (p->_stdin, O_RDONLY); if (f < 0) return 1; close (0); dup2 (f, 0); } if (p->_stdout) { int f = open (p->_stdout, O_WRONLY); if (f < 0) return 1; close (1); dup2 (f, 1); } if (p->_stderr) { int f = open (p->_stderr, O_WRONLY); if (f < 0) return 1; close (2); dup2 (f, 2); } if (p->_aslr != -1) setASLR (p->_aslr); #if __UNIX__ set_limit (p->_docore, RLIMIT_CORE, RLIM_INFINITY); if (p->_maxfd) set_limit (p->_maxfd, RLIMIT_NOFILE, p->_maxfd); #ifdef RLIMIT_NPROC if (p->_maxproc) set_limit (p->_maxproc, RLIMIT_NPROC, p->_maxproc); #endif if (p->_maxstack) set_limit (p->_maxstack, RLIMIT_STACK, p->_maxstack); #else if (p->_docore || p->_maxfd || p->_maxproc || p->_maxstack) eprintf ("Warning: setrlimits not supported for this platform\n"); #endif if (p->_connect) { char *q = strchr (p->_connect, ':'); if (q) { RSocket *fd = r_socket_new (0); *q = 0; if (!r_socket_connect_tcp (fd, p->_connect, q+1, 30)) { eprintf ("Cannot connect\n"); return 1; } eprintf ("connected\n"); close (0); close (1); close (2); dup2 (fd->fd, 0); dup2 (fd->fd, 1); dup2 (fd->fd, 2); } else { eprintf ("Invalid format for connect. missing ':'\n"); return 1; } } if (p->_listen) { RSocket *child, *fd = r_socket_new (0); if (!r_socket_listen (fd, p->_listen, NULL)) { eprintf ("rarun2: cannot listen\n"); r_socket_free (fd); return 1; } child = r_socket_accept (fd); if (child) { eprintf ("connected\n"); close (0); close (1); close (2); dup2 (child->fd, 0); dup2 (child->fd, 1); dup2 (child->fd, 2); } } if (p->_r2sleep != 0) { r_sys_sleep (p->_r2sleep); } if (p->_chgdir) { ret = chdir (p->_chgdir); if (ret < 0) return 1; } if (p->_chroot) { ret = chdir (p->_chroot); if (ret < 0) return 1; } #if __UNIX__ if (p->_chroot) { if (chroot (p->_chroot)) { eprintf ("rarun2: cannot chroot\n"); return 1; } chdir("/"); } if (p->_setuid) { ret = setgroups(0, NULL); if (ret < 0) return 1; ret = setuid (atoi (p->_setuid)); if (ret < 0) return 1; } if (p->_seteuid) { ret = seteuid (atoi (p->_seteuid)); if (ret < 0) return 1; } if (p->_setgid) { ret = setgid (atoi (p->_setgid)); if (ret < 0) return 1; } if (p->_input) { int f2[2]; pipe (f2); close (0); dup2 (f2[0], 0); parseinput (p->_input); write (f2[1], p->_input, strlen (p->_input)); } #endif if (p->_r2preload) { if (p->_preload) { eprintf ("WARNING: Only one library can be opened at a time\n"); } p->_preload = R2_LIBDIR"/libr2."R_LIB_EXT; } if (p->_libpath) { #if __WINDOWS__ eprintf ("rarun2: libpath unsupported for this platform\n"); #elif __HAIKU__ r_sys_setenv ("LIBRARY_PATH", p->_libpath); #elif __APPLE__ r_sys_setenv ("DYLD_LIBRARY_PATH", p->_libpath); #else r_sys_setenv ("LD_LIBRARY_PATH", p->_libpath); #endif } if (p->_preload) { #if __APPLE__ // 10.6 r_sys_setenv ("DYLD_PRELOAD", p->_preload); r_sys_setenv ("DYLD_INSERT_LIBRARIES", p->_preload); // 10.8 r_sys_setenv ("DYLD_FORCE_FLAT_NAMESPACE", "1"); #else r_sys_setenv ("LD_PRELOAD", p->_preload); #endif } if (p->_timeout) { #if __UNIX__ int mypid = getpid (); if (!fork ()) { sleep (p->_timeout); if (!kill (mypid, 0)) eprintf ("\nrarun2: Interrupted by timeout\n"); kill (mypid, SIGKILL); exit (0); } #else eprintf ("timeout not supported for this platform\n"); #endif } #if __APPLE__ posix_spawnattr_init (&attr); if (p->_args[0]) { char **envp = r_sys_get_environ(); ut32 spflags = 0; //POSIX_SPAWN_START_SUSPENDED; spflags |= POSIX_SPAWN_SETEXEC; if (p->_aslr == 0) { #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 spflags |= _POSIX_SPAWN_DISABLE_ASLR; } (void)posix_spawnattr_setflags (&attr, spflags); if (p->_bits) { size_t copied = 1; cpu_type_t cpu; #if __i386__ || __x86_64__ cpu = CPU_TYPE_I386; if (p->_bits == 64) cpu |= CPU_ARCH_ABI64; #else cpu = CPU_TYPE_ANY; #endif posix_spawnattr_setbinpref_np ( &attr, 1, &cpu, &copied); } ret = posix_spawnp (&pid, p->_args[0], NULL, &attr, p->_args, envp); switch (ret) { case 0: break; case 22: eprintf ("posix_spawnp: Invalid argument\n"); break; case 86: eprintf ("posix_spawnp: Unsupported architecture\n"); break; default: eprintf ("posix_spawnp: unknown error %d\n", ret); perror ("posix_spawnp"); break; } exit (ret); } #endif if (p->_system) { if (p->_pid) { eprintf ("PID: Cannot determine pid with 'system' directive. Use 'program'.\n"); } exit (r_sys_cmd (p->_system)); } if (p->_program) { if (!r_file_exists (p->_program)) { char *progpath = r_file_path (p->_program); if (progpath && *progpath) { free (p->_program); p->_program = progpath; } else { free (progpath); eprintf ("rarun2: %s: file not found\n", p->_program); return 1; } } #if __UNIX__ // XXX HACK close all non-tty fds { int i; for (i=3; i<10; i++) close (i); } // TODO: use posix_spawn if (p->_setgid) { ret = setgid (atoi (p->_setgid)); if (ret < 0) return 1; } if (p->_pid) { eprintf ("PID: %d\n", getpid ()); } if (p->_pidfile) { char pidstr[32]; snprintf (pidstr, sizeof (pidstr), "%d\n", getpid ()); r_file_dump (p->_pidfile, (const ut8*)pidstr, strlen (pidstr), 0); } #endif if (p->_nice) { #if __UNIX__ errno = 0; ret = nice(p->_nice); if (ret == -1) { if (errno != 0) { return 1; } } #else eprintf ("nice not supported for this platform\n"); #endif } exit (execv (p->_program, (char* const*)p->_args)); } return 0; }
R_API int r_diff_buffers_static(RDiff *d, const ut8 *a, int la, const ut8 *b, int lb) { int i, len; int hit = 0; la = R_ABS(la); lb = R_ABS(lb); if (la != lb) { len = R_MIN(la, lb); fprintf(stderr, "Buffer truncated to %d bytes (%d not compared)\n", len, R_ABS(lb-la)); } else len = la; for(i = 0; i<len; i++) { if (a[i]!=b[i]) { hit++; } else { if (hit>0) { struct r_diff_op_t o = { .a_off = d->off_a+i-hit, .a_buf = a+i-hit, .a_len = hit, .b_off = d->off_b+i-hit, .b_buf = b+i-hit, .b_len = hit }; d->callback (d, d->user, &o); hit = 0; } } } if (hit>0) { struct r_diff_op_t o = { .a_off = d->off_a+i-hit, .a_buf = a+i-hit, .a_len = hit, .b_off = d->off_b+i-hit, .b_buf = b+i-hit, .b_len = hit }; d->callback (d, d->user, &o); hit = 0; } return 0; } // XXX: temporary files are R_API int r_diff_buffers_radiff(RDiff *d, const ut8 *a, int la, const ut8 *b, int lb) { char *ptr, *str, buf[64], oop = 0; int ret, atl, btl, hit; ut8 at[128], bt[128]; ut64 ooa, oob; FILE *fd; hit = atl = btl = 0; ooa = oob = 0LL; oop = -1; r_file_dump (".a", a, la, 0); r_file_dump (".b", b, lb, 0); r_sys_cmd ("radiff -d .a .b | rsc uncolor > .d"); fd = fopen (".d", "r"); if (!fd) return 0; while (!feof (fd)) { ut64 oa, ob; // offset int ba, bb = 0; // byte char op; // operation oa = ob = 0LL; if (!fgets (buf, 63, fd)) break; if (feof (fd)) break; str = buf; ptr = strchr (buf, ' '); if (!ptr) continue; *ptr='\0'; sscanf (str, "0x%08"PFMT64x"", &oa); str = r_str_ichr (ptr+1, ' '); if (*str!='|'&&*str!='>'&&*str!='<') { ptr = strchr (str, ' '); if (!ptr) continue; *ptr='\0'; sscanf (str, "%02x", &ba); } else ba = 0; str = r_str_ichr (ptr+1, ' '); ptr = strchr (str, ' '); if (!ptr) continue; *ptr='\0'; sscanf (str, "%c", &op); str = r_str_ichr (ptr+1, ' '); if (str[0]!='0' || str[1]!='x') { ptr = strchr(str, ' '); if (!ptr) continue; *ptr = '\0'; sscanf (str, "%02x", &bb); } str = ptr+1; ptr = strchr (str, '\n'); if (!ptr) continue; *ptr='\0'; sscanf (str, "0x%08"PFMT64x"", &ob); if (oop == op || oop==-1) { if (hit == 0) { ooa = oa; oob = ob; } at[atl] = ba; bt[btl] = bb; switch (op) { case '|': atl++; btl++; break; case '>': btl++; break; case '<': atl++; break; } hit++; } else { if (hit>0) { struct r_diff_op_t o = { .a_off = ooa, .a_buf = at, .a_len = atl, .b_off = oob, .b_buf = bt, .b_len = btl }; ret = d->callback(d, d->user, &o); if (!ret) break; atl = btl = 0; hit = 0; } } oop = op; } if (hit > 0) { struct r_diff_op_t o = { .a_off = ooa, .a_buf = at, .a_len = atl, .b_off = oob, .b_buf = bt, .b_len = btl }; if (!d->callback (d, d->user, &o)) { fclose (fd); return 0; } atl = btl = 0; hit = 0; } fclose (fd); unlink (".a"); unlink (".b"); unlink (".d"); return 0; } R_API int r_diff_buffers(RDiff *d, const ut8 *a, ut32 la, const ut8 *b, ut32 lb) { if (d->delta) { return r_diff_buffers_delta (d, a, la, b, lb); } return r_diff_buffers_static (d, a, la, b, lb); } /* TODO: Move into r_util maybe? */ R_API bool r_diff_buffers_distance(RDiff *d, const ut8 *a, ut32 la, const ut8 *b, ut32 lb, ut32 *distance, double *similarity) { const bool verbose = d? d->verbose: false; /* More memory efficient version on Levenshtein Distance from: https://en.wikipedia.org/wiki/Levenshtein_distance http://www.codeproject.com/Articles/13525/Fast-memory-efficient-Levenshtein-algorithm ObM.. 8/July/2016 - More time efficient Levenshtein Distance. Now runs in about O(N*sum(MDistance)) instead of O(NM) In real world testing the speedups for similar files are immense. Processing of radiff2 -sV routerA/firmware_extract/bin/httpd routerB/firmware_extract/bin/httpd reduced from 28 hours to about 13 minutes. */ int i, j; const ut8 *aBufPtr; const ut8 *bBufPtr; ut32 aLen; ut32 bLen; // temp pointer will be used to switch v0 and v1 after processing the inner loop. int *temp; int *v0, *v1; // We need these variables outside the context of the loops as we need to // survive multiple loop iterations. // start and stop are used in our inner loop // colMin tells us the current 'best' edit distance. // extendStop & extendStart are used when we get 'double up' edge conditions // that require us to keep some more data. int start = 0; int stop = 0; int smallest; int colMin = 0; int extendStop = 0; int extendStart = 0; //we could move cost into the 'i' loop. int cost = 0; // loops can get very big, this can be removed, but it's currently in there for debugging // and optimisation testing. ut64 loops = 0; // We need the longest file to be 'A' because our optimisation tries to stop and start // around the diagonal. // AAAAAAA // B* // B * // B *____ // if we have them the other way around and we terminate on the diagonal, we won't have // inspected all the bytes of file B.. // AAAA // B* // B * // B * // B * // B ? if (la < lb) { aBufPtr = b; bBufPtr = a; aLen = lb; bLen = la; } else { aBufPtr = a; bBufPtr = b; aLen = la; bLen = lb; } stop = bLen; // Preliminary tests //Do we have both files a & b, and are they at least one byte? if (!aBufPtr || !bBufPtr || aLen < 1 || bLen < 1) { return false; } //IF the files are the same size and are identical, then we have matching files if (aLen == bLen && !memcmp (aBufPtr, bBufPtr, aLen)) { if (distance) { *distance = 0; } if (similarity) { *similarity = 1.0; } return true; } // Only calloc if we have to do some processing // calloc v0 & v1 and check they initialised v0 = (int*) calloc ((bLen + 3), sizeof (int)); if (!v0) { eprintf ("Error: cannot allocate %i bytes.", bLen + 3); return false; } v1 = (int*) calloc ((bLen + 3), sizeof (int)); if (!v1) { eprintf ("Error: cannot allocate %i bytes", 2 * (bLen + 3)); free (v0); return false; } // initialise v0 and v1. // With optimisiation we only strictly we only need to initialise v0[0..2]=0..2 & v1[0] = 1; for (i = 0; i < bLen + 1 ; i++) { v0[i] = i; v1[i] = i + 1; } // Outer loop = the length of the longest input file. for (i = 0; i < aLen; i++) { // We're going to stop the inner loop at: // bLen (so we don't run off the end of our array) // or 'two below the diagonal' PLUS any extension we need for 'double up' edge values // (see extendStop for logic) stop = R_MIN ((i + extendStop + 2), bLen); // We need a value in the result column (v1[start]). // If you look at the loop below, we need it because we look at v1[j] as one of the // potential shortest edit distances. // In all cases where the edit distance can't 'reach', // the value of v1[start] simply increments. if (start > bLen) { break; } v1[start] = v0[start] + 1; // need to have a bigger number in colMin than we'll ever encounter in the inner loop colMin = aLen; // Inner loop does all the work: for (j = start; j <= stop; j++) { loops++; // The main levenshtein comparison: cost = (aBufPtr[i] == bBufPtr[j]) ? 0 : 1; smallest = R_MIN ((v1[j] + 1), (v0[j + 1] + 1)); smallest = R_MIN (smallest, (v0[j] + cost)); // populate the next two entries in v1. // only really required if this is the last loop. if (j + 2 > bLen + 3) { break; } v1[j + 1] = smallest; v1[j + 2] = smallest + 1; // If we have seen a smaller number, it's the new column Minimum colMin = R_MIN ((colMin), (smallest)); } // We're going to start at i+1 next iteration // The column minimum is the current edit distance // This distance is the minimum 'search width' from the optimal 'i' diagonal // The extendStart picks up an edge case where we have a match on the first iteration // We update extendStart after we've set start for the next iteration. start = i + 1 - colMin - extendStart; // If the last processed entry is a match, AND // the current byte in 'a' and the previous processed entry in 'b' aren't a match // then we need to extend our search below the optimal 'i' diagonal. because we'll // have a vertical double up condition in our last two values of the results column. // j-2 is used because j++ increments prior to loop exit in the processing loop above. if (!cost && aBufPtr[i] != bBufPtr[j - 2]) { extendStop ++; } // If new start would be a match then we have a horizontal 'double up' // which means we need to keep an extra row of data // so don't increment the start counter this time, BUT keep // extendStart up our sleeves for next iteration. if (i + 1 < aLen && start < bLen && aBufPtr[i + 1] == bBufPtr[start]) { start --; extendStart ++; } //Switch v0 and v1 pointers via temp pointer temp = v0; v0 = v1; v1 = temp; //Print a processing update every 10K of outer loop if (verbose && i % 10000==0) { eprintf ("\rProcessing %d of %d\r", i, aLen); } } //Clean up output on loop exit (purely aesthetic) if (verbose) { eprintf ("\rProcessing %d of %d (loops=%llu)\n", i, aLen,loops); } if (distance) { // the final distance is the last byte we processed in the inner loop. // v0 is used instead of v1 because we switched the pointers before exiting the outer loop *distance = v0[stop]; if (similarity) { double diff = (double) (*distance) / (double) (R_MAX (aLen, bLen)); *similarity = (double)1 - diff; } } free (v0); free (v1); return true; }
R_API int r_run_start(RRunProfile *p) { #if LIBC_HAVE_FORK if (p->_execve) { exit (execv (p->_program, (char* const*)p->_args)); } #endif #if __APPLE__ && !__POWERPC__ && LIBC_HAVE_FORK posix_spawnattr_t attr = {0}; pid_t pid = -1; int ret; posix_spawnattr_init (&attr); if (p->_args[0]) { char **envp = r_sys_get_environ(); ut32 spflags = 0; //POSIX_SPAWN_START_SUSPENDED; spflags |= POSIX_SPAWN_SETEXEC; if (p->_aslr == 0) { #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 spflags |= _POSIX_SPAWN_DISABLE_ASLR; } (void)posix_spawnattr_setflags (&attr, spflags); if (p->_bits) { size_t copied = 1; cpu_type_t cpu; #if __i386__ || __x86_64__ cpu = CPU_TYPE_I386; if (p->_bits == 64) cpu |= CPU_ARCH_ABI64; #else cpu = CPU_TYPE_ANY; #endif posix_spawnattr_setbinpref_np ( &attr, 1, &cpu, &copied); } ret = posix_spawnp (&pid, p->_args[0], NULL, &attr, p->_args, envp); switch (ret) { case 0: break; case 22: eprintf ("posix_spawnp: Invalid argument\n"); break; case 86: eprintf ("posix_spawnp: Unsupported architecture\n"); break; default: eprintf ("posix_spawnp: unknown error %d\n", ret); perror ("posix_spawnp"); break; } exit (ret); } #endif if (p->_system) { if (p->_pid) { eprintf ("PID: Cannot determine pid with 'system' directive. Use 'program'.\n"); } exit (r_sys_cmd (p->_system)); } if (p->_program) { if (!r_file_exists (p->_program)) { char *progpath = r_file_path (p->_program); if (progpath && *progpath) { free (p->_program); p->_program = progpath; } else { free (progpath); eprintf ("rarun2: %s: file not found\n", p->_program); return 1; } } #if __UNIX__ // XXX HACK close all non-tty fds { int i; for (i=3; i<10; i++) close (i); } // TODO: use posix_spawn if (p->_setgid) { int ret = setgid (atoi (p->_setgid)); if (ret < 0) return 1; } if (p->_pid) { eprintf ("PID: %d\n", getpid ()); } if (p->_pidfile) { char pidstr[32]; snprintf (pidstr, sizeof (pidstr), "%d\n", getpid ()); r_file_dump (p->_pidfile, (const ut8*)pidstr, strlen (pidstr), 0); } #endif if (p->_nice) { #if __UNIX__ && !defined(__HAIKU__) if (nice (p->_nice) == -1) { return 1; } #else eprintf ("nice not supported for this platform\n"); #endif } // TODO: must be HAVE_EXECVE #if LIBC_HAVE_FORK exit (execv (p->_program, (char* const*)p->_args)); #endif } return 0; }
/* TODO: simplify using r_write */ static int cmd_write(void *data, const char *input) { ut64 off; ut8 *buf; const char *arg; int wseek, i, size, len = strlen (input); char *tmp, *str, *ostr; RCore *core = (RCore *)data; #define WSEEK(x,y) if(wseek)r_core_seek_delta(x,y) wseek = r_config_get_i (core->config, "cfg.wseek"); str = ostr = strdup (input+1); switch (*input) { case 'p': if (input[1]==' ' && input[2]) { r_core_patch (core, input+2); } else { eprintf ("Usage: wp [rapatch-file]\n" "TODO: rapatch format documentation here\n"); } break; case 'r': off = r_num_math (core->num, input+1); len = (int)off; if (len>0) { buf = malloc (len); if (buf != NULL) { r_num_irand (); for (i=0; i<len; i++) buf[i] = r_num_rand (256); r_core_write_at (core, core->offset, buf, len); WSEEK (core, len); free (buf); } else eprintf ("Cannot allocate %d bytes\n", len); } break; case 'A': switch (input[1]) { case ' ': if (input[2] && input[3]==' ') { r_asm_set_pc (core->assembler, core->offset); eprintf ("modify (%c)=%s\n", input[2], input+4); len = r_asm_modify (core->assembler, core->block, input[2], r_num_math (core->num, input+4)); eprintf ("len=%d\n", len); if (len>0) { r_core_write_at (core, core->offset, core->block, len); WSEEK (core, len); } else eprintf ("r_asm_modify = %d\n", len); } else eprintf ("Usage: wA [type] [value]\n"); break; case '?': default: r_cons_printf ("Usage: wA [type] [value]\n" "Types:\n" " r raw write value\n" " v set value (taking care of current address)\n" " d destination register\n" " 0 1st src register\n" " 1 2nd src register\n" "Example: wA r 0 # e800000000\n"); break; } break; case 'c': switch (input[1]) { case 'i': r_io_cache_commit (core->io); r_core_block_read (core, 0); break; case 'r': r_io_cache_reset (core->io, R_TRUE); /* Before loading the core block we have to make sure that if * the cache wrote past the original EOF these changes are no * longer displayed. */ memset (core->block, 0xff, core->blocksize); r_core_block_read (core, 0); break; case '-': if (input[2]=='*') { r_io_cache_reset (core->io, R_TRUE); } else if (input[2]==' ') { char *p = strchr (input+3, ' '); ut64 to, from = core->offset; if (p) { *p = 0; from = r_num_math (core->num, input+3); to = r_num_math (core->num, input+3); if (to<from) { eprintf ("Invalid range (from>to)\n"); return 0; } } else { from = r_num_math (core->num, input+3); to = from + core->blocksize; } r_io_cache_invalidate (core->io, from, to); } else { eprintf ("Invalidate write cache at 0x%08"PFMT64x"\n", core->offset); r_io_cache_invalidate (core->io, core->offset, core->offset+core->blocksize); } /* See 'r' above. */ memset (core->block, 0xff, core->blocksize); r_core_block_read (core, 0); break; case '?': r_cons_printf ( "Usage: wc[ir*?]\n" " wc list all write changes\n" " wc- [a] [b] remove write op at curseek or given addr\n" " wc* \"\" in radare commands\n" " wcr reset all write changes in cache\n" " wci commit write cache\n" "NOTE: Requires 'e io.cache=true'\n"); break; case '*': r_io_cache_list (core->io, R_TRUE); break; case '\0': r_io_cache_list (core->io, R_FALSE); break; } break; case ' ': /* write string */ len = r_str_escape (str); r_core_write_at (core, core->offset, (const ut8*)str, len); #if 0 r_io_set_fd (core->io, core->file->fd); r_io_write_at (core->io, core->offset, (const ut8*)str, len); #endif WSEEK (core, len); r_core_block_read (core, 0); break; case 't': if (*str != ' ') { eprintf ("Usage: wt file [size]\n"); } else { tmp = strchr (str+1, ' '); if (tmp) { st64 sz = (st64) r_num_math (core->num, tmp+1); *tmp = 0; if (sz<1) eprintf ("Invalid length\n"); else r_core_dump (core, str+1, core->offset, (ut64)sz); } else r_file_dump (str+1, core->block, core->blocksize); } break; case 'T': eprintf ("TODO: wT // why?\n"); break; case 'f': arg = (const char *)(input+((input[1]==' ')?2:1)); if ((buf = (ut8*) r_file_slurp (arg, &size))) { r_io_set_fd (core->io, core->file->fd); r_io_write_at (core->io, core->offset, buf, size); WSEEK (core, size); free(buf); r_core_block_read (core, 0); } else eprintf ("Cannot open file '%s'\n", arg); break; case 'F': arg = (const char *)(input+((input[1]==' ')?2:1)); if ((buf = r_file_slurp_hexpairs (arg, &size))) { r_io_set_fd (core->io, core->file->fd); r_io_write_at (core->io, core->offset, buf, size); WSEEK (core, size); free (buf); r_core_block_read (core, 0); } else eprintf ("Cannot open file '%s'\n", arg); break; case 'w': str++; len = (len-1)<<1; if (len>0) tmp = malloc (len+1); else tmp = NULL; if (tmp) { for (i=0; i<len; i++) { if (i%2) tmp[i] = 0; else tmp[i] = str[i>>1]; } str = tmp; r_io_set_fd (core->io, core->file->fd); r_io_write_at (core->io, core->offset, (const ut8*)str, len); WSEEK (core, len); r_core_block_read (core, 0); free (tmp); } else eprintf ("Cannot malloc %d\n", len); break; case 'x': { int b, len = strlen (input); ut8 *buf = malloc (len+1); len = r_hex_str2bin (input+1, buf); if (len != 0) { if (len<0) len = -len+1; b = core->block[len]&0xf; b |= (buf[len]&0xf0); buf[len] = b; r_core_write_at (core, core->offset, buf, len); WSEEK (core, len); r_core_block_read (core, 0); } else eprintf ("Error: invalid hexpair string\n"); free (buf); } break; case 'a': switch (input[1]) { case 'o': if (input[2] == ' ') r_core_hack (core, input+3); else r_core_hack_help (core); break; case ' ': case '*': { const char *file = input[1]=='*'? input+2: input+1; RAsmCode *acode; r_asm_set_pc (core->assembler, core->offset); acode = r_asm_massemble (core->assembler, file); if (acode) { if (input[1]=='*') { r_cons_printf ("wx %s\n", acode->buf_hex); } else { if (r_config_get_i (core->config, "scr.prompt")) eprintf ("Written %d bytes (%s)=wx %s\n", acode->len, input+1, acode->buf_hex); r_core_write_at (core, core->offset, acode->buf, acode->len); WSEEK (core, acode->len); r_core_block_read (core, 0); } r_asm_code_free (acode); } } break; case 'f': if ((input[2]==' '||input[2]=='*')) { const char *file = input[2]=='*'? input+4: input+3; RAsmCode *acode; r_asm_set_pc (core->assembler, core->offset); acode = r_asm_assemble_file (core->assembler, file); if (acode) { if (input[2]=='*') { r_cons_printf ("wx %s\n", acode->buf_hex); } else { if (r_config_get_i (core->config, "scr.prompt")) eprintf ("Written %d bytes (%s)=wx %s\n", acode->len, input+1, acode->buf_hex); r_core_write_at (core, core->offset, acode->buf, acode->len); WSEEK (core, acode->len); r_core_block_read (core, 0); } r_asm_code_free (acode); } else eprintf ("Cannot assemble file\n"); } else eprintf ("Wrong argument\n"); break; default: eprintf ("Usage: wa[of*] [arg]\n" " wa nop : write nopcode using asm.arch and asm.bits\n" " wa* mov eax, 33 : show 'wx' op with hexpair bytes of sassembled opcode\n" " \"wa nop;nop\" : assemble more than one instruction (note the quotes)\n" " waf foo.asm : assemble file and write bytes\n" " wao nop : convert current opcode into nops\n" " wao? : show help for assembler operation on current opcode (hack)\n"); break; } break; case 'b': { int len = strlen (input); ut8 *buf = malloc (len+1); if (buf) { len = r_hex_str2bin (input+1, buf); if (len > 0) { r_mem_copyloop (core->block, buf, core->blocksize, len); r_core_write_at (core, core->offset, core->block, core->blocksize); WSEEK (core, core->blocksize); r_core_block_read (core, 0); } else eprintf ("Wrong argument\n"); } else eprintf ("Cannot malloc %d\n", len+1); } break; case 'm': size = r_hex_str2bin (input+1, (ut8*)str); switch (input[1]) { case '\0': eprintf ("Current write mask: TODO\n"); // TODO break; case '?': break; case '-': r_io_set_write_mask(core->io, 0, 0); eprintf ("Write mask disabled\n"); break; case ' ': if (size>0) { r_io_set_fd (core->io, core->file->fd); r_io_set_write_mask (core->io, (const ut8*)str, size); WSEEK (core, size); eprintf ("Write mask set to '"); for (i=0; i<size; i++) eprintf ("%02x", str[i]); eprintf ("'\n"); } else eprintf ("Invalid string\n"); break; } break; case 'v': { int type = 0; ut8 addr1; ut16 addr2; ut32 addr4, addr4_; ut64 addr8; switch (input[1]) { case '?': r_cons_printf ("Usage: wv[size] [value] # write value of given size\n" " wv1 234 # write one byte with this value\n" " wv 0x834002 # write dword with this value\n" "Supported sizes are: 1, 2, 4, 8\n"); return 0; case '1': type = 1; break; case '2': type = 2; break; case '4': type = 4; break; case '8': type = 8; break; } off = r_num_math (core->num, input+2); r_io_set_fd (core->io, core->file->fd); r_io_seek (core->io, core->offset, R_IO_SEEK_SET); if (type == 0) type = (off&UT64_32U)? 8: 4; switch (type) { case 1: addr1 = (ut8)off; r_io_write (core->io, (const ut8 *)&addr1, 1); WSEEK (core, 1); break; case 2: addr2 = (ut16)off; r_io_write (core->io, (const ut8 *)&addr2, 2); WSEEK (core, 2); break; case 4: addr4_ = (ut32)off; //drop_endian((ut8*)&addr4_, (ut8*)&addr4, 4); /* addr4_ = addr4 */ //endian_memcpy((ut8*)&addr4, (ut8*)&addr4_, 4); /* addr4 = addr4_ */ memcpy ((ut8*)&addr4, (ut8*)&addr4_, 4); // XXX needs endian here too r_io_write (core->io, (const ut8 *)&addr4, 4); WSEEK (core, 4); break; case 8: /* 8 byte addr */ memcpy ((ut8*)&addr8, (ut8*)&off, 8); // XXX needs endian here // endian_memcpy((ut8*)&addr8, (ut8*)&off, 8); r_io_write (core->io, (const ut8 *)&addr8, 8); WSEEK (core, 8); break; } r_core_block_read (core, 0); } break; case 'o': switch (input[1]) { case 'a': case 's': case 'A': case 'x': case 'r': case 'l': case 'm': case 'd': case 'o': case 'w': if (input[2]!=' ') { r_cons_printf ("Usage: 'wo%c 00 11 22'\n", input[1]); return 0; } case '2': case '4': r_core_write_op (core, input+3, input[1]); r_core_block_read (core, 0); break; case 'n': r_core_write_op (core, "ff", 'x'); r_core_block_read (core, 0); break; case '\0': case '?': default: r_cons_printf ( "Usage: wo[asmdxoArl24] [hexpairs] @ addr[:bsize]\n" "Example:\n" " wox 0x90 ; xor cur block with 0x90\n" " wox 90 ; xor cur block with 0x90\n" " wox 0x0203 ; xor cur block with 0203\n" " woa 02 03 ; add [0203][0203][...] to curblk\n" "Supported operations:\n" " wow == write looped value (alias for 'wb')\n" " woa += addition\n" " wos -= substraction\n" " wom *= multiply\n" " wod /= divide\n" " wox ^= xor\n" " woo |= or\n" " woA &= and\n" " wor >>= shift right\n" " wol <<= shift left\n" " wo2 2= 2 byte endian swap\n" " wo4 4= 4 byte endian swap\n" ); break; } break; default: case '?': if (core->oobi) { eprintf ("Writing oobi buffer!\n"); r_io_set_fd (core->io, core->file->fd); r_io_write (core->io, core->oobi, core->oobi_len); WSEEK (core, core->oobi_len); r_core_block_read (core, 0); } else r_cons_printf ( "Usage: w[x] [str] [<file] [<<EOF] [@addr]\n" " w foobar write string 'foobar'\n" " wr 10 write 10 random bytes\n" " ww foobar write wide string 'f\\x00o\\x00o\\x00b\\x00a\\x00r\\x00'\n" " wa push ebp write opcode, separated by ';' (use '\"' around the command)\n" " waf file assemble file and write bytes\n" " wA r 0 alter/modify opcode at current seek (see wA?)\n" " wb 010203 fill current block with cyclic hexpairs\n" " wc[ir*?] write cache commit/reset/list\n" " wx 9090 write two intel nops\n" " wv eip+34 write 32-64 bit value\n" " wo? hex write in block with operation. 'wo?' fmi\n" " wm f0ff set binary mask hexpair to be used as cyclic write mask\n" " wf file write contents of file at current offset\n" " wF file write contents of hexpairs file here\n" " wt file [sz] write to file (from current seek, blocksize or sz bytes)\n" " wp file apply radare patch file. See wp? fmi\n"); //TODO: add support for offset+seek // " wf file o s ; write contents of file from optional offset 'o' and size 's'.\n" break; }
R_API bool r_buf_dump(RBuffer *b, const char *file) { if (!b || !file) { return false; } return r_file_dump (file, r_buf_get_at (b, 0, NULL), r_buf_size (b), 0); }
/* TODO: simplify using r_write */ static int cmd_write(void *data, const char *input) { int wseek, i, size, len = strlen (input); RCore *core = (RCore *)data; char *tmp, *str, *ostr; const char *arg, *filename; char _fn[32]; ut64 off; ut8 *buf; st64 num = 0; const char* help_msg[] = { "Usage:","w[x] [str] [<file] [<<EOF] [@addr]","", "w","[1248][+-][n]","increment/decrement byte,word..", "w"," foobar","write string 'foobar'", "w0"," [len]","write 'len' bytes with value 0x00", "w6","[de] base64/hex","write base64 [d]ecoded or [e]ncoded string", "wa"," push ebp","write opcode, separated by ';' (use '\"' around the command)", "waf"," file","assemble file and write bytes", "wA"," r 0","alter/modify opcode at current seek (see wA?)", "wb"," 010203","fill current block with cyclic hexpairs", "wB","[-]0xVALUE","set or unset bits with given value", "wc","","list all write changes", "wc","[ir*?]","write cache undo/commit/reset/list (io.cache)", "wd"," [off] [n]","duplicate N bytes from offset at current seek (memcpy) (see y?)", "we","[nNsxX] [arg]","extend write operations (insert instead of replace)", "wf"," -|file","write contents of file at current offset", "wF"," -|file","write contents of hexpairs file here", "wh"," r2","whereis/which shell command", "wm"," f0ff","set binary mask hexpair to be used as cyclic write mask", "wo?"," hex","write in block with operation. 'wo?' fmi", "wp"," -|file","apply radare patch file. See wp? fmi", "wr"," 10","write 10 random bytes", "ws"," pstring","write 1 byte for length and then the string", "wt"," file [sz]","write to file (from current seek, blocksize or sz bytes)", "ww"," foobar","write wide string 'f\\x00o\\x00o\\x00b\\x00a\\x00r\\x00'", "wx"," 9090","write two intel nops", "wv"," eip+34","write 32-64 bit value", NULL }; if (!input) return 0; #define WSEEK(x,y) if (wseek)r_core_seek_delta (x,y) wseek = r_config_get_i (core->config, "cfg.wseek"); str = ostr = strdup ((input&&*input)?input+1:""); _fn[0] = 0; switch (*input) { case 'B': switch (input[1]) { case ' ': cmd_write_bits (core, 1, r_num_math (core->num, input+2)); break; case '-': cmd_write_bits (core, 0, r_num_math (core->num, input+2)); break; default: eprintf ("Usage: wB 0x2000 # or wB-0x2000\n"); break; } break; case '0': { ut64 len = r_num_math (core->num, input+1); if (len>0) { ut8 *buf = calloc (1, len); if (buf) { r_io_write (core->io, buf, len); free (buf); } else eprintf ("Cannot allocate %d bytes\n", (int)len); } } break; case '1': case '2': case '4': case '8': if (input[1] && input[2]) { if (input[1]==input[2]) { num = 1; } else num = r_num_math (core->num, input+2); } switch (input[2] ? input[1] : 0) { case '+': cmd_write_inc (core, *input-'0', num); break; case '-': cmd_write_inc (core, *input-'0', -num); break; default: eprintf ("Usage: w[1248][+-][num] # inc/dec byte/word/..\n"); } break; case '6': { int fail = 0; if(input[1] && input[2] != ' ') { fail = 1; } ut8 *buf; int len, str_len; const char *str; if (input[1] && input[2] && input[3]) str = input + 3; else str = ""; str_len = strlen (str) + 1; if (!fail) { switch (input[1]) { case 'd': buf = malloc (str_len); len = r_base64_decode (buf, str, 0); if(len == 0) { free(buf); fail = 1; } break; case 'e': { ut8 *bin_buf = malloc(str_len); int bin_len = r_hex_str2bin(str, bin_buf); if(bin_len == 0) { fail = 1; } else { buf = malloc(str_len * 4 + 1); len = r_base64_encode((char *)buf, bin_buf, bin_len); if(len == 0) { free(buf); fail = 1; } } free (bin_buf); break; } default: fail = 1; break; } } if(!fail) { r_core_write_at (core, core->offset, buf, len); WSEEK (core, len); r_core_block_read (core, 0); free(buf); } else { eprintf ("Usage: w6[de] base64/hex\n"); } break; } case 'h': { char *p = strchr (input, ' '); if (p) { while (*p==' ') p++; p = r_file_path (p); if (p) { r_cons_printf ("%s\n", p); free (p); } } } break; case 'e': { ut64 addr = 0, len = 0, b_size = 0; st64 dist = 0; ut8* bytes = NULL; int cmd_suc = R_FALSE; char *input_shadow = NULL, *p = NULL; switch (input[1]) { case 'n': if (input[2] == ' ') { len = *input ? r_num_math ( core->num, input+3) : 0; if (len > 0){ ut64 cur_off = core->offset; cmd_suc = r_core_extend_at (core, core->offset, len); core->offset = cur_off; r_core_block_read (core, 0); } } break; case 'N': if (input[2] == ' ') { input += 3; while (*input && *input == ' ') input++; addr = r_num_math (core->num, input); while (*input && *input != ' ') input++; input++; len = *input ? r_num_math (core->num, input) : 0; if (len > 0){ ut64 cur_off = core->offset; cmd_suc = r_core_extend_at (core, addr, len); cmd_suc = r_core_seek (core, cur_off, 1); core->offset = addr; r_core_block_read (core, 0); } } break; case 'x': if (input[2] == ' ') { input+=2; len = *input ? strlen (input) : 0; bytes = len > 1? malloc (len+1) : NULL; len = bytes ? r_hex_str2bin (input, bytes) : 0; if (len > 0) { ut64 cur_off = core->offset; cmd_suc = r_core_extend_at (core, cur_off, len); if (cmd_suc) { r_core_write_at (core, cur_off, bytes, len); } core->offset = cur_off; r_core_block_read (core, 0); } free (bytes); } break; case 'X': if (input[2] == ' ') { addr = r_num_math (core->num, input+3); input += 3; while (*input && *input != ' ') input++; input++; len = *input ? strlen (input) : 0; bytes = len > 1? malloc (len+1) : NULL; len = bytes ? r_hex_str2bin (input, bytes) : 0; if (len > 0) { //ut64 cur_off = core->offset; cmd_suc = r_core_extend_at (core, addr, len); if (cmd_suc) { r_core_write_at (core, addr, bytes, len); } core->offset = addr; r_core_block_read (core, 0); } free (bytes); } break; case 's': input += 3; while (*input && *input == ' ') input++; len = strlen (input); input_shadow = len > 0? malloc (len+1): 0; // since the distance can be negative, // the r_num_math will perform an unwanted operation // the solution is to tokenize the string :/ if (input_shadow) { strncpy (input_shadow, input, len+1); p = strtok (input_shadow, " "); addr = p && *p ? r_num_math (core->num, p) : 0; p = strtok (NULL, " "); dist = p && *p ? r_num_math (core->num, p) : 0; p = strtok (NULL, " "); b_size = p && *p ? r_num_math (core->num, p) : 0; if (dist != 0){ r_core_shift_block (core, addr, b_size, dist); r_core_seek (core, addr, 1); cmd_suc = R_TRUE; } } free (input_shadow); break; case '?': default: cmd_suc = R_FALSE; } if (cmd_suc == R_FALSE) { r_cons_printf ("|Usage: write extend\n" "wen <num> insert num null bytes at current offset\n" "wex <hex_bytes> insert bytes at current offset\n" "weN <addr> <len> insert bytes at address\n" "weX <addr> <hex_bytes> insert bytes at address\n" "wes <addr> <dist> <block_size> shift a blocksize left or write in the editor\n" ); } } break; case 'p': if (input[1]=='-' || (input[1]==' ' && input[2]=='-')) { char *out = r_core_editor (core, NULL, NULL); if (out) { r_core_patch (core, out); free (out); } } else { if (input[1]==' ' && input[2]) { char *data = r_file_slurp (input+2, NULL); if (data) { r_core_patch (core, data); free (data); } } else { eprintf ("Usage: wp [-|r2patch-file]\n" "TODO: rapatch format documentation here\n"); } } break; case 'u': // TODO: implement it in an API RCore.write_unified_hexpatch() is ETOOLONG if (input[1]==' ') { char *data = r_file_slurp (input+2, NULL); if (data) { char sign = ' '; int line = 0, offs = 0, hexa = 0; int newline = 1; for (i=0; data[i]; i++) { switch (data[i]) { case '+': if (newline) sign = 1; break; case '-': if (newline) { sign = 0; offs = i + ((data[i+1]==' ')?2:1); } break; case ' ': data[i] = 0; if (sign) { if (!line) line = i+1; else if (!hexa) hexa = i+1; } break; case '\r': break; case '\n': newline = 1; if (sign == -1) { offs = 0; line = 0; hexa = 0; } else if (sign) { if (offs && hexa) { r_cons_printf ("wx %s @ %s\n", data+hexa, data+offs); } else eprintf ("food\n"); offs = 0; line = 0; } else hexa = 0; sign = -1; continue; } newline = 0; } free (data); } } else { eprintf ("|Usage: wu [unified-diff-patch] # see 'cu'\n"); } break; case 'r': off = r_num_math (core->num, input+1); len = (int)off; if (len>0) { buf = malloc (len); if (buf != NULL) { r_num_irand (); for (i=0; i<len; i++) buf[i] = r_num_rand (256); r_core_write_at (core, core->offset, buf, len); WSEEK (core, len); free (buf); } else eprintf ("Cannot allocate %d bytes\n", len); } break; case 'A': switch (input[1]) { case ' ': if (input[2] && input[3]==' ') { r_asm_set_pc (core->assembler, core->offset); eprintf ("modify (%c)=%s\n", input[2], input+4); len = r_asm_modify (core->assembler, core->block, input[2], r_num_math (core->num, input+4)); eprintf ("len=%d\n", len); if (len>0) { r_core_write_at (core, core->offset, core->block, len); WSEEK (core, len); } else eprintf ("r_asm_modify = %d\n", len); } else eprintf ("Usage: wA [type] [value]\n"); break; case '?': default: r_cons_printf ("|Usage: wA [type] [value]\n" "|Types:\n" "| r raw write value\n" "| v set value (taking care of current address)\n" "| d destination register\n" "| 0 1st src register\n" "| 1 2nd src register\n" "|Example: wA r 0 # e800000000\n"); break; } break; case 'c': switch (input[1]) { case 'i': r_io_cache_commit (core->io, 0, UT64_MAX); r_core_block_read (core, 0); break; case 'r': r_io_cache_reset (core->io, R_TRUE); /* Before loading the core block we have to make sure that if * the cache wrote past the original EOF these changes are no * longer displayed. */ memset (core->block, 0xff, core->blocksize); r_core_block_read (core, 0); break; case '+': if (input[2]=='*') { //r_io_cache_reset (core->io, R_TRUE); eprintf ("TODO\n"); } else if (input[2]==' ') { char *p = strchr (input+3, ' '); ut64 to, from = core->offset; if (p) { *p = 0; from = r_num_math (core->num, input+3); to = r_num_math (core->num, input+3); if (to<from) { eprintf ("Invalid range (from>to)\n"); return 0; } } else { from = r_num_math (core->num, input+3); to = from + core->blocksize; } r_io_cache_commit (core->io, from, to); } else { eprintf ("Invalidate write cache at 0x%08"PFMT64x"\n", core->offset); r_io_cache_commit (core->io, core->offset, core->offset+1); } break; case '-': if (input[2]=='*') { r_io_cache_reset (core->io, R_TRUE); } else if (input[2]==' ') { char *p = strchr (input+3, ' '); ut64 to, from = core->offset; if (p) { *p = 0; from = r_num_math (core->num, input+3); to = r_num_math (core->num, input+3); if (to<from) { eprintf ("Invalid range (from>to)\n"); return 0; } } else { from = r_num_math (core->num, input+3); to = from + core->blocksize; } r_io_cache_invalidate (core->io, from, to); } else { eprintf ("Invalidate write cache at 0x%08"PFMT64x"\n", core->offset); r_io_cache_invalidate (core->io, core->offset, core->offset+core->blocksize); } /* See 'r' above. */ memset (core->block, 0xff, core->blocksize); r_core_block_read (core, 0); break; case '?': { const char* help_msg[] = { "Usage:", "wc[ir+-*?]"," # NOTE: Uses io.cache=true", "wc","","list all write changes", "wc-"," [from] [to]","remove write op at curseek or given addr", "wc+"," [addr]","commit change from cache to io", "wc*","","\"\" in radare commands", "wcr","","reset all write changes in cache", "wci","","commit write cache", NULL }; r_core_cmd_help(core, help_msg); } break; case '*': r_io_cache_list (core->io, R_TRUE); break; case '\0': //if (!r_config_get_i (core->config, "io.cache")) // eprintf ("[warning] e io.cache must be true\n"); r_io_cache_list (core->io, R_FALSE); break; } break; case ' ': /* write string */ len = r_str_unescape (str); r_core_write_at (core, core->offset, (const ut8*)str, len); #if 0 r_io_use_desc (core->io, core->file->desc); r_io_write_at (core->io, core->offset, (const ut8*)str, len); #endif WSEEK (core, len); r_core_block_read (core, 0); break; case 't': // "wt" if (*str == '?' || *str == '\0') { eprintf ("Usage: wt[a] file [size] write 'size' bytes in current block to file\n"); free (ostr); return 0; } else { int append = 0; st64 sz = core->blocksize; if (*str=='a') { // "wta" append = 1; str++; if (str[0]==' ') { filename = str+1; } else { const char* prefix = r_config_get (core->config, "cfg.prefixdump"); snprintf (_fn, sizeof (_fn), "%s.0x%08"PFMT64x, prefix, core->offset); filename = _fn; } } else if (*str != ' ') { const char* prefix = r_config_get (core->config, "cfg.prefixdump"); snprintf(_fn, sizeof(_fn), "%s.0x%08"PFMT64x, prefix, core->offset); filename = _fn; } else filename = str+1; tmp = strchr (str+1, ' '); if (tmp) { sz = (st64) r_num_math (core->num, tmp+1); if (!sz) { sz = core->blocksize; } *tmp = 0; if (sz<1) eprintf ("Invalid length\n"); else r_core_dump (core, filename, core->offset, (ut64)sz, append); } else { if (!r_file_dump (filename, core->block, core->blocksize, append)) { sz = 0; } else sz = core->blocksize; } eprintf ("Dumped %"PFMT64d" bytes from 0x%08"PFMT64x" into %s\n", sz, core->offset, filename); } break; case 'f': arg = (const char *)(input+((input[1]==' ')?2:1)); if (!strcmp (arg, "-")) { char *out = r_core_editor (core, NULL, NULL); if (out) { r_io_write_at (core->io, core->offset, (ut8*)out, strlen (out)); free (out); } } else if ((buf = (ut8*) r_file_slurp (arg, &size))) { r_io_use_desc (core->io, core->file->desc); r_io_write_at (core->io, core->offset, buf, size); WSEEK (core, size); free (buf); r_core_block_read (core, 0); } else eprintf ("Cannot open file '%s'\n", arg); break; case 'F': arg = (const char *)(input+((input[1]==' ')?2:1)); if (!strcmp (arg, "-")) { int len; ut8 *out; char *in = r_core_editor (core, NULL, NULL); if (in) { out = (ut8 *)strdup (in); if (out) { len = r_hex_str2bin (in, out); if (len>0) r_io_write_at (core->io, core->offset, out, len); free (out); } free (in); } } else if ((buf = r_file_slurp_hexpairs (arg, &size))) { r_io_use_desc (core->io, core->file->desc); r_io_write_at (core->io, core->offset, buf, size); WSEEK (core, size); free (buf); r_core_block_read (core, 0); } else eprintf ("Cannot open file '%s'\n", arg); break; case 'w': str++; len = (len-1)<<1; if (len>0) tmp = malloc (len+1); else tmp = NULL; if (tmp) { for (i=0; i<len; i++) { if (i%2) tmp[i] = 0; else tmp[i] = str[i>>1]; } str = tmp; r_io_use_desc (core->io, core->file->desc); r_io_write_at (core->io, core->offset, (const ut8*)str, len); WSEEK (core, len); r_core_block_read (core, 0); free (tmp); } else eprintf ("Cannot malloc %d\n", len); break; case 'x': { int b, len = strlen (input); ut8 *buf = malloc (len+1); len = r_hex_str2bin (input+1, buf); if (len != 0) { if (len<0) len = -len+1; if (len<core->blocksize) { b = core->block[len]&0xf; b |= (buf[len]&0xf0); } else b = buf[len]; buf[len] = b; r_core_write_at (core, core->offset, buf, len); WSEEK (core, len); r_core_block_read (core, 0); } else eprintf ("Error: invalid hexpair string\n"); free (buf); } break; case 'a': switch (input[1]) { case 'o': if (input[2] == ' ') r_core_hack (core, input+3); else r_core_hack_help (core); break; case ' ': case '*': { const char *file = input[1]=='*'? input+2: input+1; RAsmCode *acode; r_asm_set_pc (core->assembler, core->offset); acode = r_asm_massemble (core->assembler, file); if (acode) { if (input[1]=='*') { r_cons_printf ("wx %s\n", acode->buf_hex); } else { if (r_config_get_i (core->config, "scr.prompt")) eprintf ("Written %d bytes (%s) = wx %s\n", acode->len, input+2, acode->buf_hex); r_core_write_at (core, core->offset, acode->buf, acode->len); WSEEK (core, acode->len); r_core_block_read (core, 0); } r_asm_code_free (acode); } } break; case 'f': if ((input[2]==' '||input[2]=='*')) { const char *file = input[2]=='*'? input+4: input+3; RAsmCode *acode; r_asm_set_pc (core->assembler, core->offset); acode = r_asm_assemble_file (core->assembler, file); if (acode) { if (input[2]=='*') { r_cons_printf ("wx %s\n", acode->buf_hex); } else { if (r_config_get_i (core->config, "scr.prompt")) eprintf ("Written %d bytes (%s)=wx %s\n", acode->len, input+1, acode->buf_hex); r_core_write_at (core, core->offset, acode->buf, acode->len); WSEEK (core, acode->len); r_core_block_read (core, 0); } r_asm_code_free (acode); } else eprintf ("Cannot assemble file\n"); } else eprintf ("Wrong argument\n"); break; default: r_cons_printf ("|Usage: wa[of*] [arg]\n" "| wa nop : write nopcode using asm.arch and asm.bits\n" "| wa* mov eax, 33 : show 'wx' op with hexpair bytes of assembled opcode\n" "| \"wa nop;nop\" : assemble more than one instruction (note the quotes)\n" "| waf foo.asm : assemble file and write bytes\n" "| wao nop : convert current opcode into nops\n" "| wao? : show help for assembler operation on current opcode (hack)\n"); break; } break; case 'b': { int len = strlen (input); ut8 *buf = malloc (len+1); if (buf) { len = r_hex_str2bin (input+1, buf); if (len > 0) { r_mem_copyloop (core->block, buf, core->blocksize, len); r_core_write_at (core, core->offset, core->block, core->blocksize); WSEEK (core, core->blocksize); r_core_block_read (core, 0); } else eprintf ("Wrong argument\n"); free (buf); } else eprintf ("Cannot malloc %d\n", len+1); } break; case 'm': size = r_hex_str2bin (input+1, (ut8*)str); switch (input[1]) { case '\0': eprintf ("Current write mask: TODO\n"); // TODO break; case '?': break; case '-': r_io_set_write_mask (core->io, 0, 0); eprintf ("Write mask disabled\n"); break; case ' ': if (size>0) { r_io_use_desc (core->io, core->file->desc); r_io_set_write_mask (core->io, (const ut8*)str, size); WSEEK (core, size); eprintf ("Write mask set to '"); for (i=0; i<size; i++) eprintf ("%02x", str[i]); eprintf ("'\n"); } else eprintf ("Invalid string\n"); break; } break; case 'v': cmd_write_value (core, input); break; case 'o': cmd_write_op (core, input); break; case 'd': if (input[1] && input[1]==' ') { char *arg, *inp = strdup (input+2); arg = strchr (inp, ' '); if (arg) { *arg = 0; ut64 addr = r_num_math (core->num, input+2); ut64 len = r_num_math (core->num, arg+1); ut8 *data = malloc (len); r_io_read_at (core->io, addr, data, len); r_io_write_at (core->io, core->offset, data, len); free (data); } else eprintf ("See wd?\n"); free (inp); } else eprintf ("Usage: wd [source-offset] [length] @ [dest-offset]\n"); break; case 's': if (str && *str && str[1]) { len = r_str_unescape (str+1); if (len>255) { eprintf ("Too large\n"); } else { ut8 ulen = (ut8)len; r_core_write_at (core, core->offset, &ulen, 1); r_core_write_at (core, core->offset+1, (const ut8*)str+1, len); WSEEK (core, len); r_core_block_read (core, 0); } } else eprintf ("Too short.\n"); break; default: case '?': if (core->oobi) { eprintf ("Writing oobi buffer!\n"); r_io_use_desc (core->io, core->file->desc); r_io_write (core->io, core->oobi, core->oobi_len); WSEEK (core, core->oobi_len); r_core_block_read (core, 0); } else { r_core_cmd_help (core, help_msg); } break; }
static int cmd_project(void *data, const char *input) { RCore *core = (RCore *)data; const char *file, *arg = input+1; const char *fileproject = r_config_get (core->config, "file.project"); char *str = strdup (fileproject); if (*arg==' ') arg++; file = input[1]?arg:str; switch (input[0]) { case 'c': if (!input[1]) { eprintf ("TODO: Show project saving script to console\n"); } else if (input[1]==' ') { r_core_project_cat (core, input+2); } else eprintf ("Usage: Pc [prjname]\n"); break; case 'o': // if (r_file_is_regular (file)) if (input[1]) { r_core_project_open (core, file); } else { if (file && *file) r_cons_printf ("%s\n", file); } break; case 'l': r_core_project_list (core, input[1]); break; case 'd': r_core_project_delete (core, file); break; case 's': if (r_core_project_save (core, file)) { r_config_set (core->config, "file.project", file); r_cons_printf ("%s\n", file); } break; case 'n': if (!fileproject || !*fileproject) { eprintf ("No project\n"); } else switch (input[1]) { case '-': /* remove lines containing specific words */ { char *str = r_core_project_notes_file (core, fileproject); char *data = r_file_slurp (str, NULL); FILE *fd = r_sandbox_fopen (str, "w"); if (!fd) { eprintf ("Cannot open %s\n", str); } else { int del = 0; if (data) { char *ptr, *nl; for (ptr = data; ptr; ptr = nl) { nl = strchr (ptr, '\n'); if (nl) { *nl++ = 0; if (strstr (ptr, input+2)) { del ++; } else { fprintf (fd, "%s\n", ptr); } } } free (data); } fclose (fd); free (str); if (del>0) { eprintf ("Deleted %d lines\n", del); } } } break; case ' ': if (input[2]=='-') { char *str = r_core_project_notes_file (core, fileproject); // edit with cfg.editor const char *editor = r_config_get (core->config, "cfg.editor"); if (str && *str && editor && *editor) r_sys_cmdf ("%s %s", editor, str); else eprintf ("No cfg.editor configured\n"); free (str); } else { //char *str = r_core_project_notes_file (core, fileproject); // append line to project notes char *str = r_core_project_notes_file (core, fileproject); char *data = r_file_slurp (str, NULL); FILE *fd = r_sandbox_fopen (str, "a"); if (fd) { fprintf (fd, "%s\n", input+2); fclose (fd); } free (str); free (data); } break; case 'j': if (!input[2]) { int len = 0; /* get base64 string */ char *str = r_core_project_notes_file (core, fileproject); if (str) { char *data = r_file_slurp (str, &len); char *res = r_base64_encode_dyn (data, len); if (res) { r_cons_printf ("%s\n", res); free (res); } free (data); free (str); } } else if (input[2] == ' ') { /* set base64 string */ ut8 *data = r_base64_decode_dyn (input+3, 0); if (data) { char *str = r_core_project_notes_file (core, fileproject); if (str) { r_file_dump (str, data, strlen ((const char*)data)); free (str); } free (data); } } else { eprintf ("Usage: `Pnj` or `Pnj ...`\n"); } break; case 0: { char *str = r_core_project_notes_file (core, fileproject); char *data = r_file_slurp (str, NULL); if (data) { r_cons_printf ("%s\n", data); free (data); } free (str); } break; case '?': { const char* help_msg[] = { "Usage:", "Pn[j-?] [...]", "Project Notes", "Pn", "", "show project notes", "Pn", " -", "edit notes with cfg.editor", "Pn-", "", "delete notes", "Pn-", "str", "delete lines matching /str/ in notes", "Pnj", "", "show notes in base64", "Pnj", " [base64]", "set notes in base64", NULL}; r_core_cmd_help (core, help_msg); } break; } break; case 'i': // if (r_file_is_regular (file)) free (r_core_project_info (core, file)); break; default: { const char* help_msg[] = { "Usage:", "P[?osi] [file]", "Project management", "Pc", "", "show what will be saved in the project script", "Pc", " [file]", "show project script to console", "Pd", " [file]", "delete project", "Pi", " [file]", "show project information", "Pl", "", "list all projects", "Pn", "[j]", "show project notes (Pnj for json)", "Pn", " [base64]", "set notes text", "Pn", " -", "edit notes with cfg.editor", "Po", " [file]", "open project", "Ps", " [file]", "save project", "NOTE:", "", "See 'e file.project'", "NOTE:", "", "project files are stored in ~/.config/radare2/projects", NULL}; r_core_cmd_help (core, help_msg); } break; } free (str); return R_TRUE; }
static int cmd_cmp(void *data, const char *input) { RCore *core = data; FILE *fd; ut8 *buf; int ret; ut32 v32; ut64 v64; switch (*input) { case ' ': radare_compare (core, core->block, (ut8*)input+1, strlen (input+1)+1); break; case 'x': if (input[1]!=' ') { eprintf ("Usage: cx 001122'\n"); return 0; } buf = (ut8*)malloc (strlen (input+2)); ret = r_hex_str2bin (input+2, buf); if (ret<1) eprintf ("Cannot parse hexpair\n"); else radare_compare (core, core->block, buf, ret); free (buf); break; case 'X': buf = malloc (core->blocksize); ret = r_io_read_at (core->io, r_num_math (core->num, input+1), buf, core->blocksize); radare_compare (core, core->block, buf, ret); free (buf); break; case 'f': if (input[1]!=' ') { eprintf ("Please. use 'cf [file]'\n"); return 0; } fd = fopen (input+2, "rb"); if (fd == NULL) { eprintf ("Cannot open file '%s'\n", input+2); return 0; } buf = (ut8 *)malloc (core->blocksize); fread (buf, 1, core->blocksize, fd); fclose (fd); radare_compare (core, core->block, buf, core->blocksize); free (buf); break; case 'q': v64 = (ut64) r_num_math (core->num, input+1); radare_compare (core, core->block, (ut8*)&v64, sizeof (v64)); break; case 'd': v32 = (ut32) r_num_math (core->num, input+1); radare_compare (core, core->block, (ut8*)&v32, sizeof (v32)); break; #if 0 case 'c': radare_compare_code ( r_num_math (core->num, input+1), core->block, core->blocksize); break; case 'D': { // XXX ugly hack char cmd[1024]; sprintf (cmd, "radiff -b %s %s", ".curblock", input+2); r_file_dump (".curblock", config.block, config.block_size); radare_system(cmd); unlink(".curblock"); } break; #endif case 'g': { // XXX: this is broken int diffops = 0; RCore *core2; char *file2 = NULL; if (input[1]=='o') { file2 = (char*)r_str_chop_ro (input+2); r_anal_diff_setup (core->anal, R_TRUE, -1, -1); } else if (input[1]==' ') { file2 = (char*)r_str_chop_ro (input+2); r_anal_diff_setup (core->anal, R_FALSE, -1, -1); } else { eprintf ("Usage: cg[o] [file]\n"); eprintf (" cg - byte-per-byte code graph diff\n"); eprintf (" cgo - opcode-bytes code graph diff\n"); return R_FALSE; } if (!(core2 = r_core_new ())) { eprintf ("Cannot init diff core\n"); return R_FALSE; } core2->io->va = core->io->va; core2->anal->split = core->anal->split; if (!r_core_file_open (core2, file2, 0, 0LL)) { eprintf ("Cannot open diff file '%s'\n", file2); r_core_free (core2); return R_FALSE; } // TODO: must replicate on core1 too r_config_set_i (core2->config, "io.va", R_TRUE); r_config_set_i (core2->config, "anal.split", R_TRUE); r_anal_diff_setup (core->anal, diffops, -1, -1); r_anal_diff_setup (core2->anal, diffops, -1, -1); r_core_bin_load (core2, file2); r_core_gdiff (core, core2); r_core_diff_show (core, core2); r_core_free (core2); } break; case '?': r_cons_strcat ( "Usage: c[?cdfx] [argument]\n" " c [string] Compares a plain with escaped chars string\n" //" cc [offset] Code bindiff current block against offset\n" " cd [value] Compare a doubleword from a math expression\n" //" cD [file] Like above, but using radiff -b\n"); " cq [value] Compare a quadword from a math expression\n" " cx [hexpair] Compare hexpair string\n" " cX [addr] Like 'cc' but using hexdiff output\n" " cf [file] Compare contents of file at current seek\n" " cg[o] [file] Graphdiff current file and [file]\n"); break; default: eprintf ("Usage: c[?Ddxf] [argument]\n"); } return 0; }
R_API int r_diff_buffers_static(RDiff *d, const ut8 *a, int la, const ut8 *b, int lb) { int i, len; int hit = 0; la = R_ABS(la); lb = R_ABS(lb); if (la != lb) { len = R_MIN(la, lb); fprintf(stderr, "Buffer truncated to %d bytes (%d not compared)\n", len, R_ABS(lb-la)); } else len = la; for(i = 0; i<len; i++) { if (a[i]!=b[i]) { hit++; } else { if (hit>0) { struct r_diff_op_t o = { .a_off = d->off_a+i-hit, .a_buf = a+i-hit, .a_len = hit, .b_off = d->off_b+i-hit, .b_buf = b+i-hit, .b_len = hit }; d->callback (d, d->user, &o); hit = 0; } } } if (hit>0) { struct r_diff_op_t o = { .a_off = d->off_a+i-hit, .a_buf = a+i-hit, .a_len = hit, .b_off = d->off_b+i-hit, .b_buf = b+i-hit, .b_len = hit }; d->callback (d, d->user, &o); hit = 0; } return 0; } // XXX: temporary files are R_API int r_diff_buffers_radiff(RDiff *d, const ut8 *a, int la, const ut8 *b, int lb) { char *ptr, *str, buf[64], oop = 0; int ret, atl, btl, hit; ut8 at[128], bt[128]; ut64 ooa, oob; FILE *fd; hit = atl = btl = 0; ooa = oob = 0LL; oop = -1; r_file_dump (".a", a, la, 0); r_file_dump (".b", b, lb, 0); r_sys_cmd ("radiff -d .a .b | rsc uncolor > .d"); fd = fopen (".d", "r"); if (!fd) return 0; while (!feof (fd)) { ut64 oa, ob; // offset int ba, bb = 0; // byte char op; // operation oa = ob = 0LL; if (!fgets (buf, 63, fd)) break; if (feof (fd)) break; str = buf; ptr = strchr (buf, ' '); if (!ptr) continue; *ptr='\0'; sscanf (str, "0x%08"PFMT64x"", &oa); str = r_str_ichr (ptr+1, ' '); if (*str!='|'&&*str!='>'&&*str!='<') { ptr = strchr (str, ' '); if (!ptr) continue; *ptr='\0'; sscanf (str, "%02x", &ba); } else ba = 0; str = r_str_ichr (ptr+1, ' '); ptr = strchr (str, ' '); if (!ptr) continue; *ptr='\0'; sscanf (str, "%c", &op); str = r_str_ichr (ptr+1, ' '); if (str[0]!='0' || str[1]!='x') { ptr = strchr(str, ' '); if (!ptr) continue; *ptr = '\0'; sscanf (str, "%02x", &bb); } str = ptr+1; ptr = strchr (str, '\n'); if (!ptr) continue; *ptr='\0'; sscanf (str, "0x%08"PFMT64x"", &ob); if (oop == op || oop==-1) { if (hit == 0) { ooa = oa; oob = ob; } at[atl] = ba; bt[btl] = bb; switch (op) { case '|': atl++; btl++; break; case '>': btl++; break; case '<': atl++; break; } hit++; } else { if (hit>0) { struct r_diff_op_t o = { .a_off = ooa, .a_buf = at, .a_len = atl, .b_off = oob, .b_buf = bt, .b_len = btl }; ret = d->callback(d, d->user, &o); if (!ret) break; atl = btl = 0; hit = 0; } } oop = op; } if (hit > 0) { struct r_diff_op_t o = { .a_off = ooa, .a_buf = at, .a_len = atl, .b_off = oob, .b_buf = bt, .b_len = btl }; if (!d->callback (d, d->user, &o)) { fclose (fd); return 0; } atl = btl = 0; hit = 0; } fclose (fd); unlink (".a"); unlink (".b"); unlink (".d"); return 0; } R_API int r_diff_buffers(RDiff *d, const ut8 *a, ut32 la, const ut8 *b, ut32 lb) { if (d->delta) { return r_diff_buffers_delta (d, a, la, b, lb); } return r_diff_buffers_static (d, a, la, b, lb); } /* TODO: Move into r_util maybe? */ R_API bool r_diff_buffers_distance(RDiff *d, const ut8 *a, ut32 la, const ut8 *b, ut32 lb, ut32 *distance, double *similarity) { const bool verbose = d? d->verbose: false; /* More memory efficient version on Levenshtein Distance from: https://en.wikipedia.org/wiki/Levenshtein_distance http://www.codeproject.com/Articles/13525/Fast-memory-efficient-Levenshtein-algorithm ObM.. */ int i, j; /* TODO: ensure those pointers are allocated */ int *v0 = (int*) calloc ((lb + 1), sizeof (int)); int *v1 = (int*) calloc ((lb + 1), sizeof (int)); if (!a || !b || la < 1 || lb < 1) { free (v0); free (v1); return false; } if (la == lb && !memcmp (a, b, la)) { if (distance) { *distance = 0; } if (similarity) { *similarity = 1.0; } free (v0); free (v1); return true; } for (i = 0; i < lb + 1 ; i++) { v0[i] = i; } for (i = 0; i < la; i++) { v1[0] = i + 1; for (j = 0; j < lb; j++) { int cost = (a[i] == b[j]) ? 0 : 1; int smallest = R_MIN ((v1[j] + 1), (v0[j + 1] + 1)); smallest = R_MIN (smallest, (v0[j] + cost)); v1[j + 1] = smallest; } for (j = 0; j < lb + 1; j++) { v0[j] = v1[j]; } if (verbose && (i % 10000 == 0)) eprintf ("Processing %d of %d\r", i, la - 1); } if (verbose) { eprintf ("\rProcessing %d of %d\n", i, la - 1); } if (distance) { *distance = v1[lb]; if (similarity) { double diff = (double) (*distance) / (double) (R_MAX (la, lb)); *similarity = (double)1 - diff; } } free (v0); free (v1); return true; }
R_API int r_core_rtr_http(RCore *core, int launch, const char *path) { char buf[32]; RSocketHTTPRequest *rs; int iport, oldsandbox = -1; int timeout = r_config_get_i (core->config, "http.timeout"); int x = r_config_get_i (core->config, "scr.html"); int y = r_config_get_i (core->config, "scr.color"); int z = r_config_get_i (core->config, "asm.bytes"); int u = r_config_get_i (core->config, "scr.interactive"); int v = r_config_get_i (core->config, "asm.cmtright"); const char *port = r_config_get (core->config, "http.port"); char *allow = (char *)r_config_get (core->config, "http.allow"); if (core->http_up) { eprintf ("http server is already running\n"); return 1; } if (r_sandbox_enable (0)) { eprintf ("sandbox: connect disabled\n"); return 1; } if (path && atoi (path)) { port = path; path = NULL; } if (!strcmp (port, "0")) { r_num_irand (); iport = 1024+r_num_rand (45256); snprintf (buf, sizeof (buf), "%d", iport); port = buf; } s = r_socket_new (R_FALSE); s->local = !r_config_get_i (core->config, "http.public"); if (!r_socket_listen (s, port, NULL)) { eprintf ("Cannot listen on http.port\n"); return 1; } if (launch) { char cmd[128]; const char *browser = r_config_get (core->config, "http.browser"); snprintf (cmd, sizeof (cmd)-1, "%s http://localhost:%d/%s &", browser, atoi (port), path?path:""); r_sys_cmd (cmd); } r_config_set (core->config, "asm.cmtright", "false"); r_config_set (core->config, "scr.html", "true"); r_config_set (core->config, "scr.color", "false"); r_config_set (core->config, "asm.bytes", "false"); r_config_set (core->config, "scr.interactive", "false"); if (r_config_get_i (core->config, "http.sandbox")) { oldsandbox = r_config_get_i (core->config, "cfg.sandbox"); r_config_set (core->config, "cfg.sandbox", "true"); } eprintf ("Starting http server...\n"); eprintf ("http://localhost:%d/\n", atoi (port)); core->http_up = R_TRUE; while (!r_cons_singleton ()->breaked) { r_cons_break ((RConsBreak)http_break, core); rs = r_socket_http_accept (s, timeout); if (!rs) { if (!s) break; r_sys_usleep (100); continue; } if (allow && *allow) { int accepted = R_FALSE; const char *host; char *p, *peer = r_socket_to_string (rs->s); char *allows = strdup (allow); //eprintf ("Firewall (%s)\n", allows); int i, count = r_str_split (allows, ','); p = strchr (peer, ':'); if (p) *p = 0; for (i=0; i<count; i++) { host = r_str_word_get0 (allows, i); //eprintf ("--- (%s) (%s)\n", host, peer); if (!strcmp (host, peer)) { accepted = R_TRUE; break; } } free (peer); free (allows); if (!accepted) { r_socket_http_close (rs); continue; } } if (!rs->method || !rs->path) { eprintf ("Invalid http headers received from client\n"); r_socket_http_close (rs); continue; } char *dir = NULL; if (r_config_get_i (core->config, "http.dirlist")) if (r_file_is_directory (rs->path)) dir = strdup (rs->path); if (!strcmp (rs->method, "GET")) { if (!memcmp (rs->path, "/up", 3)) { if (r_config_get_i (core->config, "http.upget")) { const char *uproot = r_config_get (core->config, "http.uproot"); if (!rs->path[3] || (rs->path[3]=='/'&&!rs->path[4])) { char *ptr = rtr_dir_files (uproot); r_socket_http_response (rs, 200, ptr, 0, NULL); free (ptr); } else { char *path = r_file_root (uproot, rs->path + 4); if (r_file_exists (path)) { int sz = 0; char *f = r_file_slurp (path, &sz); if (f) { r_socket_http_response (rs, 200, f, sz, NULL); free (f); } else { r_socket_http_response (rs, 403, "Permission denied", 0, NULL); eprintf ("http: Cannot open '%s'\n", path); } } else { if (dir) { char *resp = rtr_dir_files (dir); r_socket_http_response (rs, 404, resp, 0, NULL); free (resp); } else { eprintf ("File '%s' not found\n", path); r_socket_http_response (rs, 404, "File not found\n", 0, NULL); } } free (path); } } else { r_socket_http_response (rs, 403, "Permission denied\n", 0, NULL); } } else if (!memcmp (rs->path, "/cmd/", 5)) { char *cmd = rs->path +5; char foo[32]; const char *httpcmd = r_config_get (core->config, "http.uri"); while (*cmd=='/') cmd++; if (httpcmd && *httpcmd) { int len; char *res; // do remote http query and proxy response snprintf (foo, sizeof (foo), "%s/%s", httpcmd, cmd); res = r_socket_http_get (foo, NULL, &len); if (res) { res[len]=0; r_cons_printf ("%s\n", res); } } else { char *out, *cmd = rs->path+5; r_str_uri_decode (cmd); // eprintf ("CMD (%s)\n", cmd); out = r_core_cmd_str_pipe (core, cmd); // eprintf ("\nOUT LEN = %d\n", strlen (out)); if (out) { char *res = r_str_uri_encode (out); r_socket_http_response (rs, 200, out, 0, "Content-Type: text/plain\n"); free (out); free (res); } else r_socket_http_response (rs, 200, "", 0, NULL); } } else { const char *root = r_config_get (core->config, "http.root"); char *path = r_file_root (root, rs->path); // FD IS OK HERE if (rs->path [strlen (rs->path)-1] == '/') { path = r_str_concat (path, "index.html"); //rs->path = r_str_concat (rs->path, "index.html"); } else { //snprintf (path, sizeof (path), "%s/%s", root, rs->path); if (r_file_is_directory (path)) { char res[128]; snprintf (res, sizeof (res), "Location: %s/\n", rs->path); r_socket_http_response (rs, 302, NULL, 0, res); r_socket_http_close (rs); free (path); free (dir); dir = NULL; continue; } } if (r_file_exists (path)) { int sz = 0; char *f = r_file_slurp (path, &sz); if (f) { const char *contenttype = NULL; if (strstr (path, ".js")) contenttype = "Content-Type: application/javascript\n"; if (strstr (path, ".css")) contenttype = "Content-Type: text/css\n"; if (strstr (path, ".html")) contenttype = "Content-Type: text/html\n"; r_socket_http_response (rs, 200, f, sz, contenttype); free (f); } else { r_socket_http_response (rs, 403, "Permission denied", 0, NULL); eprintf ("http: Cannot open '%s'\n", path); } } else { if (dir) { char *resp = rtr_dir_files (dir); eprintf ("Dirlisting %s\n", dir); r_socket_http_response (rs, 404, resp, 0, NULL); free (resp); } else { eprintf ("File '%s' not found\n", path); r_socket_http_response (rs, 404, "File not found\n", 0, NULL); } } free (path); } } else if (!strcmp (rs->method, "POST")) { ut8 *ret; int retlen; char buf[128]; if (r_config_get_i (core->config, "http.upload")) { ret = r_socket_http_handle_upload ( rs->data, rs->data_length, &retlen); if (ret) { ut64 size = r_config_get_i (core->config, "http.maxsize"); if (size && retlen > size) { r_socket_http_response (rs, 403, "403 File too big\n", 0, NULL); } else { char *filename = r_file_root ( r_config_get (core->config, "http.uproot"), rs->path + 4); eprintf ("UPLOADED '%s'\n", filename); r_file_dump (filename, ret, retlen); free (filename); snprintf (buf, sizeof (buf), "<html><body><h2>uploaded %d bytes. Thanks</h2>\n", retlen); r_socket_http_response (rs, 200, buf, 0, NULL); } free (ret); } } else { r_socket_http_response (rs, 403, "403 Forbidden\n", 0, NULL); } } else { r_socket_http_response (rs, 404, "Invalid protocol", 0, NULL); } r_socket_http_close (rs); free (dir); } core->http_up = R_FALSE; r_socket_free (s); r_cons_break_end (); r_config_set_i (core->config, "scr.html", x); r_config_set_i (core->config, "scr.color", y); r_config_set_i (core->config, "asm.bytes", z); r_config_set_i (core->config, "scr.interactive", u); r_config_set_i (core->config, "asm.cmtright", v); if (oldsandbox != -1) r_config_set_i (core->config, "cfg.sandbox", oldsandbox); return 0; }
static int cmd_project(void *data, const char *input) { RCore *core = (RCore *) data; const char *file, *arg = (input && *input)? input + 1: NULL; const char *fileproject = r_config_get (core->config, "prj.name"); char *str = NULL; if (!input) { return false; } str = strdup (fileproject); arg = strchr (input, ' '); if (arg) { arg++; } else { if (*input) { arg = input + 1; if (*arg == '&') { arg++; } } } file = arg; switch (input[0]) { case 'c': if (input[1] == ' ') { r_core_project_cat (core, input + 2); } else { eprintf ("Usage: Pc [prjname]\n"); } break; case 'o': // if (r_file_is_regular (file)) if (input[1] == '&') { r_core_project_open (core, file, true); } else if (input[1]) { r_core_project_open (core, file, false); } else { if (file && *file) { r_cons_println (file); } } break; case 'l': r_core_project_list (core, input[1]); break; case 'd': case '-': r_core_project_delete (core, file); break; case 's': if (!file || !file[0]) { /* if no argument specified use current project */ file = str; } if (r_core_project_save (core, file)) { r_config_set (core->config, "prj.name", file); r_cons_println (file); } break; case 'S': if (input[1] == ' ') { r_core_project_save_rdb (core, input + 2, R_CORE_PRJ_ALL); } else { eprintf ("Usage: PS [file]\n"); } break; case 'n': if (!fileproject || !*fileproject) { eprintf ("No project\n"); } else { switch (input[1]) { case '-': /* remove lines containing specific words */ { FILE *fd = r_sandbox_fopen (str, "w"); if (!fd) { eprintf ("Cannot open %s\n", str); } else { char *str = r_core_project_notes_file (core, fileproject); char *data = r_file_slurp (str, NULL); int del = 0; if (data) { char *ptr, *nl; for (ptr = data; ptr; ptr = nl) { nl = strchr (ptr, '\n'); if (nl) { *nl++ = 0; if (strstr (ptr, input + 2)) { del++; } else { fprintf (fd, "%s\n", ptr); } } } free (data); } if (del > 0) { eprintf ("Deleted %d lines\n", del); } free (str); fclose (fd); } } break; case ' ': if (input[2] == '-') { char *str = r_core_project_notes_file (core, fileproject); // edit with cfg.editor const char *editor = r_config_get (core->config, "cfg.editor"); if (str && *str && editor && *editor) { r_sys_cmdf ("%s %s", editor, str); } else { eprintf ("No cfg.editor configured\n"); } free (str); } else { //char *str = r_core_project_notes_file (core, fileproject); // append line to project notes char *str = r_core_project_notes_file (core, fileproject); char *data = r_file_slurp (str, NULL); FILE *fd = r_sandbox_fopen (str, "a"); if (fd) { fprintf (fd, "%s\n", input + 2); fclose (fd); } free (str); free (data); } break; case 'j': if (!input[2]) { int len = 0; /* get base64 string */ char *str = r_core_project_notes_file (core, fileproject); if (str) { char *data = r_file_slurp (str, &len); char *res = r_base64_encode_dyn (data, len); if (res) { r_cons_println (res); free (res); } free (data); free (str); } } else if (input[2] == ' ') { /* set base64 string */ ut8 *data = r_base64_decode_dyn (input + 3, -1); if (data) { char *str = r_core_project_notes_file (core, fileproject); if (str) { r_file_dump (str, data, strlen ((const char *) data), 0); free (str); } free (data); } } else { eprintf ("Usage: `Pnj` or `Pnj ...`\n"); } break; case 'x': r_core_project_execute_cmds (core, fileproject); break; case 0: { char *str = r_core_project_notes_file (core, fileproject); char *data = r_file_slurp (str, NULL); if (data) { r_cons_println (data); free (data); } free (str); } break; case '?': { const char *help_msg[] = { "Usage:", "Pn[j-?] [...]", "Project Notes", "Pn", "", "show project notes", "Pn", " -", "edit notes with cfg.editor", "Pn-", "", "delete notes", "Pn-", "str", "delete lines matching /str/ in notes", "Pnx", "", "run project note commands", "Pnj", "", "show notes in base64", "Pnj", " [base64]", "set notes in base64", NULL }; r_core_cmd_help (core, help_msg); } break; } } break; case 'i': if (file && *file) { char *prjName = r_core_project_info (core, file); r_cons_println (prjName); free (prjName); } break; default: { const char *help_msg[] = { "Usage:", "P[?osi] [file]", "Project management", "Pc", " [file]", "show project script to console", "Pd", " [file]", "delete project", "Pi", " [file]", "show project information", "Pl", "", "list all projects", "Pn", "[j]", "show project notes (Pnj for json)", "Pn", " [base64]", "set notes text", "Pn", " -", "edit notes with cfg.editor", "Po", " [file]", "open project", "Ps", " [file]", "save project", "PS", " [file]", "save script file", "P-", " [file]", "delete project (alias for Pd)", "NOTE:", "", "See 'e??prj.'", "NOTE:", "", "project are stored in ~/.config/radare2/projects", NULL }; r_core_cmd_help (core, help_msg); } break; } free (str); return true; }
R_API char* r_egg_Cfile_parser(const char *file, const char *arch, const char *os, int bits) { char *output = NULL; char *fileExt = NULL; // "file" with extension (.s, .text, ...) struct cEnv_t *cEnv = r_egg_Cfile_set_cEnv (arch, os, bits); if (!cEnv) { goto fail; } r_str_sanitize (cEnv->CC); //printf ("==> Compile\n"); printf ("'%s' %s -o '%s.tmp' -S -Os '%s'\n", cEnv->CC, cEnv->CFLAGS, file, file); output = r_sys_cmd_strf ("('%s' %s -o '%s.tmp' -S -Os '%s') 2>&1", cEnv->CC, cEnv->CFLAGS, file, file); if (output == NULL) { eprintf ("Compilation failed!\n"); goto fail; } printf ("%s", output); if (!(fileExt = r_str_newf ("%s.s", file))) { goto fail; } if (!r_file_dump (fileExt, (const ut8*) cEnv->SHDR, strlen (cEnv->SHDR), false)) { eprintf ("Error while opening %s.s\n", file); goto fail; } if (!r_egg_Cfile_parseCompiled (file)) { goto fail; } //printf ("==> Assemble\n"); printf ("'%s' %s -Os -o '%s.o' '%s.s'\n", cEnv->CC, cEnv->LDFLAGS, file, file); free (output); output = r_sys_cmd_strf ("'%s' %s -Os -o '%s.o' '%s.s'", cEnv->CC, cEnv->LDFLAGS, file, file); if (!output) { eprintf ("Assembly failed!\n"); goto fail; } printf ("%s", output); //printf ("==> Link\n"); printf ("rabin2 -o '%s.text' -O d/S/'%s' '%s.o'\n", file, cEnv->TEXT, file); free (output); output = r_sys_cmd_strf ("rabin2 -o '%s.text' -O d/S/'%s' '%s'.o", file, cEnv->TEXT, file); if (!output) { eprintf ("Linkage failed!\n"); goto fail; } free (fileExt); if (!(fileExt = r_str_newf ("%s.o", file))) { goto fail; } if (!r_file_exists (fileExt)) { eprintf ("Cannot find %s.o\n", file); goto fail; } free (fileExt); if (!(fileExt = r_str_newf ("%s.text", file))) { goto fail; } if (r_file_size (fileExt) == 0) { printf ("FALLBACK: Using objcopy instead of rabin2"); free (output); output = r_sys_cmd_strf ("'%s' -j .text -O binary '%s.o' '%s.text'", cEnv->OBJCOPY, file, file); if (!output) { eprintf ("objcopy failed!\n"); goto fail; } } size_t i; const char *extArray[] = {"bin", "tmp", "s", "o"}; for (i = 0; i < 4; i++) { free (fileExt); if (!(fileExt = r_str_newf ("%s.%s", file, extArray[i]))) { goto fail; } r_file_rm (fileExt); } free (fileExt); if ((fileExt = r_str_newf ("%s.text", file)) == NULL) { goto fail; } free (output); r_egg_Cfile_free_cEnv (cEnv); return fileExt; fail: free (fileExt); free (output); r_egg_Cfile_free_cEnv (cEnv); return NULL; }
R_API int r_bin_wr_output(RBin *bin, const char *filename) { return r_file_dump (filename, bin->cur.buf->buf, bin->cur.buf->length); }
/* TODO: simplify using r_write */ static int cmd_write(void *data, const char *input) { ut64 off; ut8 *buf; const char *arg; int wseek, i, size, len = strlen (input); char *tmp, *str, *ostr; RCore *core = (RCore *)data; #define WSEEK(x,y) if (wseek)r_core_seek_delta (x,y) wseek = r_config_get_i (core->config, "cfg.wseek"); str = ostr = strdup (input+1); switch (*input) { case 'h': { char *p = strchr (input, ' '); if (p) { while (*p==' ') p++; p = r_file_path (p); if (p) { r_cons_printf ("%s\n", p); free (p); } } } break; case 'e': { ut64 addr = 0, len = 0, b_size = 0; st64 dist = 0; ut8* bytes = NULL; int cmd_suc = R_FALSE; char *input_shadow = NULL, *p = NULL; switch (input[1]) { case 'n': if (input[2] == ' ') { len = *input ? r_num_math (core->num, input+3) : 0; if (len > 0){ ut64 cur_off = core->offset; cmd_suc = r_core_extend_at (core, core->offset, len); core->offset = cur_off; r_core_block_read (core, 0); } } break; case 'N': if (input[2] == ' ') { input += 3; while (*input && *input == ' ') input++; addr = r_num_math (core->num, input); while (*input && *input != ' ') input++; input++; len = *input ? r_num_math (core->num, input) : 0; if (len > 0){ ut64 cur_off = core->offset; cmd_suc = r_core_extend_at (core, addr, len); cmd_suc = r_core_seek (core, cur_off, 1); core->offset = addr; r_core_block_read (core, 0); } } break; case 'x': if (input[2] == ' ') { input+=2; len = *input ? strlen (input) : 0; bytes = len > 1? malloc (len+1) : NULL; len = bytes ? r_hex_str2bin (input, bytes) : 0; if (len > 0) { ut64 cur_off = core->offset; cmd_suc = r_core_extend_at (core, cur_off, len); if (cmd_suc) { r_core_write_at (core, cur_off, bytes, len); } core->offset = cur_off; r_core_block_read (core, 0); } free (bytes); } break; case 'X': if (input[2] == ' ') { addr = r_num_math (core->num, input+3); input += 3; while (*input && *input != ' ') input++; input++; len = *input ? strlen (input) : 0; bytes = len > 1? malloc (len+1) : NULL; len = bytes ? r_hex_str2bin (input, bytes) : 0; if (len > 0) { //ut64 cur_off = core->offset; cmd_suc = r_core_extend_at (core, addr, len); if (cmd_suc) { r_core_write_at (core, addr, bytes, len); } core->offset = addr; r_core_block_read (core, 0); } free (bytes); } break; case 's': input += 3; while (*input && *input == ' ') input++; len = strlen (input); input_shadow = len > 0? malloc (len+1): 0; // since the distance can be negative, // the r_num_math will perform an unwanted operation // the solution is to tokenize the string :/ if (input_shadow) { strncpy (input_shadow, input, len+1); p = strtok (input_shadow, " "); addr = p && *p ? r_num_math (core->num, p) : 0; p = strtok (NULL, " "); dist = p && *p ? r_num_math (core->num, p) : 0; p = strtok (NULL, " "); b_size = p && *p ? r_num_math (core->num, p) : 0; if (dist != 0){ r_core_shift_block (core, addr, b_size, dist); r_core_seek (core, addr, 1); cmd_suc = R_TRUE; } } free (input_shadow); break; case '?': default: cmd_suc = R_FALSE; } if (cmd_suc == R_FALSE) { r_cons_printf ("|Usage: write extend\n" "wen <num> insert num null bytes at current offset\n" "wex <hex_bytes> insert bytes at current offset\n" "weN <addr> <len> insert bytes at address\n" "weX <addr> <hex_bytes> insert bytes at address\n" "wes <addr> <dist> <block_size> shift a blocksize left or write in the editor\n" ); } } break; case 'p': if (input[1]=='-' || (input[1]==' '&&input[2]=='-')) { const char *tmpfile = ".tmp"; char *out = r_core_editor (core, NULL); if (out) { // XXX hacky .. patch should support str, not only file r_file_dump (tmpfile, (ut8*)out, strlen (out)); r_core_patch (core, tmpfile); r_file_rm (tmpfile); free (out); } } else { if (input[1]==' ' && input[2]) { r_core_patch (core, input+2); } else { eprintf ("Usage: wp [-|r2patch-file]\n" "TODO: rapatch format documentation here\n"); } } break; case 'u': // TODO: implement it in an API RCore.write_unified_hexpatch() is ETOOLONG if (input[1]==' ') { char *data = r_file_slurp (input+2, NULL); if (data) { char sign = ' '; int line = 0, offs = 0, hexa = 0; int newline = 1; for (i=0; data[i]; i++) { switch (data[i]) { case '+': if (newline) sign = 1; break; case '-': if (newline) { sign = 0; offs = i + ((data[i+1]==' ')?2:1); } break; case ' ': data[i] = 0; if (sign) { if (!line) line = i+1; else if (!hexa) hexa = i+1; } break; case '\r': break; case '\n': newline = 1; if (sign == -1) { offs = 0; line = 0; hexa = 0; } else if (sign) { if (offs && hexa) { r_cons_printf ("wx %s @ %s\n", data+hexa, data+offs); } else eprintf ("food\n"); offs = 0; line = 0; } else hexa = 0; sign = -1; continue; } newline = 0; } free (data); } } else { eprintf ("|Usage: wu [unified-diff-patch] # see 'cu'\n"); } break; case 'r': off = r_num_math (core->num, input+1); len = (int)off; if (len>0) { buf = malloc (len); if (buf != NULL) { r_num_irand (); for (i=0; i<len; i++) buf[i] = r_num_rand (256); r_core_write_at (core, core->offset, buf, len); WSEEK (core, len); free (buf); } else eprintf ("Cannot allocate %d bytes\n", len); } break; case 'A': switch (input[1]) { case ' ': if (input[2] && input[3]==' ') { r_asm_set_pc (core->assembler, core->offset); eprintf ("modify (%c)=%s\n", input[2], input+4); len = r_asm_modify (core->assembler, core->block, input[2], r_num_math (core->num, input+4)); eprintf ("len=%d\n", len); if (len>0) { r_core_write_at (core, core->offset, core->block, len); WSEEK (core, len); } else eprintf ("r_asm_modify = %d\n", len); } else eprintf ("Usage: wA [type] [value]\n"); break; case '?': default: r_cons_printf ("|Usage: wA [type] [value]\n" "|Types:\n" "| r raw write value\n" "| v set value (taking care of current address)\n" "| d destination register\n" "| 0 1st src register\n" "| 1 2nd src register\n" "|Example: wA r 0 # e800000000\n"); break; } break; case 'c': switch (input[1]) { case 'i': r_io_cache_commit (core->io); r_core_block_read (core, 0); break; case 'r': r_io_cache_reset (core->io, R_TRUE); /* Before loading the core block we have to make sure that if * the cache wrote past the original EOF these changes are no * longer displayed. */ memset (core->block, 0xff, core->blocksize); r_core_block_read (core, 0); break; case '-': if (input[2]=='*') { r_io_cache_reset (core->io, R_TRUE); } else if (input[2]==' ') { char *p = strchr (input+3, ' '); ut64 to, from = core->offset; if (p) { *p = 0; from = r_num_math (core->num, input+3); to = r_num_math (core->num, input+3); if (to<from) { eprintf ("Invalid range (from>to)\n"); return 0; } } else { from = r_num_math (core->num, input+3); to = from + core->blocksize; } r_io_cache_invalidate (core->io, from, to); } else { eprintf ("Invalidate write cache at 0x%08"PFMT64x"\n", core->offset); r_io_cache_invalidate (core->io, core->offset, core->offset+core->blocksize); } /* See 'r' above. */ memset (core->block, 0xff, core->blocksize); r_core_block_read (core, 0); break; case '?': r_cons_printf ( "|Usage: wc[ir*?]\n" "| wc list all write changes\n" "| wc- [a] [b] remove write op at curseek or given addr\n" "| wc* \"\" in radare commands\n" "| wcr reset all write changes in cache\n" "| wci commit write cache\n" "|NOTE: Requires 'e io.cache=true'\n"); break; case '*': r_io_cache_list (core->io, R_TRUE); break; case '\0': if (!r_config_get_i (core->config, "io.cache")) eprintf ("[warning] e io.cache must be true\n"); r_io_cache_list (core->io, R_FALSE); break; } break; case ' ': /* write string */ len = r_str_unescape (str); r_core_write_at (core, core->offset, (const ut8*)str, len); #if 0 r_io_use_desc (core->io, core->file->desc); r_io_write_at (core->io, core->offset, (const ut8*)str, len); #endif WSEEK (core, len); r_core_block_read (core, 0); break; case 't': if (*str != ' ') { eprintf ("Usage: wt file [size]\n"); } else { tmp = strchr (str+1, ' '); if (tmp) { st64 sz = (st64) r_num_math (core->num, tmp+1); *tmp = 0; if (sz<1) eprintf ("Invalid length\n"); else r_core_dump (core, str+1, core->offset, (ut64)sz); } else r_file_dump (str+1, core->block, core->blocksize); } break; case 'T': eprintf ("TODO: wT // why?\n"); break; case 'f': arg = (const char *)(input+((input[1]==' ')?2:1)); if (!strcmp (arg, "-")) { char *out = r_core_editor (core, NULL); if (out) { r_io_write_at (core->io, core->offset, (ut8*)out, strlen (out)); free (out); } } else if ((buf = (ut8*) r_file_slurp (arg, &size))) { r_io_use_desc (core->io, core->file->desc); r_io_write_at (core->io, core->offset, buf, size); WSEEK (core, size); free (buf); r_core_block_read (core, 0); } else eprintf ("Cannot open file '%s'\n", arg); break; case 'F': arg = (const char *)(input+((input[1]==' ')?2:1)); if (!strcmp (arg, "-")) { int len; ut8 *out; char *in = r_core_editor (core, NULL); if (in) { out = (ut8 *)strdup (in); if (out) { len = r_hex_str2bin (in, out); if (len>0) r_io_write_at (core->io, core->offset, out, len); free (out); } free (in); } } else if ((buf = r_file_slurp_hexpairs (arg, &size))) { r_io_use_desc (core->io, core->file->desc); r_io_write_at (core->io, core->offset, buf, size); WSEEK (core, size); free (buf); r_core_block_read (core, 0); } else eprintf ("Cannot open file '%s'\n", arg); break; case 'w': str++; len = (len-1)<<1; if (len>0) tmp = malloc (len+1); else tmp = NULL; if (tmp) { for (i=0; i<len; i++) { if (i%2) tmp[i] = 0; else tmp[i] = str[i>>1]; } str = tmp; r_io_use_desc (core->io, core->file->desc); r_io_write_at (core->io, core->offset, (const ut8*)str, len); WSEEK (core, len); r_core_block_read (core, 0); free (tmp); } else eprintf ("Cannot malloc %d\n", len); break; case 'x': { int b, len = strlen (input); ut8 *buf = malloc (len+1); len = r_hex_str2bin (input+1, buf); if (len != 0) { if (len<0) len = -len+1; if (len<core->blocksize) { b = core->block[len]&0xf; b |= (buf[len]&0xf0); } else b = buf[len]; buf[len] = b; r_core_write_at (core, core->offset, buf, len); WSEEK (core, len); r_core_block_read (core, 0); } else eprintf ("Error: invalid hexpair string\n"); free (buf); } break; case 'a': switch (input[1]) { case 'o': if (input[2] == ' ') r_core_hack (core, input+3); else r_core_hack_help (core); break; case ' ': case '*': { const char *file = input[1]=='*'? input+2: input+1; RAsmCode *acode; r_asm_set_pc (core->assembler, core->offset); acode = r_asm_massemble (core->assembler, file); if (acode) { if (input[1]=='*') { r_cons_printf ("wx %s\n", acode->buf_hex); } else { if (r_config_get_i (core->config, "scr.prompt")) eprintf ("Written %d bytes (%s) = wx %s\n", acode->len, input+2, acode->buf_hex); r_core_write_at (core, core->offset, acode->buf, acode->len); WSEEK (core, acode->len); r_core_block_read (core, 0); } r_asm_code_free (acode); } } break; case 'f': if ((input[2]==' '||input[2]=='*')) { const char *file = input[2]=='*'? input+4: input+3; RAsmCode *acode; r_asm_set_pc (core->assembler, core->offset); acode = r_asm_assemble_file (core->assembler, file); if (acode) { if (input[2]=='*') { r_cons_printf ("wx %s\n", acode->buf_hex); } else { if (r_config_get_i (core->config, "scr.prompt")) eprintf ("Written %d bytes (%s)=wx %s\n", acode->len, input+1, acode->buf_hex); r_core_write_at (core, core->offset, acode->buf, acode->len); WSEEK (core, acode->len); r_core_block_read (core, 0); } r_asm_code_free (acode); } else eprintf ("Cannot assemble file\n"); } else eprintf ("Wrong argument\n"); break; default: r_cons_printf ("|Usage: wa[of*] [arg]\n" "| wa nop : write nopcode using asm.arch and asm.bits\n" "| wa* mov eax, 33 : show 'wx' op with hexpair bytes of sassembled opcode\n" "| \"wa nop;nop\" : assemble more than one instruction (note the quotes)\n" "| waf foo.asm : assemble file and write bytes\n" "| wao nop : convert current opcode into nops\n" "| wao? : show help for assembler operation on current opcode (hack)\n"); break; } break; case 'b': { int len = strlen (input); ut8 *buf = malloc (len+1); if (buf) { len = r_hex_str2bin (input+1, buf); if (len > 0) { r_mem_copyloop (core->block, buf, core->blocksize, len); r_core_write_at (core, core->offset, core->block, core->blocksize); WSEEK (core, core->blocksize); r_core_block_read (core, 0); } else eprintf ("Wrong argument\n"); free (buf); } else eprintf ("Cannot malloc %d\n", len+1); } break; case 'm': size = r_hex_str2bin (input+1, (ut8*)str); switch (input[1]) { case '\0': eprintf ("Current write mask: TODO\n"); // TODO break; case '?': break; case '-': r_io_set_write_mask (core->io, 0, 0); eprintf ("Write mask disabled\n"); break; case ' ': if (size>0) { r_io_use_desc (core->io, core->file->desc); r_io_set_write_mask (core->io, (const ut8*)str, size); WSEEK (core, size); eprintf ("Write mask set to '"); for (i=0; i<size; i++) eprintf ("%02x", str[i]); eprintf ("'\n"); } else eprintf ("Invalid string\n"); break; } break; case 'v': { int type = 0; ut8 addr1; ut16 addr2; ut32 addr4, addr4_; ut64 addr8; switch (input[1]) { case '?': r_cons_printf ("|Usage: wv[size] [value] # write value of given size\n" "| wv1 234 # write one byte with this value\n" "| wv 0x834002 # write dword with this value\n" "|Supported sizes are: 1, 2, 4, 8\n"); return 0; case '1': type = 1; break; case '2': type = 2; break; case '4': type = 4; break; case '8': type = 8; break; } off = r_num_math (core->num, input+2); r_io_use_desc (core->io, core->file->desc); r_io_seek (core->io, core->offset, R_IO_SEEK_SET); if (type == 0) type = (off&UT64_32U)? 8: 4; switch (type) { case 1: addr1 = (ut8)off; r_io_write (core->io, (const ut8 *)&addr1, 1); WSEEK (core, 1); break; case 2: addr2 = (ut16)off; r_io_write (core->io, (const ut8 *)&addr2, 2); WSEEK (core, 2); break; case 4: addr4_ = (ut32)off; //drop_endian((ut8*)&addr4_, (ut8*)&addr4, 4); /* addr4_ = addr4 */ //endian_memcpy((ut8*)&addr4, (ut8*)&addr4_, 4); /* addr4 = addr4_ */ memcpy ((ut8*)&addr4, (ut8*)&addr4_, 4); // XXX needs endian here too r_io_write (core->io, (const ut8 *)&addr4, 4); WSEEK (core, 4); break; case 8: /* 8 byte addr */ memcpy ((ut8*)&addr8, (ut8*)&off, 8); // XXX needs endian here // endian_memcpy((ut8*)&addr8, (ut8*)&off, 8); r_io_write (core->io, (const ut8 *)&addr8, 8); WSEEK (core, 8); break; } r_core_block_read (core, 0); } break; case 'o': switch (input[1]) { case 'a': case 's': case 'e': case 'A': case 'x': case 'r': case 'l': case 'm': case 'd': case 'o': case 'w': if (input[2]!=' ') { if (input[1]=='e') r_cons_printf ( "Usage: 'woe from-to step'\n"); else r_cons_printf ( "Usage: 'wo%c 00 11 22'\n", input[1]); free (ostr); return 0; } case '2': case '4': r_core_write_op (core, input+3, input[1]); r_core_block_read (core, 0); break; case 'R': r_core_cmd0 (core, "wr $b"); break; case 'n': r_core_write_op (core, "ff", 'x'); r_core_block_read (core, 0); break; case '\0': case '?': default: r_cons_printf ( "|Usage: wo[asmdxoArl24] [hexpairs] @ addr[:bsize]\n" "|Example:\n" "| wox 0x90 ; xor cur block with 0x90\n" "| wox 90 ; xor cur block with 0x90\n" "| wox 0x0203 ; xor cur block with 0203\n" "| woa 02 03 ; add [0203][0203][...] to curblk\n" "| woe 02 03 \n" "|Supported operations:\n" "| wow == write looped value (alias for 'wb')\n" "| woa += addition\n" "| wos -= substraction\n" "| wom *= multiply\n" "| wod /= divide\n" "| wox ^= xor\n" "| woo |= or\n" "| woA &= and\n" "| woR random bytes (alias for 'wr $b'\n" "| wor >>= shift right\n" "| wol <<= shift left\n" "| wo2 2= 2 byte endian swap\n" "| wo4 4= 4 byte endian swap\n" ); break; } break; case 'd': if (input[1]==' ') { char *arg, *inp = strdup (input+2); arg = strchr (inp, ' '); if (arg) { *arg = 0; ut64 addr = r_num_math (core->num, input+2); ut64 len = r_num_math (core->num, arg+1); ut8 *data = malloc (len); r_io_read_at (core->io, addr, data, len); r_io_write_at (core->io, core->offset, data, len); free (data); } else eprintf ("See wd?\n"); free (inp); } else eprintf ("Usage: wd [source-offset] [length] @ [dest-offset]\n"); break; case 's': { ut8 ulen; len = r_str_unescape (str+1); if (len>255) { eprintf ("Too large\n"); } else { ulen = (ut8)len; r_core_write_at (core, core->offset, &ulen, 1); r_core_write_at (core, core->offset+1, (const ut8*)str+1, len); WSEEK (core, len); r_core_block_read (core, 0); } } break; default: case '?': if (core->oobi) { eprintf ("Writing oobi buffer!\n"); r_io_use_desc (core->io, core->file->desc); r_io_write (core->io, core->oobi, core->oobi_len); WSEEK (core, core->oobi_len); r_core_block_read (core, 0); } else r_cons_printf ( "|Usage: w[x] [str] [<file] [<<EOF] [@addr]\n" "| w foobar write string 'foobar'\n" "| wh r2 whereis/which shell command\n" "| wr 10 write 10 random bytes\n" "| ww foobar write wide string 'f\\x00o\\x00o\\x00b\\x00a\\x00r\\x00'\n" "| wa push ebp write opcode, separated by ';' (use '\"' around the command)\n" "| waf file assemble file and write bytes\n" "| wA r 0 alter/modify opcode at current seek (see wA?)\n" "| wb 010203 fill current block with cyclic hexpairs\n" "| wc[ir*?] write cache undo/commit/reset/list (io.cache)\n" "| wd [off] [n] duplicate N bytes from offset at current seek (memcpy) (see y?)\n" "| wx 9090 write two intel nops\n" "| wv eip+34 write 32-64 bit value\n" "| wo? hex write in block with operation. 'wo?' fmi\n" "| wm f0ff set binary mask hexpair to be used as cyclic write mask\n" "| ws pstring write 1 byte for length and then the string\n" "| wf -|file write contents of file at current offset\n" "| wF -|file write contents of hexpairs file here\n" "| wp -|file apply radare patch file. See wp? fmi\n" "| wt file [sz] write to file (from current seek, blocksize or sz bytes)\n" ); //TODO: add support for offset+seek // " wf file o s ; write contents of file from optional offset 'o' and size 's'.\n" break; }
R_API int r_diff_buffers_static(RDiff *d, const ut8 *a, int la, const ut8 *b, int lb) { int i, len; int hit = 0; la = R_ABS(la); lb = R_ABS(lb); if (la != lb) { len = R_MIN(la, lb); fprintf(stderr, "Buffer truncated to %d bytes (%d not compared)\n", len, R_ABS(lb-la)); } else len = la; for(i = 0; i<len; i++) { if (a[i]!=b[i]) { hit++; } else { if (hit>0) { struct r_diff_op_t o = { .a_off = d->off_a+i-hit, .a_buf = a+i-hit, .a_len = hit, .b_off = d->off_b+i-hit, .b_buf = b+i-hit, .b_len = hit }; d->callback (d, d->user, &o); hit = 0; } } } if (hit>0) { struct r_diff_op_t o = { .a_off = d->off_a+i-hit, .a_buf = a+i-hit, .a_len = hit, .b_off = d->off_b+i-hit, .b_buf = b+i-hit, .b_len = hit }; d->callback (d, d->user, &o); hit = 0; } return 0; } // XXX: temporary files are R_API int r_diff_buffers_radiff(RDiff *d, const ut8 *a, int la, const ut8 *b, int lb) { char *ptr, *str, buf[64], oop = 0; int ret, atl, btl, hit; ut8 at[128], bt[128]; ut64 ooa, oob; FILE *fd; hit = atl = btl = 0; ooa = oob = 0LL; oop = -1; r_file_dump (".a", a, la, 0); r_file_dump (".b", b, lb, 0); r_sys_cmd ("radiff -d .a .b | rsc uncolor > .d"); fd = fopen (".d", "r"); while (!feof (fd)) { ut64 oa, ob; // offset int ba, bb = 0; // byte char op; // operation oa = ob = 0LL; if (!fgets (buf, 63, fd)) break; if (feof (fd)) break; str = buf; ptr = strchr (buf, ' '); if (!ptr) continue; *ptr='\0'; sscanf (str, "0x%08"PFMT64x"", &oa); str = r_str_ichr (ptr+1, ' '); if (*str!='|'&&*str!='>'&&*str!='<') { ptr = strchr (str, ' '); if (!ptr) continue; *ptr='\0'; sscanf (str, "%02x", &ba); } else ba = 0; str = r_str_ichr (ptr+1, ' '); ptr = strchr (str, ' '); if (!ptr) continue; *ptr='\0'; sscanf (str, "%c", &op); str = r_str_ichr (ptr+1, ' '); if (str[0]!='0' || str[1]!='x') { ptr = strchr(str, ' '); if (!ptr) continue; *ptr = '\0'; sscanf (str, "%02x", &bb); } str = ptr+1; ptr = strchr (str, '\n'); if (!ptr) continue; *ptr='\0'; sscanf (str, "0x%08"PFMT64x"", &ob); if (oop == op || oop==-1) { if (hit == 0) { ooa = oa; oob = ob; } at[atl] = ba; bt[btl] = bb; switch (op) { case '|': atl++; btl++; break; case '>': btl++; break; case '<': atl++; break; } hit++; } else { if (hit>0) { struct r_diff_op_t o = { .a_off = ooa, .a_buf = at, .a_len = atl, .b_off = oob, .b_buf = bt, .b_len = btl }; ret = d->callback(d, d->user, &o); if (!ret) break; atl = btl = 0; hit = 0; } } oop = op; } if (hit>0) { struct r_diff_op_t o = { .a_off = ooa, .a_buf = at, .a_len = atl, .b_off = oob, .b_buf = bt, .b_len = btl }; if (!d->callback (d, d->user, &o)) { fclose (fd); return 0; } atl = btl = 0; hit = 0; } fclose (fd); unlink (".a"); unlink (".b"); unlink (".d"); return 0; } R_API int r_diff_buffers(RDiff *d, const ut8 *a, ut32 la, const ut8 *b, ut32 lb) { if (d->delta) return r_diff_buffers_delta (d, a, la, b, lb); return r_diff_buffers_static (d, a, la, b, lb); } /* TODO: Move into r_util maybe? */ R_API int r_diff_buffers_distance(RDiff *d, const ut8 *a, ut32 la, const ut8 *b, ut32 lb, ut32 *distance, double *similarity) { int i, j, cost, tmin, **m; if (!a || !b || la < 1 || lb < 1) return R_FALSE; if ((m = malloc ((la+1) * sizeof(int*))) == NULL) return R_FALSE; for(i = 0; i <= la; i++) if ((m[i] = malloc ((lb+1) * sizeof(int))) == NULL) { while (i--) free (m[i]); free (m); return R_FALSE; } for (i = 0; i <= la; i++) m[i][0] = i; for (j = 0; j <= lb; j++) m[0][j] = j; for (i = 1; i <= la; i++) { for (j = 1; j <= lb; j++) { if (a[i-1] == b[j-1]) cost = 0; else cost = 1; tmin = R_MIN (m[i-1][j] + 1, m[i][j-1] + 1); m[i][j] = R_MIN (tmin, m[i-1][j-1] + cost); } } if (distance != NULL) *distance = m[la][lb]; if (similarity != NULL) *similarity = (double)1 - (double)(m[la][lb])/(double)(R_MAX(la, lb)); for(i = 0; i <= la; i++) free (m[i]); free (m); return R_TRUE; }
static int extract_binobj (const RBinFile *bf, const RBinObject *o, int idx ) { ut64 boffset = o ? o->boffset : 0; ut64 bin_size = o ? o->obj_size : 0; const ut8 *bytes = bf ? r_buf_buffer (bf->buf) : NULL; //ut64 sz = bf ? r_buf_size (bf->buf) : 0; RBinInfo *info = o ? o->info : NULL; const char *arch = info ? info->arch : "unknown"; char bits = info ? info->bits : 0; const char *filename = bf ? bf->file : NULL; char *path = NULL, *outpath = NULL, *outfile = NULL, *ptr = NULL; ut32 outfile_sz = 0, outpath_sz = 0; int res = R_FALSE; if (!bf || !o || !filename ) return R_FALSE; path = strdup (filename); // XXX: Wrong for w32 (/) if (r_what_os_am_i () == ON_NIX_OS && (ptr = strrchr (path, '/'))){ *ptr = '\0'; ptr++; } else if ((ptr = strrchr (path, '\\'))) { *ptr = '\0'; ptr++; } else ptr = path; outpath_sz = strlen (path) + 20; if (outpath_sz) outpath = malloc (outpath_sz); if (outpath) snprintf (outpath, outpath_sz, "%s.fat", ptr); if (!outpath || !r_sys_rmkdir (outpath)) { free (path); free (outpath); eprintf ("Error creating dir structure\n"); return R_FALSE; } outfile_sz = outpath_sz + strlen (ptr) + strlen (arch) + 3 + 10 + 10; if (outfile_sz) outfile = malloc (outfile_sz); if (outfile) snprintf (outfile, outfile_sz, "%s/%s.%s_%i.%d", outpath, ptr, arch, bits, idx); if (!outfile || !r_file_dump (outfile, bytes+boffset, bin_size)) { eprintf ("Error extracting %s\n", outfile); res = R_FALSE; } else { printf ("%s created (%"PFMT64d")\n", outfile, bin_size); res = R_TRUE; } free (outfile); free (outpath); free (path); return res; }
int main(int argc, char **argv) { int c, bits = 0; int action = ACTION_UNK; const char *op = NULL; char *arch = NULL, *arch_name = NULL; ut64 offset; bin = r_bin_new (); l = r_lib_new ("radare_plugin"); r_lib_add_handler (l, R_LIB_TYPE_BIN, "bin plugins", &__lib_bin_cb, &__lib_bin_dt, NULL); r_lib_add_handler (l, R_LIB_TYPE_BIN_XTR, "bin xtr plugins", &__lib_bin_xtr_cb, &__lib_bin_xtr_dt, NULL); { /* load plugins everywhere */ char *homeplugindir = r_str_home (".radare/plugins"); r_lib_opendir (l, getenv ("LIBR_PLUGINS")); r_lib_opendir (l, homeplugindir); r_lib_opendir (l, LIBDIR"/radare2/"); } while ((c = getopt (argc, argv, "Af:a:B:b:c:CdMm:n:@:VisSzIHelRwO:o:p:rvLhx")) != -1) { switch(c) { case 'A': action |= ACTION_LISTARCHS; break; case 'a': if (optarg) arch = strdup (optarg); break; case 'c': if (!optarg) { eprintf ("Missing argument for -c"); return 1; } action = ACTION_CREATE; create = strdup (optarg); break; case 'C': action |= ACTION_CLASSES; break; case 'f': if (optarg) arch_name = strdup (optarg); break; case 'b': bits = r_num_math (NULL, optarg); break; case 'm': at = r_num_math (NULL, optarg); action |= ACTION_SRCLINE; break; case 'i': action |= ACTION_IMPORTS; break; case 's': action |= ACTION_SYMBOLS; break; case 'S': action |= ACTION_SECTIONS; break; case 'z': action |= ACTION_STRINGS; break; case 'I': action |= ACTION_INFO; break; case 'H': action |= ACTION_FIELDS; break; case 'd': action |= ACTION_DWARF; break; case 'e': action |= ACTION_ENTRIES; break; case 'M': action |= ACTION_MAIN; break; case 'l': action |= ACTION_LIBS; break; case 'R': action |= ACTION_RELOCS; break; case 'x': action |= ACTION_EXTRACT; break; case 'w': rw = R_TRUE; break; case 'O': op = optarg; action |= ACTION_OPERATION; if (optind==argc) { eprintf ("Missing filename\n"); return 1; } // return rabin_do_operation (op); break; case 'o': output = optarg; break; case 'r': rad = R_TRUE; break; case 'v': va = R_TRUE; break; case 'L': r_bin_list (bin); return 1; case 'B': gbaddr = r_num_math (NULL, optarg); break; case '@': at = r_num_math (NULL, optarg); break; case 'n': name = optarg; break; case 'V': printf ("rabin2 v"R2_VERSION"\n"); return 0; case 'h': default: action |= ACTION_HELP; } } file = argv[optind]; if (action == ACTION_HELP || action == ACTION_UNK || file == NULL) return rabin_show_help (); if (arch) { char *ptr; ptr = strchr (arch, '_'); if (ptr) { *ptr = '\0'; bits = r_num_math (NULL, ptr+1); } } if (action & ACTION_CREATE) { // TODO: move in a function outside RBuffer *b; int datalen, codelen; ut8 *data = NULL, *code = NULL; char *p2, *p = strchr (create, ':'); if (!p) { eprintf ("Invalid format for -c flag. Use 'format:codehexpair:datahexpair'\n"); return 1; } *p++ = 0; p2 = strchr (p, ':'); if (p2) { // has data *p2++ = 0; data = malloc (strlen (p2)); datalen = r_hex_str2bin (p2, data); } else { data = NULL; datalen = 0; } code = malloc (strlen (p)); codelen = r_hex_str2bin (p, code); if (!arch) arch = "x86"; if (!bits) bits = 32; if (!r_bin_use_arch (bin, arch, bits, create)) { eprintf ("Cannot set arch\n"); return 1; } b = r_bin_create (bin, code, codelen, data, datalen); if (b) { if (r_file_dump (file, b->buf, b->length)) { eprintf ("dumped %d bytes in '%s'\n", b->length, file); r_file_chmod (file, "+x", 0); } else eprintf ("error dumping into a.out\n"); r_buf_free (b); } else eprintf ("Cannot create binary for this format '%s'.\n", create); r_bin_free (bin); return 0; } if (!r_bin_load (bin, file, R_FALSE) && !r_bin_load (bin, file, R_TRUE)) { eprintf ("r_bin: Cannot open '%s'\n", file); return 1; } if (action & ACTION_LISTARCHS || ((arch || bits || arch_name) && !r_bin_select (bin, arch, bits, arch_name))) { r_bin_list_archs (bin); free (arch); free (arch_name); r_bin_free (bin); return 1; } if (gbaddr != 0LL) bin->curarch.baddr = gbaddr; RCore core; core.bin = bin; RCoreBinFilter filter; filter.offset = at; filter.name = name; offset = r_bin_get_offset (bin); r_cons_new ()->is_interactive = R_FALSE; if (action&ACTION_SECTIONS) r_core_bin_info (&core, R_CORE_BIN_ACC_SECTIONS, rad, va, &filter, 0); if (action&ACTION_ENTRIES) r_core_bin_info (&core, R_CORE_BIN_ACC_ENTRIES, rad, va, NULL, offset); if (action&ACTION_MAIN) r_core_bin_info (&core, R_CORE_BIN_ACC_MAIN, rad, va, NULL, offset); if (action&ACTION_IMPORTS) r_core_bin_info (&core, R_CORE_BIN_ACC_IMPORTS, rad, va, &filter, offset); if (action&ACTION_CLASSES) r_core_bin_info (&core, R_CORE_BIN_ACC_CLASSES, rad, va, NULL, 0); if (action&ACTION_SYMBOLS) r_core_bin_info (&core, R_CORE_BIN_ACC_SYMBOLS, rad, va, &filter, offset); if (action&ACTION_STRINGS) r_core_bin_info (&core, R_CORE_BIN_ACC_STRINGS, rad, va, NULL, 0); if (action&ACTION_INFO) r_core_bin_info (&core, R_CORE_BIN_ACC_INFO, rad, va, NULL, 0); if (action&ACTION_FIELDS) r_core_bin_info (&core, R_CORE_BIN_ACC_FIELDS, rad, va, NULL, 0); if (action&ACTION_LIBS) r_core_bin_info (&core, R_CORE_BIN_ACC_LIBS, rad, va, NULL, 0); if (action&ACTION_RELOCS) r_core_bin_info (&core, R_CORE_BIN_ACC_RELOCS, rad, va, NULL, 0); if (action&ACTION_DWARF) rabin_show_dwarf (&core); if (action&ACTION_SRCLINE) rabin_show_srcline (at); if (action&ACTION_EXTRACT) rabin_extract ((arch==NULL && arch_name==NULL && bits==0)); if (op != NULL && action&ACTION_OPERATION) rabin_do_operation (op); free (arch); r_bin_free (bin); r_cons_flush (); return 0; }
int main(int argc, char **argv) { const char *query = NULL; int c, bits = 0, actions_done = 0, actions = 0, action = ACTION_UNK; char *homeplugindir = r_str_home (R2_HOMEDIR"/plugins"); char *ptr, *arch = NULL, *arch_name = NULL; const char *op = NULL; RCoreBinFilter filter; RCore core; RCoreFile *cf = NULL; int xtr_idx = 0; // load all files if extraction is necessary. int fd = -1; int rawstr = 0; r_core_init (&core); bin = core.bin; l = r_lib_new ("radare_plugin"); r_lib_add_handler (l, R_LIB_TYPE_BIN, "bin plugins", &__lib_bin_cb, &__lib_bin_dt, NULL); r_lib_add_handler (l, R_LIB_TYPE_BIN_XTR, "bin xtr plugins", &__lib_bin_xtr_cb, &__lib_bin_xtr_dt, NULL); /* load plugins everywhere */ r_lib_opendir (l, getenv ("LIBR_PLUGINS")); r_lib_opendir (l, homeplugindir); r_lib_opendir (l, LIBDIR"/radare2/"R2_VERSION); #define is_active(x) (action&x) #define set_action(x) actions++; action |=x while ((c = getopt (argc, argv, "jgqAf:a:B:b:c:Ck:dMm:n:N:@:isSIHelRwO:o:rvLhxzZ")) != -1) { switch (c) { case 'g': set_action (ACTION_CLASSES); set_action (ACTION_IMPORTS); set_action (ACTION_SYMBOLS); set_action (ACTION_SECTIONS); set_action (ACTION_STRINGS); set_action (ACTION_SIZE); set_action (ACTION_INFO); set_action (ACTION_FIELDS); set_action (ACTION_DWARF); set_action (ACTION_ENTRIES); set_action (ACTION_MAIN); set_action (ACTION_LIBS); set_action (ACTION_RELOCS); set_action (ACTION_EXTRACT); break; case 'q': rad = R_CORE_BIN_SIMPLE; break; case 'j': rad = R_CORE_BIN_JSON; break; case 'A': set_action (ACTION_LISTARCHS); break; case 'a': if (optarg) arch = optarg; break; case 'c': if (!optarg) { eprintf ("Missing argument for -c"); return 1; } set_action (ACTION_CREATE); create = strdup (optarg); break; case 'k': query = optarg; break; case 'C': set_action (ACTION_CLASSES); break; case 'f': if (optarg) arch_name = strdup (optarg); break; case 'b': bits = r_num_math (NULL, optarg); break; case 'm': at = r_num_math (NULL, optarg); set_action (ACTION_SRCLINE); break; case 'i': set_action (ACTION_IMPORTS); break; case 's': set_action (ACTION_SYMBOLS); break; case 'S': set_action (ACTION_SECTIONS); break; case 'z': if (is_active (ACTION_STRINGS)) { rawstr = R_TRUE; } else set_action (ACTION_STRINGS); break; case 'Z': set_action (ACTION_SIZE); break; case 'I': set_action (ACTION_INFO); break; case 'H': set_action (ACTION_FIELDS); break; case 'd': set_action (ACTION_DWARF); break; case 'e': set_action (ACTION_ENTRIES); break; case 'M': set_action (ACTION_MAIN); break; case 'l': set_action (ACTION_LIBS); break; case 'R': set_action (ACTION_RELOCS); break; case 'x': set_action (ACTION_EXTRACT); break; case 'w': rw = R_TRUE; break; case 'O': op = optarg; set_action (ACTION_OPERATION); if (op && !strcmp (op, "help")) { printf ("Operation string:\n" " Dump symbols: d/s/1024\n" " Dump section: d/S/.text\n" " Resize section: r/.data/1024\n"); return 0; } if (optind==argc) { eprintf ("Missing filename\n"); return 1; } break; case 'o': output = optarg; break; case 'r': rad = R_TRUE; break; case 'v': va = R_TRUE; break; case 'L': r_bin_list (bin); return 1; case 'B': baddr = r_num_math (NULL, optarg); break; case '@': at = r_num_math (NULL, optarg); break; case 'n': name = optarg; break; case 'N': bin->minstrlen = r_num_math (NULL, optarg); break; //case 'V': return blob_version ("rabin2"); case 'h': return rabin_show_help (1); default: action |= ACTION_HELP; } } file = argv[optind]; if (!query) if (action & ACTION_HELP || action == ACTION_UNK || file == NULL) { if (va) return blob_version ("rabin2"); return rabin_show_help (0); } if (arch) { ptr = strchr (arch, '_'); if (ptr) { *ptr = '\0'; bits = r_num_math (NULL, ptr+1); } } if (action & ACTION_CREATE) { // TODO: move in a function outside RBuffer *b; int datalen, codelen; ut8 *data = NULL, *code = NULL; char *p2, *p = strchr (create, ':'); if (!p) { eprintf ("Invalid format for -c flag. Use 'format:codehexpair:datahexpair'\n"); return 1; } *p++ = 0; p2 = strchr (p, ':'); if (p2) { // has data *p2++ = 0; data = malloc (strlen (p2)+1); datalen = r_hex_str2bin (p2, data); } else { data = NULL; datalen = 0; } code = malloc (strlen (p)+1); if (!code) { return 1; } codelen = r_hex_str2bin (p, code); if (!arch) arch = "x86"; if (!bits) bits = 32; if (!r_bin_use_arch (bin, arch, bits, create)) { eprintf ("Cannot set arch\n"); return 1; } b = r_bin_create (bin, code, codelen, data, datalen); if (b) { if (r_file_dump (file, b->buf, b->length)) { eprintf ("dumped %d bytes in '%s'\n", b->length, file); r_file_chmod (file, "+x", 0); } else eprintf ("error dumping into a.out\n"); r_buf_free (b); } else eprintf ("Cannot create binary for this format '%s'.\n", create); r_bin_free (bin); return 0; } r_config_set_i (core.config, "bin.rawstr", rawstr); cf = r_core_file_open (&core, file, R_IO_READ, 0); fd = cf ? r_core_file_cur_fd (&core) : -1; if (!cf || fd == -1) { eprintf ("r_core: Cannot open file\n"); return 1; } if (!r_bin_load (bin, file, baddr, 0, xtr_idx, fd, rawstr)) { if (!r_bin_load (bin, file, baddr, 0, xtr_idx, fd, rawstr)) { eprintf ("r_bin: Cannot open file\n"); return 1; } } if (query) { if (!strcmp (query, "-")) { __sdb_prompt (bin->cur->sdb); } else sdb_query (bin->cur->sdb, query); return 0; } // XXX: TODO move this to libr/core/bin.c if (action & ACTION_LISTARCHS || ((arch || bits || arch_name) && !r_bin_select (bin, arch, bits, arch_name))) { if (rad == R_CORE_BIN_JSON) { int i; printf ("["); for (i = 0; i < bin->narch; i++) { if (r_bin_select_idx (bin, bin->file, i)) { RBinObject *o = r_bin_cur_object (bin); RBinInfo *info = o ? o->info : NULL; printf ("%s{\"arch\":\"%s\",\"bits\":%d," "\"offset\":%"PFMT64d",\"machine\":\"%s\"}", i?",":"",info->arch, info->bits, bin->cur->offset, info->machine); } } printf ("]"); } else r_bin_list_archs (bin, 1); free (arch_name); } if (baddr != 0LL) { r_bin_set_baddr (bin, baddr); bin->cur->o->baddr = baddr; } core.bin = bin; filter.offset = at; filter.name = name; r_cons_new ()->is_interactive = R_FALSE; #define isradjson (rad==R_CORE_BIN_JSON&&actions>0) #define run_action(n,x,y) {\ if (action&x) {\ if (isradjson) r_cons_printf ("\"%s\":",n);\ if (!r_core_bin_info (&core, y, rad, va, &filter, 0)) {\ if (isradjson) r_cons_printf("false");\ };\ actions_done++;\ if (isradjson) r_cons_printf (actions==actions_done? "":",");\ }\ } if (isradjson) r_cons_printf ("{"); run_action ("sections", ACTION_SECTIONS, R_CORE_BIN_ACC_SECTIONS); run_action ("entries", ACTION_ENTRIES, R_CORE_BIN_ACC_ENTRIES); run_action ("main", ACTION_MAIN, R_CORE_BIN_ACC_MAIN); run_action ("imports", ACTION_IMPORTS, R_CORE_BIN_ACC_IMPORTS); run_action ("classes", ACTION_CLASSES, R_CORE_BIN_ACC_CLASSES); run_action ("symbols", ACTION_SYMBOLS, R_CORE_BIN_ACC_SYMBOLS); run_action ("strings", ACTION_STRINGS, R_CORE_BIN_ACC_STRINGS); run_action ("info", ACTION_INFO, R_CORE_BIN_ACC_INFO); run_action ("fields", ACTION_FIELDS, R_CORE_BIN_ACC_FIELDS); run_action ("libs", ACTION_LIBS, R_CORE_BIN_ACC_LIBS); run_action ("relocs", ACTION_RELOCS, R_CORE_BIN_ACC_RELOCS); run_action ("dwarf", ACTION_DWARF, R_CORE_BIN_ACC_DWARF); run_action ("size", ACTION_SIZE, R_CORE_BIN_ACC_SIZE); if (action&ACTION_SRCLINE) rabin_show_srcline (at); if (action&ACTION_EXTRACT) rabin_extract ((arch==NULL && arch_name==NULL && bits==0)); if (op != NULL && action&ACTION_OPERATION) rabin_do_operation (op); if (isradjson) printf ("}"); r_cons_flush (); r_core_fini (&core); return 0; }
R_API int r_run_start(RRunProfile *p) { #if LIBC_HAVE_FORK if (p->_execve) { exit (execv (p->_program, (char* const*)p->_args)); } #endif #if __APPLE__ && !__POWERPC__ && LIBC_HAVE_FORK posix_spawnattr_t attr = {0}; pid_t pid = -1; int ret; posix_spawnattr_init (&attr); if (p->_args[0]) { char **envp = r_sys_get_environ(); ut32 spflags = 0; //POSIX_SPAWN_START_SUSPENDED; spflags |= POSIX_SPAWN_SETEXEC; if (p->_aslr == 0) { #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 spflags |= _POSIX_SPAWN_DISABLE_ASLR; } (void)posix_spawnattr_setflags (&attr, spflags); if (p->_bits) { size_t copied = 1; cpu_type_t cpu; #if __i386__ || __x86_64__ cpu = CPU_TYPE_I386; if (p->_bits == 64) { cpu |= CPU_ARCH_ABI64; } #else cpu = CPU_TYPE_ANY; #endif posix_spawnattr_setbinpref_np ( &attr, 1, &cpu, &copied); } ret = posix_spawnp (&pid, p->_args[0], NULL, &attr, p->_args, envp); switch (ret) { case 0: break; case 22: eprintf ("posix_spawnp: Invalid argument\n"); break; case 86: eprintf ("posix_spawnp: Unsupported architecture\n"); break; default: eprintf ("posix_spawnp: unknown error %d\n", ret); perror ("posix_spawnp"); break; } exit (ret); } #endif if (p->_system) { if (p->_pid) { eprintf ("PID: Cannot determine pid with 'system' directive. Use 'program'.\n"); } exit (r_sys_cmd (p->_system)); } if (p->_program) { if (!r_file_exists (p->_program)) { char *progpath = r_file_path (p->_program); if (progpath && *progpath) { free (p->_program); p->_program = progpath; } else { free (progpath); eprintf ("rarun2: %s: file not found\n", p->_program); return 1; } } #if __UNIX__ // XXX HACK close all non-tty fds { int i; for (i = 3; i < 10; i++) { close (i); } } // TODO: use posix_spawn if (p->_setgid) { int ret = setgid (atoi (p->_setgid)); if (ret < 0) { return 1; } } if (p->_pid) { eprintf ("PID: %d\n", getpid ()); } if (p->_pidfile) { char pidstr[32]; snprintf (pidstr, sizeof (pidstr), "%d\n", getpid ()); r_file_dump (p->_pidfile, (const ut8*)pidstr, strlen (pidstr), 0); } #endif if (p->_nice) { #if __UNIX__ && !defined(__HAIKU__) if (nice (p->_nice) == -1) { return 1; } #else eprintf ("nice not supported for this platform\n"); #endif } // TODO: must be HAVE_EXECVE #if LIBC_HAVE_FORK exit (execv (p->_program, (char* const*)p->_args)); #endif } if (p->_runlib) { if (!p->_runlib_fcn) { eprintf ("No function specified. Please set runlib.fcn\n"); return 1; } void *addr = r_lib_dl_open (p->_runlib); if (!addr) { eprintf ("Could not load the library '%s'\n", p->_runlib); return 1; } void (*fcn)(void) = r_lib_dl_sym (addr, p->_runlib_fcn); if (!fcn) { eprintf ("Could not find the function '%s'\n", p->_runlib_fcn); return 1; } switch (p->_argc) { case 0: fcn (); break; case 1: r_run_call1 (fcn, p->_args[1]); break; case 2: r_run_call2 (fcn, p->_args[1], p->_args[2]); break; case 3: r_run_call3 (fcn, p->_args[1], p->_args[2], p->_args[3]); break; case 4: r_run_call4 (fcn, p->_args[1], p->_args[2], p->_args[3], p->_args[4]); break; case 5: r_run_call5 (fcn, p->_args[1], p->_args[2], p->_args[3], p->_args[4], p->_args[5]); break; case 6: r_run_call6 (fcn, p->_args[1], p->_args[2], p->_args[3], p->_args[4], p->_args[5], p->_args[6]); break; case 7: r_run_call7 (fcn, p->_args[1], p->_args[2], p->_args[3], p->_args[4], p->_args[5], p->_args[6], p->_args[7]); break; case 8: r_run_call8 (fcn, p->_args[1], p->_args[2], p->_args[3], p->_args[4], p->_args[5], p->_args[6], p->_args[7], p->_args[8]); break; case 9: r_run_call9 (fcn, p->_args[1], p->_args[2], p->_args[3], p->_args[4], p->_args[5], p->_args[6], p->_args[7], p->_args[8], p->_args[9]); break; case 10: r_run_call10 (fcn, p->_args[1], p->_args[2], p->_args[3], p->_args[4], p->_args[5], p->_args[6], p->_args[7], p->_args[8], p->_args[9], p->_args[10]); break; default: eprintf ("Too many arguments.\n"); return 1; } r_lib_dl_close (addr); } return 0; }