R_API int r_socket_spawn (RSocket *s, const char *cmd, unsigned int timeout) { // XXX TODO: dont use sockets, we can achieve the same with pipes const int port = 2000 + r_num_rand (2000); int childPid = r_sys_fork(); if (childPid == 0) { char *a = r_str_replace (strdup (cmd), "\\", "\\\\", true); r_sys_cmdf ("rarun2 system=\"%s\" listen=%d", a, port); free (a); #if 0 // TODO: use the api char *profile = r_str_newf ( "system=%s\n" "listen=%d\n", cmd, port); RRunProfile *rp = r_run_new (profile); r_run_start (rp); r_run_free (rp); free (profile); #endif eprintf ("r_socket_spawn: %s is dead\n", cmd); exit (0); } r_sys_sleep (1); r_sys_usleep (timeout); char aport[32]; sprintf (aport, "%d", port); // redirect stdin/stdout/stderr return r_socket_connect (s, "127.0.0.1", aport, R_SOCKET_PROTO_TCP, 2000); }
// TODO: support len for binary data? R_API char *r_core_rtr_cmds_query (RCore *core, const char *host, const char *port, const char *cmd) { int retries = 6; unsigned char buf[1024]; char *rbuf = NULL; const int timeout = 0; RSocket *s = r_socket_new (0); for (;retries>0; r_sys_usleep (10*1000)) { if (r_socket_connect (s, host, port, R_SOCKET_PROTO_TCP, timeout)) break; retries--; } if (retries>0) { rbuf = strdup (""); r_socket_write (s, (void*)cmd, strlen (cmd)); //r_socket_write (s, "px\n", 3); for (;;) { int ret = r_socket_read (s, buf, sizeof (buf)); if (ret<1) break; buf[ret] = 0; rbuf = r_str_concat (rbuf, (const char *)buf); } } else { eprintf ("Cannot connect\n"); } r_socket_free (s); return rbuf; }
int main() { int ret; char buf[1024]; RSocket *s = r_socket_new (R_FALSE); if (r_socket_connect (s, "localhost", "9090", 0, 10)) { do { ret = r_socket_gets (s, buf, sizeof (buf)); eprintf ("((%s))\n", buf); } while (ret>=0); } r_socket_free (s); }
static void http_break (void *u) { RSocket* sock; const char *port; const int timeout = 1; // 1 second RCore *core = (RCore*)u; if (((size_t)u)>0xff) { port = listenport? listenport: r_config_get (core->config, "http.port"); sock = r_socket_new (0); r_socket_connect (sock, "localhost", port, R_SOCKET_PROTO_TCP, timeout); r_socket_free (sock); } r_socket_free (s); s = NULL; }
R_API bool r_socket_spawn(RSocket *s, const char *cmd, unsigned int timeout) { // XXX TODO: dont use sockets, we can achieve the same with pipes const int port = 2000 + r_num_rand (2000); int childPid = r_sys_fork (); if (childPid == 0) { char *a = r_str_replace (strdup (cmd), "\\", "\\\\", true); int res = r_sys_cmdf ("rarun2 system=\"%s\" listen=%d", a, port); free (a); #if 0 // TODO: use the api char *profile = r_str_newf ( "system=%s\n" "listen=%d\n", cmd, port); RRunProfile *rp = r_run_new (profile); r_run_start (rp); r_run_free (rp); free (profile); #endif if (res != 0) { eprintf ("r_socket_spawn: rarun2 failed\n"); exit (1); } eprintf ("r_socket_spawn: %s is dead\n", cmd); exit (0); } r_sys_sleep (1); r_sys_usleep (timeout); char aport[32]; sprintf (aport, "%d", port); // redirect stdin/stdout/stderr bool sock = r_socket_connect (s, "127.0.0.1", aport, R_SOCKET_PROTO_TCP, 2000); if (!sock) { return false; } #if __UNIX__ r_sys_sleep (4); r_sys_usleep (timeout); int status = 0; int ret = waitpid (childPid, &status, WNOHANG); if (ret != 0) { r_socket_close (s); return false; } #endif return true; }
/* 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; }