static int r_cmd_yara_scan(const RCore* core) { RListIter* rules_it; YR_RULES* rules; void* to_scan; int result; const unsigned int to_scan_size = r_io_size (core->io); if (to_scan_size < 1) { eprintf ("Invalid file size\n"); return R_FALSE; } to_scan = malloc (to_scan_size); if (!to_scan) { eprintf ("Something went wrong during memory allocation\n"); return R_FALSE; } result = r_io_read_at (core->io, 0L, to_scan, to_scan_size); if (!result) { eprintf ("Something went wrong during r_io_read_at\n"); free (to_scan); return R_FALSE; } r_list_foreach (rules_list, rules_it, rules) { yr_rules_scan_mem (rules, to_scan, to_scan_size, 0, callback, NULL, 0); }
static ut8 *slurp(RCore **c, const char *file, int *sz) { RIODesc *d; RIO *io; if (c && file && strstr (file, "://")) { ut8 *data = NULL; ut64 size; if (!*c) { *c = opencore (NULL); } io = (*c)->io; d = r_io_open (io, file, 0, 0); if (!d) { return NULL; } size = r_io_size (io); if (size > 0 || size < ST32_MAX) { data = calloc (1, size); if (r_io_read_at (io, 0, data, size) == size) { if (sz) { *sz = size; } } else { eprintf ("slurp: read error\n"); R_FREE (data); } } else { eprintf ("slurp: File is too big\n"); } r_io_close (io, d); return data; } return (ut8*)r_file_slurp (file, sz); }
R_API ut64 r_io_desc_size(RIO *io, RIODesc *desc){ RIODesc *old = NULL; ut64 sz = -1; if (desc && io->desc != desc){ old = io->desc; r_io_use_desc (io, desc); } if (desc) sz = r_io_size(io); if (old) r_io_use_desc (io, old); return sz; }
static bool flagbar_foreach(RFlagItem *fi, void *user) { struct flagbar_t *u = (struct flagbar_t *)user; ut64 min = 0, max = r_io_size (u->core->io); RIOMap *m = r_io_map_get (u->core->io, fi->offset); if (m) { min = m->itv.addr; max = m->itv.addr + m->itv.size; } r_cons_printf ("0x%08"PFMT64x" ", fi->offset); r_print_rangebar (u->core->print, fi->offset, fi->offset + fi->size, min, max, u->cols); r_cons_printf (" %s\n", fi->name); return true; }
R_API int r_core_write_at(RCore *core, ut64 addr, const ut8 *buf, int size) { int ret; if (!core->io || !core->file || size<1) return R_FALSE; ret = r_io_set_fd (core->io, core->file->fd); if (ret != -1) { ret = r_io_write_at (core->io, addr, buf, size); if (addr >= core->offset && addr <= core->offset+core->blocksize) r_core_block_read (core, 0); } core->file->size = r_io_size (core->io); return (ret==-1)? R_FALSE: R_TRUE; }
R_API ut64 r_io_desc_size(RIO *io, RIODesc *desc){ RIODesc *old = NULL; ut64 sz = -1; if (desc && io->fd != desc){ old = io->fd; r_io_set_fd(io, desc); } if (desc) sz = r_io_size(io); if(old){ r_io_set_fd(io, old); } return sz; }
static int perform_mapped_file_yank (RCore *core, ut64 offset, ut64 len, const char *filename) { // grab the current file descriptor, so we can reset core and io state // after our io op is done RIODesc *yankfd = NULL; ut64 fd = core->file ? core->file->desc->fd : -1, yank_file_sz = 0, loadaddr = 0, addr = offset; int res = R_FALSE; if (filename && *filename) { ut64 load_align = r_config_get_i (core->config, "file.loadalign"); RIOMap * map = NULL; yankfd = r_io_open (core->io, filename, R_IO_READ, 0644); // map the file in for IO operations. if (yankfd && load_align) { yank_file_sz = r_io_size (core->io); map = r_io_map_add_next_available (core->io, yankfd->fd, R_IO_READ, 0, 0, yank_file_sz, load_align); loadaddr = map ? map->from : -1; if (yankfd && map && loadaddr != -1) { // ***NOTE*** this is important, we need to // address the file at its physical address! addr += loadaddr; } else if (yankfd) { eprintf ("Unable to map the opened file: %s", filename); r_io_close (core->io, yankfd); yankfd = NULL; } else { eprintf ("Unable to open the file: %s", filename); } } } // if len is -1 then we yank in everything if (len == -1) len = yank_file_sz; IFDBG eprintf ("yankfd: %p, yank->fd = %d, fd=%d\n", yankfd, (int)(yankfd ? yankfd->fd : -1), (int)fd); // this wont happen if the file failed to open or the file failed to // map into the IO layer if (yankfd) { ut64 res = r_io_seek (core->io, addr, R_IO_SEEK_SET), actual_len = len <= yank_file_sz ? len : 0; ut8 *buf = NULL; IFDBG eprintf ( "Addr (%"PFMT64d ") file_sz (%"PFMT64d ") actual_len (%"PFMT64d ") len (%"PFMT64d ") bytes from file: %s\n", addr, yank_file_sz, actual_len, len, filename); if (actual_len > 0 && res == addr) { IFDBG eprintf ( "Creating buffer and reading %"PFMT64d " bytes from file: %s\n", actual_len, filename); buf = malloc (actual_len); actual_len = r_io_read_at (core->io, addr, buf, actual_len); IFDBG eprintf ( "Reading %"PFMT64d " bytes from file: %s\n", actual_len, filename); /*IFDBG { int i = 0; eprintf ("Read these bytes from file: \n"); for (i = 0; i < actual_len; i++) eprintf ("%02x", buf[i]); eprintf ("\n"); }*/ r_core_yank_set (core, R_CORE_FOREIGN_ADDR, buf, len); res = R_TRUE; } else if (res != addr) { eprintf ( "ERROR: Unable to yank data from file: (loadaddr (0x%" PFMT64x ") (addr (0x%" PFMT64x ") > file_sz (0x%"PFMT64x ")\n", res, addr, yank_file_sz ); } else if (actual_len == 0) { eprintf ( "ERROR: Unable to yank from file: addr+len (0x%" PFMT64x ") > file_sz (0x%"PFMT64x ")\n", addr+len, yank_file_sz ); } r_io_close (core->io, yankfd); free (buf); } if (fd != -1) { r_io_raise (core->io, fd); core->switch_file_view = 1; r_core_block_read (core, 0); } return res; }
static int do_hash(const char *file, const char *algo, RIO *io, int bsize, int rad, int ule) { ut64 j, fsize, algobit = r_hash_name_to_bits (algo); RHash *ctx; ut8 *buf; int i, first = 1; if (algobit == R_HASH_NONE) { eprintf ("rahash2: Invalid hashing algorithm specified\n"); return 1; } fsize = r_io_size (io); if (fsize <1) { eprintf ("rahash2: Invalid file size\n"); return 1; } if (bsize<0) bsize = fsize / -bsize; if (bsize == 0 || bsize > fsize) bsize = fsize; if (to == 0LL) to = fsize; if (from>to) { eprintf ("rahash2: Invalid -f -t range\n"); return 1; } if (fsize == -1LL) { eprintf ("rahash2: Unknown file size\n"); return 1; } buf = malloc (bsize+1); if (!buf) return 1; ctx = r_hash_new (R_TRUE, algobit); if (rad == 'j') printf ("["); if (incremental) { for (i=1; i<0x800000; i<<=1) { if (algobit & i) { int hashbit = i & algobit; int dlen = r_hash_size (hashbit); r_hash_do_begin (ctx, i); if (rad == 'j') { if (first) { first = 0; } else { printf (","); } } if (s.buf && s.prefix) { do_hash_internal (ctx, hashbit, s.buf, s.len, rad, 0, ule); } for (j=from; j<to; j+=bsize) { int len = ((j+bsize)>to)? (to-j): bsize; r_io_pread (io, j, buf, len); do_hash_internal (ctx, hashbit, buf, len, rad, 0, ule); } if (s.buf && !s.prefix) { do_hash_internal (ctx, hashbit, s.buf, s.len, rad, 0, ule); } r_hash_do_end (ctx, i); if (iterations>0) r_hash_do_spice (ctx, i, iterations, _s); if (!*r_hash_name (i)) continue; if (!quiet && rad != 'j') printf ("%s: ", file); do_hash_print (ctx, i, dlen, rad, ule); } } if (_s) free (_s->buf); } else { /* iterate over all algorithm bits */ if (s.buf) eprintf ("Warning: Seed ignored on per-block hashing.\n"); for (i=1; i<0x800000; i<<=1) { ut64 f, t, ofrom, oto; if (algobit & i) { int hashbit = i & algobit; ofrom = from; oto = to; f = from; t = to; for (j=f; j<t; j+=bsize) { int nsize = (j+bsize<fsize)? bsize: (fsize-j); r_io_pread (io, j, buf, bsize); from = j; to = j+bsize; if (to>fsize) to = fsize; do_hash_internal (ctx, hashbit, buf, nsize, rad, 1, ule); } from = ofrom; to = oto; } } } if (rad == 'j') printf ("]\n"); r_hash_free (ctx); free (buf); return 0; }
static int do_hash(const char *algo, RIO *io, int bsize, int rad) { ut8 *buf; RHash *ctx; ut64 j, fsize; int i; ut64 algobit = r_hash_name_to_bits (algo); if (algobit == R_HASH_NONE) { eprintf ("Invalid hashing algorithm specified\n"); return 1; } fsize = r_io_size (io); if (bsize == 0 || bsize > fsize) bsize = fsize; if (to == 0LL) to = fsize; if (from>to) { eprintf ("Invalid -f -t range\n"); return 1; } if (fsize == -1LL) { eprintf ("Unknown file size\n"); return 1; } buf = malloc (bsize+1); ctx = r_hash_new (R_TRUE, algobit); if (incremental) { for (i=1; i<0x800000; i<<=1) { if (algobit & i) { int hashbit = i & algobit; int dlen = r_hash_size (hashbit); r_hash_do_begin (ctx, i); for (j=from; j<to; j+=bsize) { r_io_read_at (io, j, buf, bsize); do_hash_internal (ctx, hashbit, buf, ((j+bsize)<fsize)? bsize: (fsize-j), rad, 0); } r_hash_do_end (ctx, i); do_hash_print (ctx, i, dlen, rad); } } } else { /* iterate over all algorithm bits */ for (i=1; i<0x800000; i<<=1) { ut64 f, t, ofrom, oto; if (algobit & i) { int hashbit = i & algobit; ofrom = from; oto = to; f = from; t = to; for (j=f; j<t; j+=bsize) { int nsize = (j+bsize<fsize)? bsize: (fsize-j); r_io_read_at (io, j, buf, bsize); from = j; to = j+bsize; do_hash_internal (ctx, hashbit, buf, nsize, rad, 1); } from = ofrom; to = oto; } } } r_hash_free (ctx); free (buf); return 0; }
static int perform_mapped_file_yank(RCore *core, ut64 offset, ut64 len, const char *filename) { // grab the current file descriptor, so we can reset core and io state // after our io op is done RIODesc *yankdesc = NULL; ut64 fd = core->file? core->file->fd: -1, yank_file_sz = 0, loadaddr = 0, addr = offset; int res = false; if (filename && *filename) { ut64 load_align = r_config_get_i (core->config, "file.loadalign"); RIOMap *map = NULL; yankdesc = r_io_open_nomap (core->io, filename, R_PERM_R, 0644); // map the file in for IO operations. if (yankdesc && load_align) { yank_file_sz = r_io_size (core->io); map = r_io_map_add_next_available (core->io, yankdesc->fd, R_PERM_R, 0, 0, yank_file_sz, load_align); loadaddr = map? map->itv.addr: -1; if (yankdesc && map && loadaddr != -1) { // ***NOTE*** this is important, we need to // address the file at its physical address! addr += loadaddr; } else if (yankdesc) { eprintf ("Unable to map the opened file: %s", filename); r_io_desc_close (yankdesc); yankdesc = NULL; } else { eprintf ("Unable to open the file: %s", filename); } } } // if len is -1 then we yank in everything if (len == -1) { len = yank_file_sz; } // this wont happen if the file failed to open or the file failed to // map into the IO layer if (yankdesc) { ut64 res = r_io_seek (core->io, addr, R_IO_SEEK_SET); ut64 actual_len = len <= yank_file_sz? len: 0; ut8 *buf = NULL; if (actual_len > 0 && res == addr) { buf = malloc (actual_len); if (!r_io_read_at (core->io, addr, buf, actual_len)) { actual_len = 0; } r_core_yank_set (core, R_CORE_FOREIGN_ADDR, buf, len); res = true; } else if (res != addr) { eprintf ( "ERROR: Unable to yank data from file: (loadaddr (0x%" PFMT64x ") (addr (0x%" PFMT64x ") > file_sz (0x%"PFMT64x ")\n", res, addr, yank_file_sz ); } else if (actual_len == 0) { eprintf ( "ERROR: Unable to yank from file: addr+len (0x%" PFMT64x ") > file_sz (0x%"PFMT64x ")\n", addr + len, yank_file_sz ); } r_io_desc_close (yankdesc); free (buf); } if (fd != -1) { r_io_use_fd (core->io, fd); core->switch_file_view = 1; r_core_block_read (core); } return res; }
static int rafind_open_file(char *file) { const char *kw; RListIter *iter; bool last = false; int ret; if (!quiet) { printf ("File: %s\n", file); } if (identify) { char *cmd = r_str_newf ("r2 -e search.show=false -e search.maxhits=1 -nqcpm '%s'", file); r_sandbox_system (cmd, 1); free (cmd); return 0; } io = r_io_new (); fd = r_io_open_nomap (io, file, R_PERM_R, 0); if (!fd) { eprintf ("Cannot open file '%s'\n", file); return 1; } r_cons_new (); rs = r_search_new (mode); if (!rs) { return 1; } buf = calloc (1, bsize); if (!buf) { eprintf ("Cannot allocate %"PFMT64d" bytes\n", bsize); return 1; } rs->align = align; r_search_set_callback (rs, &hit, buf); if (to == -1) { to = r_io_size(io); } if (mode == R_SEARCH_STRING) { /* TODO: implement using api */ r_sys_cmdf ("rabin2 -qzzz '%s'", file); return 0; } if (mode == R_SEARCH_MAGIC) { char *tostr = (to && to != UT64_MAX)? r_str_newf ("-e search.to=%"PFMT64d, to): strdup (""); char *cmd = r_str_newf ("r2" " -e search.in=range" " -e search.align=%d" " -e search.from=%"PFMT64d " %s -qnc/m '%s'", align, from, tostr, file); r_sandbox_system (cmd, 1); free (cmd); free (tostr); return 0; } if (mode == R_SEARCH_ESIL) { char *cmd; r_list_foreach (keywords, iter, kw) { cmd = r_str_newf ("r2 -qc \"/E %s\" %s", kw, file); r_sandbox_system (cmd, 1); free (cmd); }
/* TODO: simplify using r_write */ static int cmd_write(void *data, const char *input) { int wseek, i, size, len; 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", "wao"," [?] op","modify opcode (change conditional of jump. nop, etc)", "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", "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[f]"," [?] file [sz]","write to file (from current seek, blocksize or sz bytes)", "wts"," host:port [sz]", "send data to remote host:port via tcp://", "ww"," foobar","write wide string 'f\\x00o\\x00o\\x00b\\x00a\\x00r\\x00'", "wx","[?][fs] 9090","write two intel nops (from wxfile or wxseek)", "wv","[?] eip+34","write 32-64 bit value", "wz"," string","write zero terminated string (like w + \\x00)", NULL }; if (!input) { return 0; } len = strlen (input); wseek = r_config_get_i (core->config, "cfg.wseek"); str = ostr = strdup (*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_at (core->io, core->offset, buf, len); r_core_block_read (core); 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; ut8 *buf = NULL; int len = 0, str_len; const char *str; if (input[1] && input[2] != ' ') fail = 1; 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); const int bin_len = r_hex_str2bin (str, bin_buf); if (bin_len <= 0) { fail = 1; } else { buf = calloc (str_len + 1, 4); 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); 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_println (p); free (p); } } } break; case 'e': { ut64 addr = 0, len = 0, b_size = 0; st64 dist = 0; ut8* bytes = NULL; int cmd_suc = 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) { const ut64 cur_off = core->offset; cmd_suc = r_core_extend_at (core, core->offset, len); core->offset = cur_off; r_core_block_read (core); } } 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); } } 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); } 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); } 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 = true; } } free (input_shadow); break; case '?': default: cmd_suc = false; } if (cmd_suc == false) { const char* help_msg[] = { "Usage", "", "write extend", "wen", " <num>", "insert num null bytes at current offset", "wex", " <hex_bytes>", "insert bytes at current offset", "weN", " <addr> <len>", "insert bytes at address", "weX", " <addr> <hex_bytes>", "insert bytes at address", "wes", " <addr> <dist> <block_size>", "shift a blocksize left or write in the editor", NULL}; r_core_cmd_help (core, help_msg); } } 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 { r_cons_printf ("Usage: wp [-|r2patch-file]\n" " ^# -> comments\n" " . -> execute command\n" " ! -> execute command\n" " OFFSET { code block }\n" " OFFSET \"string\"\n" " OFFSET 01020304\n" " OFFSET : assembly\n" " + {code}|\"str\"|0210|: asm\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': //wr 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: { const char* help_msg[] = { "Usage:", " wA", "[type] [value]", "Types", "", "", "r", "", "raw write value", "v", "", "set value (taking care of current address)", "d", "", "destination register", "0", "", "1st src register", "1", "", "2nd src register", "Example:", "wA r 0", "# e800000000", NULL}; r_core_cmd_help (core, help_msg); break; } } break; case 'c': switch (input[1]) { case 'i': r_io_cache_commit (core->io, 0, UT64_MAX); r_core_block_read (core); break; case 'r': r_io_cache_reset (core->io, 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); break; case '+': if (input[2]=='*') { //r_io_cache_reset (core->io, true); eprintf ("TODO\n"); } else if (input[2]==' ') { char *p = strchr (input+3, ' '); ut64 to, from; from = r_num_math (core->num, input+3); if (p) { *p = 0; to = r_num_math (core->num, input+3); if (to<from) { eprintf ("Invalid range (from>to)\n"); return 0; } } else { 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, true); } else if (input[2]==' ') { char *p = strchr (input+3, ' '); ut64 to, from; 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); 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, 1); break; case 'j': r_io_cache_list (core->io, 2); 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, 0); break; } break; case ' ': // "w" /* 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); break; case 'z': // "wz" /* write zero-terminated string */ len = r_str_unescape (str); r_core_write_at (core, core->offset, (const ut8*)str + 1, len); if (len > 0) { core->num->value = len; } else { core->num->value = 0; } #if 0 r_io_use_desc (core->io, core->file->desc); #endif WSEEK (core, len + 1); r_core_block_read (core); break; case 't': // "wt" if (*str == 's') { // "wts" if (str[1] == ' ') { eprintf ("Write to server\n"); st64 sz = r_io_size (core->io); if (sz > 0) { ut64 addr = 0; char *host = str + 2; char *port = strchr (host, ':'); if (port) { *port ++= 0; char *space = strchr (port, ' '); if (space) { *space++ = 0; sz = r_num_math (core->num, space); addr = core->offset; } ut8 *buf = calloc (1, sz); r_io_read_at (core->io, addr, buf, sz); RSocket *s = r_socket_new (false); if (r_socket_connect (s, host, port, R_SOCKET_PROTO_TCP, 0)) { int done = 0; eprintf ("Transfering file to the end-point...\n"); while (done < sz) { int rc = r_socket_write (s, buf + done, sz - done); if (rc <1) { eprintf ("oops\n"); break; } done += rc; } } else { eprintf ("Cannot connect\n"); } r_socket_free (s); free (buf); } else { eprintf ("Usage wts host:port [sz]\n"); } } else { eprintf ("Unknown file size\n"); } } else { eprintf ("Usage wts host:port [sz]\n"); } } else if (*str == '?' || *str == '\0') { const char* help_msg[] = { "Usage:", "wt[a] file [size]", " Write 'size' bytes in current blok to 'file'", "wta", " [filename]", "append to 'filename'", "wtf", " [filename] [size]", "write to file (see also 'wxf' and 'wf?')", "wtf!", " [filename]", "write to file from current addresss to eof", NULL}; r_core_cmd_help (core, help_msg); free (ostr); return 0; } else { bool append = false; bool toend = false; st64 sz = core->blocksize; if (*str == 'f') { // "wtf" str++; if (*str == '!') { toend = true; str++; } if (*str) { filename = str + ((*str == ' ')? 1: 0); } else { filename = ""; } } else 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 (!filename || !*filename) { const char* prefix = r_config_get (core->config, "cfg.prefixdump"); snprintf (_fn, sizeof (_fn), "%s.0x%08"PFMT64x, prefix, core->offset); filename = _fn; } if (tmp) { if (toend) { sz = r_io_desc_size (core->io, core->file->desc) - core->offset; } else { 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 (toend) { sz = r_io_desc_size (core->io, core->file->desc) - core->offset; 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': cmd_wf (core, input); break; case 'w': str++; len = (len - 1) << 1; tmp = (len > 0) ? malloc (len + 1) : 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); free (tmp); } else { eprintf ("Cannot malloc %d\n", len); } break; case 'x': // "wx" switch (input[1]) { case 'f': // "wxf" arg = (const char *)(input + ((input[2]==' ')? 3: 2)); 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); core->num->value = len; } else { core->num->value = 0; } free (out); } free (in); } } else if (r_file_exists (arg)) { if ((buf = r_file_slurp_hexpairs (arg, &size))) { r_io_use_desc (core->io, core->file->desc); if (r_io_write_at (core->io, core->offset, buf, size) > 0) { core->num->value = size; WSEEK (core, size); } free (buf); r_core_block_read (core); } else { eprintf ("This file doesnt contains hexpairs\n"); } } else { eprintf ("Cannot open file '%s'\n", arg); } break; case 's': // "wxs" { int len = cmd_write_hexpair (core, input + 2); if (len > 0) { r_core_seek_delta (core, len); core->num->value = len; } else { core->num->value = 0; } } break; case ' ': // "wx ..." cmd_write_hexpair (core, input + 1); break; default: { const char* help_msg[] = { "Usage:", "wx[f] [arg]", "", "wx", " 9090", "write two intel nops", "wxf", " -|file", "write contents of hexpairs file here", "wxs", " 9090", "write hexpairs and seek at the end", NULL}; r_core_cmd_help (core, help_msg); break; } } break; case 'a': // "wa" switch (input[1]) { case 'o': // "wao" 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]=='*') { cmd_write_hexpair(core, 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); } r_asm_code_free (acode); } } break; case 'f': // "wof" 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]=='*') { cmd_write_hexpair(core, 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); } r_asm_code_free (acode); } else eprintf ("Cannot assemble file\n"); } else eprintf ("Wrong argument\n"); break; default: { const char* help_msg[] = { "Usage:", "wa[of*] [arg]", "", "wa", " nop", "write nopcode using asm.arch and asm.bits", "wa*", " mov eax, 33", "show 'wx' op with hexpair bytes of assembled opcode", "\"wa nop;nop\"", "" , "assemble more than one instruction (note the quotes)", "waf", "foo.asm" , "assemble file and write bytes", "wao?", "", "show help for assembler operation on current opcode (hack)", NULL}; r_core_cmd_help (core, help_msg); break; } } break; case 'b': // "wb" { 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); } 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); } } 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); } else { r_core_cmd_help (core, help_msg); } break; }
R_API int r_core_shift_block(RCore *core, ut64 addr, ut64 b_size, st64 dist) { // bstart - block start, fstart file start ut64 fend = 0, fstart = 0, bstart = 0, file_sz = 0; ut8 * shift_buf = NULL; int res = false; if (!core->io || !core->file) { return false; } if (b_size == 0 || b_size == (ut64) -1) { r_io_use_fd (core->io, core->file->fd); file_sz = r_io_size (core->io); if (file_sz == UT64_MAX) { file_sz = 0; } #if 0 bstart = r_io_seek (core->io, addr, R_IO_SEEK_SET); fend = r_io_seek (core->io, 0, R_IO_SEEK_END); if (fend < 1) { fend = 0; } #else bstart = 0; fend = file_sz; #endif fstart = file_sz - fend; b_size = fend > bstart ? fend - bstart: 0; } if ((st64)b_size < 1) { return false; } shift_buf = calloc (b_size, 1); if (!shift_buf) { eprintf ("Cannot allocated %d byte(s)\n", (int)b_size); return false; } // cases // addr + b_size + dist > file_end //if ( (addr+b_size) + dist > file_end ) { // res = false; //} // addr + b_size + dist < file_start (should work since dist is signed) //else if ( (addr+b_size) + dist < 0 ) { // res = false; //} // addr + dist < file_start if (addr + dist < fstart) { res = false; // addr + dist > file_end } else if ( (addr) + dist > fend) { res = false; } else { r_io_use_fd (core->io, core->file->fd); r_io_read_at (core->io, addr, shift_buf, b_size); r_io_write_at (core->io, addr + dist, shift_buf, b_size); res = true; } r_core_seek (core, addr, 1); free (shift_buf); return res; }