static void objc_analyze(RCore *core) { eprintf ("[+] Analyzing searching references to selref\n"); r_core_cmd0 (core, "aar"); if (!strcmp ("arm", r_config_get (core->config, "asm.arch"))) { bool emu_lazy = r_config_get_i (core->config, "emu.lazy"); r_config_set_i (core->config, "emu.lazy", true); r_core_cmd0 (core, "aae"); r_config_set_i (core->config, "emu.lazy", emu_lazy); } }
static void r_core_debug_breakpoint_hit(RCore *core, RBreakpointItem *bpi) { const char *cmdbp; int oecho = core->cons->echo; // should be configurable by user? core->cons->echo = 1; // should be configurable by user? cmdbp = r_config_get (core->config, "cmd.bp"); if (cmdbp && *cmdbp) r_core_cmd0 (core, cmdbp); r_core_cmd0 (core, bpi->data); core->cons->echo = oecho; }
static void objc_analyze(RCore *core) { static const char *oldstr = NULL; oldstr = r_print_rowlog (core->print, "Analyzing searching references to selref"); r_core_cmd0 (core, "aar"); if (!strcmp ("arm", r_config_get (core->config, "asm.arch"))) { bool emu_lazy = r_config_get_i (core->config, "emu.lazy"); r_config_set_i (core->config, "emu.lazy", true); r_core_cmd0 (core, "aae"); r_config_set_i (core->config, "emu.lazy", emu_lazy); } r_print_rowlog_done (core->print, oldstr); }
static RCore* opencore(const char *f) { const ut64 baddr = UT64_MAX; RCore *c = r_core_new (); if (!c) return NULL; r_core_loadlibs (c, R_CORE_LOADLIBS_ALL, NULL); r_config_set_i (c->config, "io.va", useva); r_config_set_i (c->config, "anal.split", true); if (f) { if (!r_core_file_open (c, f, 0, 0)) { r_core_free (c); return NULL; } r_core_bin_load (c, NULL, baddr); } // TODO: must enable io.va here if wanted .. r_config_set_i (c->config, "io.va", va); if (f && anal_all) { const char *cmd = "aac"; switch (anal_all) { case 1: cmd = "aaa"; break; case 2: cmd = "aaaa"; break; } r_core_cmd0 (c, cmd); } return c; }
static bool run_commands(RList *cmds, RList *files, bool quiet) { RListIter *iter; const char *cmdn; const char *file; int ret; /* -i */ r_list_foreach (files, iter, file) { if (!r_file_exists (file)) { eprintf ("Script '%s' not found.\n", file); return false; } ret = r_core_run_script (&r, file); if (ret == -2) { eprintf ("Cannot open '%s'\n", file); } if (ret < 0 || (ret == 0 && quiet)) { r_cons_flush (); return false; } } /* -c */ r_list_foreach (cmds, iter, cmdn) { r_core_cmd0 (&r, cmdn); r_cons_flush (); }
static int r_core_visual_hud(RCore *core) { const char *f = R2_LIBDIR"/radare2/"R2_VERSION"/hud/main"; char *homehud = r_str_home (R2_HOMEDIR"/hud"); char *res = NULL; char *p = 0; showcursor (core, R_TRUE); if (homehud) res = r_cons_hud_file (homehud); if (!res) { if (r_file_exists (f)) res = r_cons_hud_file (f); else r_cons_message ("Cannot find hud file"); } r_cons_clear (); if (res) { p = strchr (res, '\t'); core->printidx = 1; r_cons_printf ("%s\n", res); r_cons_flush (); if (p) r_core_cmd0 (core, p+1); free (res); } showcursor (core, R_FALSE); r_cons_flush (); free (homehud); return (int)(size_t)p; }
R_API void r_core_visual_seek_animation (RCore *core, ut64 addr) { if (r_config_get_i (core->config, "scr.feedback")<1) return; #if 0 int i, ns = 90000; const char *scmd = (addr > core->offset)? "so": "s-4"; for (i=0;i<5;i++) { r_core_cmd0 (core, scmd); r_core_visual_refresh (core); r_cons_flush(); r_sys_usleep (ns); ns -= 1000; } r_core_seek (core, addr, 1); #else if (core->offset == addr) return; r_cons_gotoxy (1, 2); if (addr>core->offset) { r_cons_printf (".----.\n"); r_cons_printf ("| \\/ |\n"); r_cons_printf ("'----'\n"); } else { r_cons_printf (".----.\n"); r_cons_printf ("| /\\ |\n"); r_cons_printf ("'----'\n"); } r_cons_flush(); r_sys_usleep (90000); #endif r_core_seek (core, addr, 1); }
R_API int r_core_visual_hud(RCore *core) { const char *c = r_config_get (core->config, "hud.path"); const char *f = R2_LIBDIR"/radare2/"R2_VERSION"/hud/main"; char *homehud = r_str_home (R2_HOMEDIR"/hud"); char *res = NULL; char *p = 0; showcursor (core, true); if (c && *c && r_file_exists (c)) res = r_cons_hud_file (c); if (!res && homehud) res = r_cons_hud_file (homehud); if (!res && r_file_exists (f)) res = r_cons_hud_file (f); if (!res) r_cons_message ("Cannot find hud file"); r_cons_clear (); if (res) { p = strchr (res, '\t'); r_cons_printf ("%s\n", res); r_cons_flush (); if (p) r_core_cmd0 (core, p+1); free (res); } showcursor (core, false); r_cons_flush (); free (homehud); return (int)(size_t)p; }
R_API int r_core_patch (RCore *core, const char *patch) { char *p, *p0, *str; ut64 noff = 0LL; p = p0 = str = strdup (patch); if (!p) { return 0; } for (; *p; p++) { /* read until newline */ if (!*p || *p == '\n') { *p++ = 0; } else { continue; } switch (*str) { case '#': case '\n': case '\r': case '\0': break; case ':': r_core_cmd0 (core, str+1); break; case '.': case '!': r_core_cmd0 (core, str); break; case '{': (void)__core_patch_bracket (core, str, &noff); break; default: r_core_patch_line (core, str); break; } if (!*p) { break; } str = p; } // eprintf ("%d\n", *p); // eprintf ("Missing newline\n"); free (p0); return 0; }
R_API void r_anal_type_match(RCore *core, RAnalFunction *fcn) { bool esil_var[STATES_SIZE] = {false}; if (!core ) { return; } if (!r_anal_emul_init (core, esil_var) || !fcn ) { r_anal_emul_restore (core, esil_var); return; } const char *pc = r_reg_get_name (core->anal->reg, R_REG_NAME_PC); ut64 addr = fcn->addr; r_reg_setv (core->dbg->reg, pc, fcn->addr); r_debug_reg_sync (core->dbg, -1, true); r_cons_break (NULL, NULL); while (!r_cons_is_breaked ()) { RAnalOp *op = r_core_anal_op (core, addr); int loop_count = sdb_num_get ( core->anal->esil->db_trace, sdb_fmt (-1, "0x%"PFMT64x".count", addr), 0); if (loop_count > LOOP_MAX) { eprintf ("Unfortunately your evilly engineered %s function trapped my most innocent `aftm` in an infinite loop.\n", fcn->name); eprintf ("I kept trace log for you to review and find out how bad things were going to happen by yourself.\n"); eprintf ("You can view this log by `ate`. Meanwhile, I will train on how to behave with such behaviour without bothering you.\n"); return; } sdb_num_set (core->anal->esil->db_trace, sdb_fmt (-1, "0x%"PFMT64x".count", addr), loop_count + 1, 0); if (!op || op->type == R_ANAL_OP_TYPE_RET) { r_anal_emul_restore (core, esil_var); return; } if (op->type == R_ANAL_OP_TYPE_CALL) { RAnalFunction *fcn_call = r_anal_get_fcn_in (core->anal, op->jump, -1); //eprintf ("in the middle of %s\n", fcn_call->name); if (fcn_call) { type_match (core, addr, fcn_call->name); } else { eprintf ("Cannot find function at 0x%08"PFMT64x"\n", op->jump); } addr += op->size; r_anal_op_free (op); r_reg_setv (core->dbg->reg, pc, addr); r_debug_reg_sync (core->dbg, -1, true); r_anal_esil_set_pc (core->anal->esil, addr); addr += stack_clean (core, addr, fcn); r_reg_setv (core->dbg->reg, pc, addr); r_debug_reg_sync (core->dbg, -1, true); r_anal_esil_set_pc (core->anal->esil, addr); continue; } else { r_core_esil_step (core, UT64_MAX, NULL); r_anal_op_free (op); } r_core_cmd0 (core, ".ar*"); addr = r_reg_getv (core->anal->reg, pc); } r_cons_break_end (); r_anal_emul_restore (core, esil_var); }
static void visual_offset (RCore *core) { char buf[256]; r_line_set_prompt ("[offset]> "); strcpy (buf, "s "); if (r_cons_fgets (buf+2, sizeof (buf)-3, 0, NULL) >0) { if (buf[2]=='.')buf[1]='.'; r_core_cmd0 (core, buf); } }
static int config_iova_callback(void *user, void *data) { RCore *core = (RCore *) user; RConfigNode *node = (RConfigNode *) data; if (node->i_value != core->io->va) { core->io->va = node->i_value; r_core_block_read (core, 0); // reload symbol information r_core_cmd0 (core, ".ia*"); } return R_TRUE; }
static int on_fcn_delete (void *_anal, void* _user, RAnalFunction *fcn) { RCore *core = (RCore*)_user; const char *cmd = r_config_get (core->config, "cmd.fcn.delete"); if (cmd && *cmd) { ut64 oaddr = core->offset; ut64 addr = fcn->addr; r_core_seek (core, addr, 1); r_core_cmd0 (core, cmd); r_core_seek (core, oaddr, 1); } return 0; }
R_API int r_core_hack_x86(RCore *core, const char *op, const RAnalOp *analop) { const ut8 *b = core->block; const int size = analop->size; if (!strcmp (op, "nop")) { if (size * 2 + 1 < size) return false; char *str = malloc (size * 2 + 1); if (!str) return false; int i; for (i = 0; i < size; i++) memcpy(str + (i * 2), "90", 2); str[size*2] = '\0'; r_core_cmdf(core, "wx %s\n", str); free(str); } else if (!strcmp (op, "trap")) { r_core_cmd0 (core, "wx cc\n"); } else if (!strcmp (op, "jz")) { if (b[0] == 0x75) { r_core_cmd0 (core, "wx 74\n"); } else { eprintf ("Current opcode is not conditional\n"); return false; } } else if (!strcmp (op, "jnz")) { if (b[0] == 0x74) { r_core_cmd0 (core, "wx 75\n"); } else { eprintf ("Current opcode is not conditional\n"); return false; } } else if (!strcmp (op, "un-cjmp")) { if (b[0] >= 0x70 && b[0] <= 0x7f) { r_core_cmd0 (core, "wx eb\n"); } else { eprintf ("Current opcode is not conditional\n"); return false; } } else if (!strcmp (op, "swap-cjmp")) { if (b[0] < 0x80 && b[0] >= 0x70){ // jo, jno, jb, jae, je, jne, jbe, ja, js, jns r_core_cmdf (core, "wx %x\n", (b[0]%2)? b[0] - 1: b[0] + 1); } else { eprintf ("Invalid opcode\n"); return false; } } else if (!strcmp (op, "ret1")) { r_core_cmd0 (core, "wx c20100\n"); } else if (!strcmp (op, "ret0")) { r_core_cmd0 (core, "wx c20000\n"); } else if (!strcmp (op, "retn")) { r_core_cmd0 (core, "wx c2ffff\n"); } else { eprintf ("Invalid operation\n"); return false; } return true; }
static int on_fcn_rename(void *_anal, void* _user, RAnalFunction *fcn, const char *oname) { RCore *core = (RCore*)_user; const char *cmd = r_config_get (core->config, "cmd.fcn.rename"); if (cmd && *cmd) { // XXX: wat do with old name here? ut64 oaddr = core->offset; ut64 addr = fcn->addr; r_core_seek (core, addr, 1); r_core_cmd0 (core, cmd); r_core_seek (core, oaddr, 1); } return 0; }
R_API void r_core_log_add(RCore *core, const char *msg) { static bool inProcess = false; r_strpool_append (core->log->sp, msg); core->log->last++; if (core->cmdlog && *core->cmdlog) { if (inProcess) { // avoid infinite recursive calls return; } inProcess = true; r_core_cmd0 (core, core->cmdlog); inProcess = false; } }
static int textlog_chat(RCore *core) { char prompt[64]; char buf[1024]; int lastmsg = 0; const char *me = r_config_get (core->config, "cfg.user"); char msg[1024]; eprintf ("Type '/help' for commands:\n"); snprintf (prompt, sizeof (prompt) - 1, "[%s]> ", me); r_line_set_prompt (prompt); for (;;) { r_core_log_list (core, lastmsg, 0, 0); lastmsg = core->log->last; if (r_cons_fgets (buf, sizeof (buf) - 1, 0, NULL) < 0) { return 1; } if (!*buf) { continue; } if (!strcmp (buf, "/help")) { eprintf ("/quit quit the chat (same as ^D)\n"); eprintf ("/name <nick> set cfg.user name\n"); eprintf ("/log show full log\n"); eprintf ("/clear clear text log messages\n"); } else if (!strncmp (buf, "/name ", 6)) { snprintf (msg, sizeof (msg) - 1, "* '%s' is now known as '%s'", me, buf + 6); r_core_log_add (core, msg); r_config_set (core->config, "cfg.user", buf + 6); me = r_config_get (core->config, "cfg.user"); snprintf (prompt, sizeof (prompt) - 1, "[%s]> ", me); r_line_set_prompt (prompt); return 0; } else if (!strcmp (buf, "/log")) { r_core_log_list (core, 0, 0, 0); return 0; } else if (!strcmp (buf, "/clear")) { // r_core_log_del (core, 0); r_core_cmd0 (core, "T-"); return 0; } else if (!strcmp (buf, "/quit")) { return 0; } else if (*buf == '/') { eprintf ("Unknown command: %s\n", buf); } else { snprintf (msg, sizeof (msg) - 1, "[%s] %s", me, buf); r_core_log_add (core, msg); } } return 1; }
static void _libwrap_init() { char *web; signal (SIGUSR1, sigusr1); signal (SIGUSR2, sigusr2); printf ("libr2 initialized. send SIGUSR1 to %d in order to reach the r2 prompt\n", getpid ()); printf ("kill -USR1 %d\n", getpid ()); fflush (stdout); web = r_sys_getenv ("RARUN2_WEB"); core = r_core_new (); r_core_loadlibs (core, R_CORE_LOADLIBS_ALL, NULL); if (web) { r_core_cmd0 (core, "=H&"); r_sys_setenv ("RARUN2_WEB", NULL); free (web); } // TODO: maybe reopen every time a signal is spawned to reload memory regions information // TODO: open io_self }
static int bin_pdb(RCore *core, int mode) { R_PDB pdb = {0}; ut64 baddr = r_bin_get_baddr (core->bin); pdb.cb_printf = r_cons_printf; if (!init_pdb_parser (&pdb, core->bin->file)) { return false; } if (!pdb.pdb_parse (&pdb)) { eprintf ("pdb was not parsed\n"); pdb.finish_pdb_parse (&pdb); return false; } if (mode == R_CORE_BIN_JSON) r_cons_printf("["); switch (mode) { case R_CORE_BIN_SET: mode = 's'; r_core_cmd0 (core, ".iP*"); return true; case R_CORE_BIN_JSON: mode = 'j'; break; case '*': case 1: mode = 'r'; break; default: mode = 'd'; // default break; } pdb.print_types (&pdb, mode); if (mode == 'j') r_cons_printf (","); pdb.print_gvars (&pdb, baddr, mode); if (mode == 'j') r_cons_printf ("]"); pdb.finish_pdb_parse (&pdb); return true; }
static int visual_nkey(RCore *core, int ch) { const char *cmd; ut64 oseek = UT64_MAX; if (ocursor == -1) { oseek = core->offset; r_core_seek (core, core->offset + cursor, 0); } switch (ch) { case R_CONS_KEY_F1: cmd = r_config_get (core->config, "key.f1"); if (cmd && *cmd) ch = r_core_cmd0 (core, cmd); else ch = '?'; break; case R_CONS_KEY_F2: cmd = r_config_get (core->config, "key.f2"); if (cmd && *cmd) ch = r_core_cmd0 (core, cmd); break; case R_CONS_KEY_F3: cmd = r_config_get (core->config, "key.f3"); if (cmd && *cmd) ch = r_core_cmd0 (core, cmd); break; case R_CONS_KEY_F4: cmd = r_config_get (core->config, "key.f4"); if (cmd && *cmd) ch = r_core_cmd0 (core, cmd); break; case R_CONS_KEY_F5: cmd = r_config_get (core->config, "key.f5"); if (cmd && *cmd) ch = r_core_cmd0 (core, cmd); break; case R_CONS_KEY_F6: cmd = r_config_get (core->config, "key.f6"); if (cmd && *cmd) ch = r_core_cmd0 (core, cmd); break; case R_CONS_KEY_F7: cmd = r_config_get (core->config, "key.f7"); if (cmd && *cmd) ch = r_core_cmd0 (core, cmd); else ch = 's'; break; case R_CONS_KEY_F8: cmd = r_config_get (core->config, "key.f8"); if (cmd && *cmd) ch = r_core_cmd0 (core, cmd); break; case R_CONS_KEY_F9: cmd = r_config_get (core->config, "key.f9"); if (cmd && *cmd) ch = r_core_cmd0 (core, cmd); else r_core_cmd0 (core, "dc"); break; case R_CONS_KEY_F10: cmd = r_config_get (core->config, "key.f10"); if (cmd && *cmd) ch = r_core_cmd0 (core, cmd); break; case R_CONS_KEY_F11: cmd = r_config_get (core->config, "key.f11"); if (cmd && *cmd) ch = r_core_cmd0 (core, cmd); break; case R_CONS_KEY_F12: cmd = r_config_get (core->config, "key.f12"); if (cmd && *cmd) ch = r_core_cmd0 (core, cmd); break; } if (oseek != UT64_MAX) r_core_seek (core, oseek, 0); return ch; }
static int r_core_magic_at(RCore *core, const char *file, ut64 addr, int depth, int v) { const char *fmt; char *q, *p; const char *str; int found = 0, delta = 0, adelta = 0; const char *cmdhit = r_config_get (core->config, "cmd.hit"); #define NAH 32 if (--depth<0) return 0; if (addr != core->offset) { #if 1 if (addr >= core->offset && (addr+NAH) < (core->offset + core->blocksize)) { delta = addr - core->offset; } else { r_core_seek (core, addr, R_TRUE); } #endif } if (((addr&7)==0) && ((addr&(7<<3))==0)) eprintf ("0x%08"PFMT64x"\r", addr); if (file) { if (*file == ' ') file++; if (!*file) file = NULL; } if (ck==NULL) { // TODO: Move RMagic into RCore r_magic_free (ck); // allocate once ck = r_magic_new (0); if (file) { if (r_magic_load (ck, file) == -1) { eprintf ("failed r_magic_load (\"%s\") %s\n", file, r_magic_error (ck)); return -1; } } else { const char *magicpath = r_config_get (core->config, "dir.magic"); if (r_magic_load (ck, magicpath) == -1) { eprintf ("failed r_magic_load (dir.magic) %s\n", r_magic_error (ck)); return -1; } } } //repeat: //if (v) r_cons_printf (" %d # pm %s @ 0x%"PFMT64x"\n", depth, file? file: "", addr); str = r_magic_buffer (ck, core->block+delta, core->blocksize-delta); if (str) { if (!v && !strcmp (str, "data")) { r_magic_free (ck); ck = NULL; return -1; } p = strdup (str); fmt = p; // processing newlinez for (q=p; *q; q++) if (q[0]=='\\' && q[1]=='n') { *q = '\n'; strcpy (q+1, q+((q[2]==' ')? 3: 2)); } if (cmdhit && *cmdhit) { r_core_cmd0 (core, cmdhit); } // TODO: This must be a callback .. move this into RSearch? r_cons_printf ("0x%08"PFMT64x" %d %s\n", addr + adelta, magicdepth-depth, p); r_cons_clear_line (1); eprintf ("0x%08"PFMT64x" 0x%08"PFMT64x" %d %s\n", addr+adelta, addr+adelta, magicdepth-depth, p); // walking children for (q=p; *q; q++) { switch (*q) { case ' ': fmt = q+1; break; case '@': { ut64 addr = 0LL; *q = 0; if (!memcmp (q+1, "0x", 2)) sscanf (q+3, "%"PFMT64x, &addr); else sscanf (q+1, "%"PFMT64d, &addr); if (!fmt || !*fmt) fmt = file; r_core_magic_at (core, fmt, addr, depth, 1); *q = '@'; } break; } } free (p); r_magic_free (ck); ck = NULL; found ++; // return adelta+1; } adelta ++; delta ++; #if 0 if((core->blocksize-delta)>16) goto repeat; #endif #if 0 r_magic_free (ck); ck = NULL; #endif return adelta; //found; }
static int core_cmd_callback (void *user, const char *cmd) { RCore *core = (RCore *)user; return r_core_cmd0 (core, cmd); }
static int cmd_seek(void *data, const char *input) { RCore *core = (RCore *)data; char *cmd, *p; ut64 off; if (*input=='r') { if (input[1] && input[2]) { if (core->io->debug) { off = r_debug_reg_get (core->dbg, input+2); r_io_sundo_push (core->io, core->offset); r_core_seek (core, off, 1); } else { RReg *orig = core->dbg->reg; core->dbg->reg = core->anal->reg; off = r_debug_reg_get (core->dbg, input+2); core->dbg->reg = orig; r_core_seek (core, off, 1); } } else eprintf ("|Usage| 'sr pc' seek to program counter register\n"); } else if (*input) { const char *inputnum = strchr (input+1, ' '); int sign = 1; inputnum = inputnum? inputnum+1: input+1; off = r_num_math (core->num, inputnum); if (*inputnum== '-') off = -off; #if 0 if (input[0]!='/' && inputnum && isalpha (inputnum[0]) && off == 0) { if (!r_flag_get (core->flags, inputnum)) { eprintf ("Cannot find address for '%s'\n", inputnum); return R_FALSE; } } #endif if (input[0]==' ') { switch (input[1]) { case '-': sign=-1; case '+': input++; break; } } switch (*input) { case 'C': if (input[1]=='*') { r_core_cmd0 (core, "C*~^\"CC"); } else if (input[1]==' ') { typedef struct { ut64 addr; char *str; } MetaCallback; int count = 0; MetaCallback cb = { 0, NULL }; ut64 addr; char key[128]; const char *val, *comma; char *list = sdb_get (core->anal->sdb_meta, "meta.C", 0); char *str, *next, *cur = list; if (list) { for (;;) { cur = sdb_anext (cur, &next); addr = sdb_atoi (cur); snprintf (key, sizeof (key)-1, "meta.C.0x%"PFMT64x, addr); val = sdb_const_get (core->anal->sdb_meta, key, 0); if (val) { comma = strchr (val, ','); if (comma) { str = (char *)sdb_decode (comma+1, 0); if (strstr (str, input+2)) { r_cons_printf ("0x%08"PFMT64x" %s\n", addr, str); count++; cb.addr = addr; free (cb.str); cb.str = str; } else free (str); } } else eprintf ("sdb_const_get key not found '%s'\n", key); if (!next) break; cur = next; } } switch (count) { case 0: eprintf ("No matching comments\n"); break; case 1: off = cb.addr; r_io_sundo_push (core->io, core->offset); r_core_seek (core, off, 1); r_core_block_read (core, 0); break; default: eprintf ("Too many results\n"); break; } free (cb.str); } else eprintf ("Usage: sC[?*] comment-grep\n" "sC* list all comments\n" "sC const seek to comment matching 'const'\n"); break; case ' ': r_io_sundo_push (core->io, core->offset); r_core_seek (core, off*sign, 1); r_core_block_read (core, 0); break; case '/': { const char *pfx = r_config_get (core->config, "search.prefix"); //kwidx cfg var is ignored int kwidx = core->search->n_kws; //(int)r_config_get_i (core->config, "search.kwidx")-1; if (kwidx<0) kwidx = 0; switch (input[1]) { case ' ': case 'x': r_config_set_i (core->config, "search.count", 1); r_core_cmdf (core, "s+1; p8 ; .%s;s-1;s %s%d_0;f-%s%d_0", input, pfx, kwidx, pfx, kwidx, pfx, kwidx); r_config_set_i (core->config, "search.count", 0); break; default: eprintf ("unknown search method\n"); break; } } break; case '.': for (input++;*input=='.';input++); r_core_seek_base (core, input); break; case '*': r_io_sundo_list (core->io); break; case '+': if (input[1]!='\0') { int delta = (input[1]=='+')? core->blocksize: off; r_io_sundo_push (core->io, core->offset); r_core_seek_delta (core, delta); } else { off = r_io_sundo_redo (core->io); if (off != UT64_MAX) r_core_seek (core, off, 0); } break; case '-': if (input[1]!='\0') { int delta = (input[1]=='-') ? -core->blocksize: -off; r_io_sundo_push (core->io, core->offset); r_core_seek_delta (core, delta); } else { off = r_io_sundo (core->io, core->offset); if (off != UT64_MAX) r_core_seek (core, off, 0); } break; case 'n': r_io_sundo_push (core->io, core->offset); r_core_seek_next (core, r_config_get (core->config, "scr.nkey")); break; case 'p': r_io_sundo_push (core->io, core->offset); r_core_seek_previous (core, r_config_get (core->config, "scr.nkey")); break; case 'a': off = core->blocksize; if (input[1]&&input[2]) { cmd = strdup (input); p = strchr (cmd+2, ' '); if (p) { off = r_num_math (core->num, p+1);; *p = '\0'; } cmd[0] = 's'; // perform real seek if provided r_cmd_call (core->rcmd, cmd); free (cmd); } r_io_sundo_push (core->io, core->offset); r_core_seek_align (core, off, 0); break; case 'b': if (off == 0) off = core->offset; r_io_sundo_push (core->io, core->offset); r_core_anal_bb_seek (core, off); break; case 'f': if (strlen(input) > 2 && input[1]==' ') { RAnalFunction *fcn = r_anal_fcn_find_name (core->anal, input+2); if (fcn) { r_core_seek (core, fcn->addr, 1); } break; } RAnalFunction *fcn = r_anal_fcn_find (core->anal, core->offset, 0); if (fcn) { r_core_seek (core, fcn->addr+fcn->size, 1); } break; case 'o': { RAnalOp op; int val=0, ret, i, n = r_num_math (core->num, input+1); if (n==0) n = 1; if (n<0) { int ret = prevopsz (core, n); ret = r_anal_op (core->anal, &op, core->offset, core->block, core->blocksize); val += ret; } else for (val=i=0; i<n; i++) { ret = r_anal_op (core->anal, &op, core->offset, core->block, core->blocksize); if (ret<1) break; r_core_seek_delta (core, ret); val += ret; } core->num->value = val; } break; case 'g': { RIOSection *s = r_io_section_vget (core->io, core->offset); if (s) r_core_seek (core, s->vaddr, 1); else r_core_seek (core, 0, 1); } break; case 'G': { RIOSection *s = r_io_section_vget (core->io, core->offset); // XXX: this +2 is a hack. must fix gap between sections if (s) r_core_seek (core, s->vaddr+s->size+2, 1); else r_core_seek (core, core->file->size, 1); } break; case '?': { const char * help_message[] = { "Usage: s", "", " # Seek commands", "s", "", "Print current address", "s", " addr", "Seek to address", "s-", "", "Undo seek", "s-", " n", "Seek n bytes backward", "s--", "", "Seek blocksize bytes backward", "s+", "", "Redo seek", "s+", " n", "Seek n bytes forward", "s++", "", "Seek blocksize bytes forward", "s*", "", "List undo seek history", "s/", " DATA", "Search for next occurrence of 'DATA'", "s/x", " 9091", "Search for next occurrence of \\x90\\x91", "s.", "hexoff", "Seek honoring a base from core->offset", "sa", " [[+-]a] [asz]", "Seek asz (or bsize) aligned to addr", "sb", "", "Seek aligned to bb start", "sC", " string", "Seek to comment matching given string", "sf", "", "Seek to next function (f->addr+f->size)", "sf", " function", "Seek to address of specified function", "sg/sG", "", "Seek begin (sg) or end (sG) of section or file", "sn/sp", "", "Seek next/prev scr.nkey", "so", " [N]", "Seek to N next opcode(s)", "sr", " pc", "Seek to register", //"sp [page] seek page N (page = block)", NULL }; r_core_cmd_help(core, help_message); } break; } } else r_cons_printf ("0x%"PFMT64x"\n", core->offset); return 0; }
static int cmd_type(void *data, const char *input) { RCore *core = (RCore*)data; switch (input[0]) { // t [typename] - show given type in C syntax case 's': { char *q, *p, *o, *e; p = o = strdup (input+1); for (;;) { q = strchr (p, ' '); if (q) *q = 0; if (!*p) { p++; continue; } e = strchr (p, '='); if (e) { *e = 0; r_anal_type_set (core->anal, core->offset, p, r_num_math (core->num, e+1)); } else eprintf ("TODO: implement get\n"); if (!q) break; p = q+1; } free (o); } break; case ' ': { char *fmt = r_anal_type_format (core->anal, input +1); if (fmt) { r_cons_printf ("pf %s\n", fmt); free (fmt); } else eprintf ("Cannot find '%s' type\n", input+1); } break; #if 0 // t* - list all types in 'pf' syntax case '*': r_anal_type_list (core->anal, R_ANAL_TYPE_ANY, 1); break; #endif case 0: // TODO: use r_cons here //sdb_list (core->anal->sdb_types); sdb_foreach (core->anal->sdb_types, sdbforcb, core); break; case 'o': if (input[1] == ' ') { const char *filename = input + 2; if (!strcmp (filename, "-")) { char *out, *tmp; tmp = r_core_editor (core, ""); if (tmp) { out = r_parse_c_string (tmp); if (out) { r_cons_strcat (out); sdb_query_lines (core->anal->sdb_types, out); free (out); } free (tmp); } } else { char *out = r_parse_c_file (filename); if (out) { r_cons_strcat (out); sdb_query_lines (core->anal->sdb_types, out); free (out); } //r_anal_type_loadfile (core->anal, filename); } } break; // td - parse string with cparse engine and load types from it case 'd': if (input[1] == '?') { const char * help_message[] = { "Usage:", "td[...]", "", "td", "[string]", "Load types from string", NULL }; r_core_cmd_help(core, help_message); } else if (input[1] == '-') { const char *arg = strchr (input+1, ' '); if (arg) arg++; else arg = input+2; r_anal_type_del (core->anal, arg); } else if (input[1] == ' ') { char tmp[256]; snprintf (tmp, sizeof (tmp), "%s;", input+2); //const char *string = input + 2; //r_anal_str_to_type (core->anal, string); char *out = r_parse_c_string (tmp); if (out) { r_cons_strcat (out); sdb_query_lines (core->anal->sdb_types, out); free (out); } } else { eprintf ("Invalid use of td. See td? for help\n"); } break; // tl - link a type to an address case 'l': if (input[1]=='?') { const char * help_message[] = { "Usage: tl", " [typename|addr] ([addr])@[addr|function]", "", NULL }; r_core_cmd_help(core, help_message); } else if (input[1]) { ut64 addr = r_num_math (core->num, input+2); char *ptr = strchr (input + 2, ' '); if (ptr) { addr = r_num_math (core->num, ptr + 1); *ptr = '\0'; } else addr = core->offset; r_anal_type_link (core->anal, input+2, addr); } else { r_core_cmd0 (core, "t~^link"); } break; case '-': if (input[1] == '?') { const char * help_message[] = { "Usage: t-", " <type>", "Delete type by its name", NULL }; r_core_cmd_help(core, help_message); } else if (input[1]=='*') { eprintf ("TODO\n"); } else { const char *name = input + 1; if (*name==' ') name++; if (*name) { r_anal_type_del (core->anal, name); } else eprintf ("Invalid use of t- . See t-? for help.\n"); } break; // tv - get/set type value linked to a given address case 'f': { ut64 addr; char *fmt, key[128]; const char *type; if (input[1]) { addr = r_num_math (core->num, input+1); } else addr = core->offset; snprintf (key, sizeof (key), "link.%"PFMT64x, addr); type = sdb_const_get (core->anal->sdb_types, key, 0); if (type) { fmt = r_anal_type_format (core->anal, type); r_cons_printf ("struct %s {\n", type); if (fmt) { r_core_cmdf (core, "pf %s @ 0x%08"PFMT64x"\n", fmt, addr); free (fmt); }// else eprintf ("Cannot find '%s' type\n", input+1); r_cons_printf ("}\n"); } } break; case '?': if (input[1]) { sdb_query (core->anal->sdb_types, input+1); } else show_help(core); break; } return R_TRUE; }
R_API int r_core_visual_cmd(RCore *core, int ch) { RAsmOp op; ut64 offset = core->offset; char buf[4096]; int i, ret, offscreen, cols = core->print->cols, delta = 0; ch = r_cons_arrow_to_hjkl (ch); ch = visual_nkey (core, ch); if (ch<2) return 1; // do we need hotkeys for data references? not only calls? if (ch>='0'&& ch<='9') { ut64 off = core->asmqjmps[ch-'0']; if (off != UT64_MAX) { int delta = R_ABS ((st64)off-(st64)offset); r_io_sundo_push (core->io, offset); if (curset && delta<100) { cursor = delta; } else { r_core_visual_seek_animation (core, off); //r_core_seek (core, off, 1); } r_core_block_read (core, 1); } } else switch (ch) { case 0x0d: { r_cons_enable_mouse (R_TRUE); RAnalOp *op = r_core_anal_op (core, core->offset+cursor); if (op) { if (op->type == R_ANAL_OP_TYPE_JMP || op->type == R_ANAL_OP_TYPE_CJMP || op->type == R_ANAL_OP_TYPE_CALL) { r_io_sundo_push (core->io, offset); r_core_visual_seek_animation(core, op->jump); } } r_anal_op_free (op); } break; case 90: // shift+tab if (!strcmp (printfmt[0], "x")) printfmt[0] = "pxa"; else printfmt[0] = "x"; break; case 9: // tab { // XXX: unify diff mode detection ut64 f = r_config_get_i (core->config, "diff.from"); ut64 t = r_config_get_i (core->config, "diff.to"); if (f == t && f == 0) { core->print->col = core->print->col==1? 2: 1; } else { ut64 delta = offset - f; r_core_seek (core, t+delta, 1); r_config_set_i (core->config, "diff.from", t); r_config_set_i (core->config, "diff.to", f); } } break; case 'a': if (core->file && !(core->file->rwx & 2)) { r_cons_printf ("\nFile has been opened in read-only mode. Use -w flag\n"); r_cons_any_key (); return R_TRUE; } r_cons_printf ("Enter assembler opcodes separated with ';':\n"); showcursor (core, R_TRUE); r_cons_flush (); r_cons_set_raw (R_FALSE); strcpy (buf, "wa "); r_line_set_prompt (":> "); if (r_cons_fgets (buf+3, 1000, 0, NULL) <0) buf[0]='\0'; if (*buf) { if (curset) r_core_seek (core, core->offset + cursor, 0); r_core_cmd (core, buf, R_TRUE); if (curset) r_core_seek (core, core->offset - cursor, 1); } showcursor (core, R_FALSE); r_cons_set_raw (R_TRUE); break; case '!': r_cons_2048(); break; case 'o': visual_offset (core); break; case 'A': { int oc = curset; ut64 off = curset? core->offset+cursor : core->offset; curset = 0; r_core_visual_asm (core, off); curset = oc; } break; case 'c': setcursor (core, curset?0:1); break; case 'C': color = color? 0: 1; r_config_set_i (core->config, "scr.color", color); break; case 'd': r_core_visual_define (core); break; case 'D': setdiff (core); break; case 'f': { int range, min, max; char name[256], *n; r_line_set_prompt ("flag name: "); showcursor (core, R_TRUE); if (r_cons_fgets (name, sizeof (name), 0, NULL) >=0 && *name) { n = r_str_chop (name); if (*name=='-') { if (*n) r_flag_unset (core->flags, n+1, NULL); } else { if (ocursor != -1) { min = R_MIN (cursor, ocursor); max = R_MAX (cursor, ocursor); } else { min = max = cursor; } range = max-min+1; if (range<1) range = 1; if (*n) r_flag_set (core->flags, n, core->offset + min, range, 1); } } } showcursor (core, R_FALSE); break; case 'F': r_flag_unset_i (core->flags, core->offset + cursor, NULL); break; case 'n': r_core_seek_next (core, r_config_get (core->config, "scr.nkey")); break; case 'N': r_core_seek_previous (core, r_config_get (core->config, "scr.nkey")); break; case 'i': case 'I': if (core->file && !(core->file->rwx & 2)) { r_cons_printf ("\nFile has been opened in read-only mode. Use -w flag\n"); r_cons_any_key (); return R_TRUE; } showcursor (core, R_TRUE); r_cons_flush (); r_cons_set_raw (0); if (ch=='I') { strcpy (buf, "wow "); r_line_set_prompt ("insert hexpair block: "); if (r_cons_fgets (buf+4, sizeof (buf)-5, 0, NULL) <0) buf[0]='\0'; char *p = strdup (buf); int cur = core->print->cur; if (cur>=core->blocksize) cur = core->print->cur-1; snprintf (buf, sizeof (buf), "%s @ $$0!%i", p, core->blocksize-cursor); r_core_cmd (core, buf, 0); free (p); break; } delta = (ocursor!=-1)? R_MIN (cursor, ocursor): cursor; if (core->print->col==2) { strcpy (buf, "\"w "); r_line_set_prompt ("insert string: "); if (r_cons_fgets (buf+3, sizeof (buf)-4, 0, NULL) <0) buf[0]='\0'; strcat (buf, "\""); } else { r_line_set_prompt ("insert hex: "); if (ocursor != -1) { int bs = R_ABS (cursor-ocursor)+1; core->blocksize = bs; strcpy (buf, "wow "); } else { strcpy (buf, "wx "); } if (r_cons_fgets (buf+strlen (buf), sizeof (buf)-strlen (buf), 0, NULL) <0) buf[0]='\0'; } if (curset) r_core_seek (core, core->offset + delta, 0); r_core_cmd (core, buf, 1); if (curset) r_core_seek (core, offset, 1); r_cons_set_raw (1); showcursor (core, R_FALSE); break; case 'R': r_core_cmd0 (core, "ecr"); break; case 'e': r_core_visual_config (core); break; case 'E': r_core_visual_colors (core); break; case 'M': r_core_visual_mounts (core); break; case 't': r_core_visual_trackflags (core); break; case 'x': { int count = 0; RList *xrefs = NULL; RAnalRef *refi; RListIter *iter; RAnalFunction *fun; if ((xrefs = r_anal_xref_get (core->anal, core->offset))) { r_cons_gotoxy (1, 1); r_cons_printf ("[GOTO XREF]> \n"); if (r_list_empty (xrefs)) { r_cons_printf ("\tNo XREF found at 0x%"PFMT64x"\n", core->offset); r_cons_any_key (); r_cons_clear00 (); } else { r_list_foreach (xrefs, iter, refi) { fun = r_anal_fcn_find (core->anal, refi->addr, R_ANAL_FCN_TYPE_NULL); r_cons_printf (" [%i] 0x%08"PFMT64x" %s XREF 0x%08"PFMT64x" (%s) \n", count, refi->at, refi->type==R_ANAL_REF_TYPE_CODE?"CODE (JMP)": refi->type==R_ANAL_REF_TYPE_CALL?"CODE (CALL)":"DATA", refi->addr, fun?fun->name:"unk"); if (++count > 9) break; } } } else xrefs = NULL;
R_API int r_core_pseudo_code(RCore *core, const char *input) { Sdb *db; ut64 queuegoto = 0LL; const char *blocktype = "else"; RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, R_ANAL_FCN_TYPE_NULL); RConfigHold *hc = r_config_hold_new (core->config); if (!hc) { return false; } r_config_save_num (hc, "asm.pseudo", "asm.decode", "asm.lines", "asm.bytes", NULL); r_config_save_num (hc, "asm.offset", "asm.flags", "asm.fcnlines", "asm.comments", NULL); r_config_save_num (hc, "asm.functions", "asm.section", "asm.cmtcol", "asm.filter", NULL); r_config_save_num (hc, "scr.color", "asm.emustr", "asm.emu", "asm.emuwrite", NULL); if (!fcn) { eprintf ("Cannot find function in 0x%08"PFMT64x"\n", core->offset); r_config_hold_free (hc); return false; } r_config_set_i (core->config, "scr.color", 0); r_config_set_i (core->config, "asm.pseudo", 1); r_config_set_i (core->config, "asm.decode", 0); r_config_set_i (core->config, "asm.filter", 1); r_config_set_i (core->config, "asm.lines", 0); r_config_set_i (core->config, "asm.bytes", 0); r_config_set_i (core->config, "asm.offset", 0); r_config_set_i (core->config, "asm.flags", 0); r_config_set_i (core->config, "asm.emu", 1); r_config_set_i (core->config, "asm.emustr", 1); r_config_set_i (core->config, "asm.emuwrite", 1); r_config_set_i (core->config, "asm.fcnlines", 0); r_config_set_i (core->config, "asm.comments", 1); r_config_set_i (core->config, "asm.functions", 0); r_config_set_i (core->config, "asm.tabs", 0); r_config_set_i (core->config, "asm.section", 0); r_config_set_i (core->config, "asm.cmtcol", 30); r_core_cmd0 (core, "aeim"); db = sdb_new0 (); /* */ // walk all basic blocks // define depth level for each block // use it for indentation // asm.pseudo=true // asm.decode=true RAnalBlock *bb = r_list_first (fcn->bbs); char indentstr[1024]; int n_bb = r_list_length (fcn->bbs); r_cons_printf ("function %s () {", fcn->name); int indent = 1; int nindent = 1; do { #define I_TAB 4 #define K_MARK(x) sdb_fmt(0,"mark.%"PFMT64x,x) #define K_ELSE(x) sdb_fmt(0,"else.%"PFMT64x,x) #define K_INDENT(x) sdb_fmt(0,"loc.%"PFMT64x,x) #define SET_INDENT(x) { memset (indentstr, ' ', x*I_TAB); indentstr [(x*I_TAB)-2] = 0; } if (!bb) break; r_cons_push (); char *code = r_core_cmd_str (core, sdb_fmt (0, "pD %d @ 0x%08"PFMT64x"\n", bb->size, bb->addr)); r_cons_pop (); memset (indentstr, ' ', indent * I_TAB); indentstr [(indent * I_TAB) - 2] = 0; code = r_str_prefix_all (code, indentstr); int len = strlen (code); code[len - 1] = 0; // chop last newline //r_cons_printf ("\n%s loc_0x%llx:\n", indentstr, bb->addr); //if (nindent != indent) { // r_cons_printf ("\n%s loc_0x%llx:\n", indentstr, bb->addr); //} find_and_change (code, len); if (!sdb_const_get (db, K_MARK (bb->addr), 0)) { bool mustprint = !queuegoto || queuegoto != bb->addr; if (mustprint) { if (queuegoto) { r_cons_printf ("\n%s goto loc_0x%llx", indentstr, queuegoto); queuegoto = 0LL; } r_cons_printf ("\n%s loc_0x%llx:\n", indentstr, bb->addr); indentstr[(indent * I_TAB) - 2] = 0; r_cons_printf ("\n%s", code); free (code); sdb_num_set (db, K_MARK (bb->addr), 1, 0); } } if (sdb_const_get (db, K_INDENT (bb->addr), 0)) { // already analyzed, go pop and continue // XXX check if cant pop //eprintf ("%s// 0x%08llx already analyzed\n", indentstr, bb->addr); ut64 addr = sdb_array_pop_num (db, "indent", NULL); if (addr == UT64_MAX) { int i; nindent = 1; for (i = indent; i != nindent; i--) { SET_INDENT (i); r_cons_printf ("\n%s}", indentstr); } r_cons_printf ("\n%sreturn;\n", indentstr); break; } if (sdb_num_get (db, K_ELSE (bb->addr), 0)) { if (!strcmp (blocktype, "else")) { r_cons_printf ("\n%s } %s {", indentstr, blocktype); } else { r_cons_printf ("\n%s } %s (?);", indentstr, blocktype); } } else { r_cons_printf ("\n%s}", indentstr); } if (addr != bb->addr) { queuegoto = addr; //r_cons_printf ("\n%s goto loc_0x%llx", indentstr, addr); } bb = r_anal_bb_from_offset (core->anal, addr); if (!bb) { eprintf ("failed block\n"); break; } //eprintf ("next is %llx\n", addr); nindent = sdb_num_get (db, K_INDENT (addr), NULL); if (indent > nindent && !strcmp (blocktype, "else")) { int i; for (i = indent; i != nindent; i--) { SET_INDENT (i); r_cons_printf ("\n%s }", indentstr); } } indent = nindent; } else { sdb_set (db, K_INDENT (bb->addr), "passed", 0); if (bb->jump != UT64_MAX) { int swap = 1; // TODO: determine which branch take first ut64 jump = swap ? bb->jump : bb->fail; ut64 fail = swap ? bb->fail : bb->jump; // if its from another function chop it! RAnalFunction *curfcn = r_anal_get_fcn_in (core->anal, jump, R_ANAL_FCN_TYPE_NULL); if (curfcn != fcn) { // chop that branch r_cons_printf ("\n // chop\n"); break; } if (sdb_get (db, K_INDENT (jump), 0)) { // already tracekd if (!sdb_get (db, K_INDENT (fail), 0)) { bb = r_anal_bb_from_offset (core->anal, fail); } } else { bb = r_anal_bb_from_offset (core->anal, jump); if (!bb) { eprintf ("failed to retrieve blcok at 0x%"PFMT64x"\n", jump); break; } if (fail != UT64_MAX) { // do not push if already pushed indent++; if (sdb_get (db, K_INDENT (bb->fail), 0)) { /* do nothing here */ eprintf ("BlockAlready 0x%"PFMT64x"\n", bb->addr); } else { // r_cons_printf (" { RADICAL %llx\n", bb->addr); sdb_array_push_num (db, "indent", fail, 0); sdb_num_set (db, K_INDENT (fail), indent, 0); sdb_num_set (db, K_ELSE (fail), 1, 0); SET_INDENT (indent); r_cons_printf ("\n%s {", indentstr); } } else { r_cons_printf ("\n%s do", indentstr); sdb_array_push_num (db, "indent", jump, 0); sdb_num_set (db, K_INDENT (jump), indent, 0); sdb_num_set (db, K_ELSE (jump), 1, 0); if (jump <= bb->addr) { blocktype = "while"; } else { blocktype = "else"; } r_cons_printf ("\n%s {", indentstr); indent++; } } } else { ut64 addr = sdb_array_pop_num (db, "indent", NULL); if (addr == UT64_MAX) { //r_cons_printf ("\nbreak\n"); break; } bb = r_anal_bb_from_offset (core->anal, addr); nindent = sdb_num_get (db, K_INDENT (addr), NULL); if (indent > nindent) { int i; for (i = indent; i != nindent; i--) { SET_INDENT (i); r_cons_printf ("\n%s}", indentstr); } } if (nindent != indent) { r_cons_printf ("\n%s} else {\n", indentstr); } indent = nindent; } } //n_bb --; } while (n_bb > 0); r_cons_printf ("\n}\n"); r_config_restore (hc); r_config_hold_free (hc); sdb_free (db); return true; }
R_API bool r_core_hack_arm(RCore *core, const char *op, const RAnalOp *analop) { const int bits = core->assembler->bits; const ut8 *b = core->block; if (!strcmp (op, "nop")) { const int nopsize = (bits==16)? 2: 4; const char *nopcode = (bits==16)? "00bf":"0000a0e1"; const int len = analop->size; char* str; int i; if (len % nopsize) { eprintf ("Invalid nopcode size\n"); return false; } str = calloc (len + 1, 2); if (!str) { return false; } for (i=0; i < len; i+=nopsize) { memcpy (str + i * 2, nopcode, nopsize*2); } str[len*2] = '\0'; r_core_cmdf (core, "wx %s\n", str); free (str); } else if (!strcmp (op, "trap")) { const char* trapcode = (bits==16)? "bebe": "fedeffe7"; r_core_cmdf (core, "wx %s\n", trapcode); } else if (!strcmp (op, "jz")) { if (bits == 16) { switch (b[1]) { case 0xb9: // CBNZ r_core_cmd0 (core, "wx b1 @@ $$+1\n"); //CBZ break; case 0xbb: // CBNZ r_core_cmd0 (core, "wx b3 @@ $$+1\n"); //CBZ break; case 0xd1: // BNE r_core_cmd0 (core, "wx d0 @@ $$+1\n"); //BEQ break; default: eprintf ("Current opcode is not conditional\n"); return false; } } else { eprintf ("ARM jz hack not supported\n"); return false; } } else if (!strcmp (op, "jnz")) { if (bits == 16) { switch (b[1]) { case 0xb1: // CBZ r_core_cmd0 (core, "wx b9 @@ $$+1\n"); //CBNZ break; case 0xb3: // CBZ r_core_cmd0 (core, "wx bb @@ $$+1\n"); //CBNZ break; case 0xd0: // BEQ r_core_cmd0 (core, "wx d1 @@ $$+1\n"); //BNE break; default: eprintf ("Current opcode is not conditional\n"); return false; } } else { eprintf ("ARM jnz hack not supported\n"); return false; } } else if (!strcmp (op, "nocj")) { // TODO: drop conditional bit instead of that hack if (bits == 16) { switch (b[1]) { case 0xb1: // CBZ case 0xb3: // CBZ case 0xd0: // BEQ case 0xb9: // CBNZ case 0xbb: // CBNZ case 0xd1: // BNE r_core_cmd0 (core, "wx e0 @@ $$+1\n"); //BEQ break; default: eprintf ("Current opcode is not conditional\n"); return false; } } else { eprintf ("ARM un-cjmp hack not supported\n"); return false; } } else if (!strcmp (op, "recj")) { eprintf ("TODO: use jnz or jz\n"); return false; } else if (!strcmp (op, "ret1")) { if (bits == 16) r_core_cmd0 (core, "wx 01207047 @@ $$+1\n"); // mov r0, 1; bx lr else r_core_cmd0 (core, "wx 0100b0e31eff2fe1 @@ $$+1\n"); // movs r0, 1; bx lr } else if (!strcmp (op, "ret0")) { if (bits == 16) r_core_cmd0 (core, "wx 00207047 @@ $$+1\n"); // mov r0, 0; bx lr else r_core_cmd0 (core, "wx 0000a0e31eff2fe1 @@ $$+1\n"); // movs r0, 0; bx lr } else if (!strcmp (op, "retn")) { if (bits == 16) r_core_cmd0 (core, "wx ff207047 @@ $$+1\n"); // mov r0, -1; bx lr else r_core_cmd0 (core, "wx ff00a0e31eff2fe1 @@ $$+1\n"); // movs r0, -1; bx lr } else { eprintf ("Invalid operation\n"); return false; } return true; }
static int cmd_seek(void *data, const char *input) { RCore *core = (RCore *) data; char *cmd, *p; ut64 off; if (!*input) { r_cons_printf ("0x%"PFMT64x "\n", core->offset); return 0; } char *ptr; if ((ptr = strstr (input, "+.")) != NULL) { char *dup = strdup (input); dup[ptr - input] = '\x00'; off = r_num_math (core->num, dup + 1); core->offset = off; free (dup); } const char *inputnum = strchr (input, ' '); { const char *u_num = inputnum? inputnum + 1: input + 1; off = r_num_math (core->num, u_num); if (*u_num == '-') { off = -off; } } int sign = 1; if (input[0] == ' ') { switch (input[1]) { case '-': sign = -1; /* pass thru */ case '+': input++; break; } } bool silent = false; if (*input == 's') { silent = true; input++; if (*input == '?') { const char *help_message[] = { "Usage: ss", "", " # Seek silently (not recorded in the seek history)", "s?", "", "Works with all s subcommands", NULL }; r_core_cmd_help (core, help_message); return 0; } } switch (*input) { case 'r': if (input[1] && input[2]) { seek_to_register (core, input + 2, silent); } else { eprintf ("|Usage| 'sr PC' seek to program counter register\n"); } break; case 'C': if (input[1] == '*') { r_core_cmd0 (core, "C*~^\"CC"); } else if (input[1] == ' ') { typedef struct { ut64 addr; char *str; } MetaCallback; int count = 0; MetaCallback cb = { 0, NULL }; ut64 addr; char key[128]; const char *val, *comma; char *list = sdb_get (core->anal->sdb_meta, "meta.C", 0); char *str, *next, *cur = list; if (list) { for (;;) { cur = sdb_anext (cur, &next); addr = sdb_atoi (cur); snprintf (key, sizeof (key) - 1, "meta.C.0x%"PFMT64x, addr); val = sdb_const_get (core->anal->sdb_meta, key, 0); if (val) { comma = strchr (val, ','); if (comma) { str = (char *) sdb_decode (comma + 1, 0); if (strstr (str, input + 2)) { r_cons_printf ("0x%08"PFMT64x " %s\n", addr, str); count++; cb.addr = addr; free (cb.str); cb.str = str; } else { free (str); } } } else { eprintf ("sdb_const_get key not found '%s'\n", key); } if (!next) { break; } cur = next; } } switch (count) { case 0: eprintf ("No matching comments\n"); break; case 1: off = cb.addr; if (!silent) { r_io_sundo_push (core->io, core->offset, r_print_get_cursor (core->print)); } r_core_seek (core, off, 1); r_core_block_read (core); break; default: eprintf ("Too many results\n"); break; } free (cb.str); } else { const char *help_msg[] = { "Usage:", "sC", "Comment grep", "sC", "*", "List all comments", "sC", " str", "Seek to the first comment matching 'str'", NULL }; r_core_cmd_help (core, help_msg); } break; case ' ': if (!silent) { r_io_sundo_push (core->io, core->offset, r_print_get_cursor (core->print)); } r_core_seek (core, off * sign, 1); r_core_block_read (core); break; case '/': { const char *pfx = r_config_get (core->config, "search.prefix"); ut64 from = r_config_get_i (core->config, "search.from"); // kwidx cfg var is ignored int kwidx = core->search->n_kws; // (int)r_config_get_i (core->config, "search.kwidx")-1; if (kwidx < 0) { kwidx = 0; } switch (input[1]) { case ' ': case 'v': case 'V': case 'w': case 'W': case 'z': case 'm': case 'c': case 'A': case 'e': case 'E': case 'i': case 'R': case 'r': case '/': case 'x': r_config_set_i (core->config, "search.from", core->offset + 1); r_config_set_i (core->config, "search.count", 1); r_core_cmdf (core, "s+1; %s; s-1; s %s%d_0; f-%s%d_0", input, pfx, kwidx, pfx, kwidx, pfx, kwidx); r_config_set_i (core->config, "search.from", from); r_config_set_i (core->config, "search.count", 0); break; case '?': eprintf ("Usage: s/.. arg.\n"); r_cons_printf ("/?\n"); break; default: eprintf ("unknown search method\n"); break; } } break; case '.': for (input++; *input == '.'; input++) { ; } r_core_seek_base (core, input); break; case 'j': // sj { RList /*<ut64 *>*/ *addrs = r_list_newf (free); RList /*<char *>*/ *names = r_list_newf (free); RList *list = r_io_sundo_list (core->io, '!'); ut64 lsz = 0; ut64 i; RListIter *iter; RIOUndos *undo; if (list) { r_list_foreach (list, iter, undo) { char *name = NULL; core->flags->space_strict = true; RFlagItem *f = r_flag_get_at (core->flags, undo->off, true); core->flags->space_strict = false; if (f) { if (f->offset != undo->off) { name = r_str_newf ("%s + %d\n", f->name, (int)(undo->off- f->offset)); } else { name = strdup (f->name); } } if (!name) { name = strdup (""); } ut64 *val = malloc (sizeof (ut64)); if (!val) { free (name); break; } *val = undo->off; r_list_append (addrs, val); r_list_append (names, strdup (name)); lsz++; free (name); } r_list_free (list); } r_cons_printf ("["); for (i = 0; i < lsz; ++i) { ut64 *addr = r_list_get_n (addrs, i); const char *name = r_list_get_n (names, i); // XXX(should the "name" field be optional? That might make // a bit more sense. r_cons_printf ("{\"offset\":%"PFMT64d",\"symbol\":\"%s\"}", *addr, name); if (i != lsz - 1) { r_cons_printf (","); } } r_cons_printf ("]\n"); r_list_free (addrs); r_list_free (names); } break; case '*': case '=': case '!': { RList *list = r_io_sundo_list (core->io, input[0]); RListIter *iter; RIOUndos *undo; if (list) { r_list_foreach (list, iter, undo) { char *name = NULL; core->flags->space_strict = true; RFlagItem *f = r_flag_get_at (core->flags, undo->off, true); core->flags->space_strict = false; if (f) { if (f->offset != undo->off) { name = r_str_newf ("%s + %d\n", f->name, (int)(undo->off- f->offset)); } else { name = strdup (f->name); } } if (!name) { name = strdup (""); } r_cons_printf ("0x%"PFMT64x" %s\n", undo->off, name); free (name); } r_list_free (list); } }
static void cmd_write_op (RCore *core, const char *input) { ut8 *buf; int len; int value; if (!input[0]) return; switch (input[1]) { case 'e': if (input[2]!=' ') { r_cons_printf ("Usage: 'woe from-to step'\n"); return; } /* fallthru */ case 'a': case 's': case 'A': case 'x': case 'r': case 'l': case 'm': case 'd': case 'o': case 'w': case '2': case '4': if (input[2]) { // parse val from arg r_core_write_op (core, input+3, input[1]); r_core_block_read (core); } else { // use clipboard instead of val r_core_write_op (core, NULL, input[1]); r_core_block_read (core); } break; case 'R': r_core_cmd0 (core, "wr $b"); break; case 'n': r_core_write_op (core, "ff", 'x'); r_core_block_read (core); break; case 'E': // "woE" encrypt case 'D': // "woD" decrypt { int direction = (input[1] == 'E') ? 0 : 1; const char *algo = NULL; const char *key = NULL; const char *iv = NULL; char *space, *args = strdup (r_str_trim_ro (input+2)); space = strchr (args, ' '); if (space) { *space++ = 0; key = space; space = strchr (key, ' '); if (space) { *space++ = 0; iv = space; } } algo = args; if (algo && *algo && key) { encrypt_or_decrypt_block (core, algo, key, direction, iv); } else { eprintf ("Usage: wo%c [algo] [key] [IV]\n", ((!direction)?'E':'D')); eprintf ("Currently supported hashes:\n"); ut64 bits; int i; for (i = 0; ; i++) { bits = ((ut64)1) << i; const char *name = r_hash_name (bits); if (!name || !*name) break; printf (" %s\n", name); } eprintf ("Available Encoders/Decoders: \n"); // TODO: do not hardcode eprintf (" base64\n"); eprintf (" base91\n"); eprintf (" punycode\n"); eprintf ("Currently supported crypto algos:\n"); for (i = 0; ; i++) { bits = ((ut64)1) << i; const char *name = r_crypto_name (bits); if (!name || !*name) break; printf (" %s\n", name); } } free (args); } break; case 'p': // debrujin patterns switch (input[2]) { case 'D': // "wopD" len = (int)(input[3]==' ') ? r_num_math (core->num, input + 3) : core->blocksize; if (len > 0) { /* XXX This seems to fail at generating long patterns (wopD 512K) */ buf = (ut8*)r_debruijn_pattern (len, 0, NULL); //debruijn_charset); if (buf) { const ut8 *ptr = buf; ut64 addr = core->offset; if (input[3] == '*') { int i; r_cons_printf ("wx "); for (i = 0; i < len; i++) { r_cons_printf ("%02x", buf[i]); } r_cons_newline (); } else { while (true) { int res = r_core_write_at (core, addr, ptr, len); if (res < 1 || len == res) { break; } if (res < len) { ptr += res; len -= res; addr += res; } } } free (buf); } else { eprintf ("Couldn't generate pattern of length %d\n", len); } } break; case 'O': // "wopO" if (strlen (input) > 4 && strncmp (input + 4, "0x", 2)) { eprintf ("Need hex value with `0x' prefix e.g. 0x41414142\n"); } else if (input[3] == ' ') { value = r_num_get (core->num, input + 4); core->num->value = r_debruijn_offset (value, r_config_get_i (core->config, "cfg.bigendian")); r_cons_printf ("%"PFMT64d"\n", core->num->value); } break; case '\0': case '?': default: r_core_cmd_help (core, help_msg_wop); break; } break; case '\0': case '?': default: r_core_cmd_help (core, help_msg_wo); break; } }
static int r_core_magic_at(RCore *core, const char *file, ut64 addr, int depth, int v) { const char *fmt; char *q, *p; const char *str; int found = 0, delta = 0, adelta = 0; #define NAH 32 if (--depth<0) { return 0; } if (addr != core->offset) { #if 1 if (addr >= core->offset && (addr+NAH) < (core->offset + core->blocksize)) { delta = addr - core->offset; } else { r_core_seek (core, addr, true); } #endif } if (core->search->align) { int mod = addr % core->search->align; if (mod) { eprintf ("Unaligned search at %d\n", mod); return mod; } } if (((addr&7)==0) && ((addr&(7<<8))==0)) eprintf ("0x%08"PFMT64x"\r", addr); if (file) { if (*file == ' ') file++; if (!*file) file = NULL; } if (file && ofile && file != ofile) { if (strcmp (file, ofile)) { r_magic_free (ck); ck = NULL; } } if (ck==NULL) { // TODO: Move RMagic into RCore r_magic_free (ck); // allocate once ck = r_magic_new (0); if (file) { free (ofile); ofile = strdup (file); if (r_magic_load (ck, file) == -1) { eprintf ("failed r_magic_load (\"%s\") %s\n", file, r_magic_error (ck)); ck = NULL; return -1; } } else { const char *magicpath = r_config_get (core->config, "dir.magic"); if (r_magic_load (ck, magicpath) == -1) { ck = NULL; eprintf ("failed r_magic_load (dir.magic) %s\n", r_magic_error (ck)); return -1; } } } //repeat: //if (v) r_cons_printf (" %d # pm %s @ 0x%"PFMT64x"\n", depth, file? file: "", addr); if (delta+2>core->blocksize) { eprintf ("EOB\n"); return -1; } str = r_magic_buffer (ck, core->block+delta, core->blocksize-delta); if (str) { const char *cmdhit; #if USE_LIB_MAGIC if (!v && (!strcmp (str, "data") || strstr(str, "ASCII") || strstr(str, "ISO") || strstr(str, "no line terminator"))) { #else if (!v && (!strcmp (str, "data"))) { #endif int mod = core->search->align; if (mod<1) mod = 1; //r_magic_free (ck); //ck = NULL; //return -1; return mod+1; } p = strdup (str); fmt = p; // processing newlinez for (q=p; *q; q++) { if (q[0]=='\\' && q[1]=='n') { *q = '\n'; strcpy (q+1, q+((q[2]==' ')? 3: 2)); } } cmdhit = r_config_get (core->config, "cmd.hit"); if (cmdhit && *cmdhit) { r_core_cmd0 (core, cmdhit); } // TODO: This must be a callback .. move this into RSearch? r_cons_printf ("0x%08"PFMT64x" %d %s\n", addr + adelta, magicdepth-depth, p); r_cons_clear_line (1); eprintf ("0x%08"PFMT64x" 0x%08"PFMT64x" %d %s\n", addr+adelta, addr+adelta, magicdepth-depth, p); // walking children for (q=p; *q; q++) { switch (*q) { case ' ': fmt = q+1; break; case '@': { ut64 addr = 0LL; *q = 0; if (!memcmp (q+1, "0x", 2)) sscanf (q+3, "%"PFMT64x, &addr); else sscanf (q+1, "%"PFMT64d, &addr); if (!fmt || !*fmt) fmt = file; r_core_magic_at (core, fmt, addr, depth, 1); *q = '@'; } break; } } free (p); r_magic_free (ck); ck = NULL; found ++; // return adelta+1; } adelta ++; delta ++; #if 0 if((core->blocksize-delta)>16) goto repeat; #endif #if 0 r_magic_free (ck); ck = NULL; #endif { int mod = core->search->align; if (mod) { return mod; //adelta%addr + deR_ABS(mod-adelta)+1; } } return adelta; //found; } static void r_core_magic(RCore *core, const char *file, int v) { ut64 addr = core->offset; magicdepth = r_config_get_i (core->config, "magic.depth"); // TODO: do not use global var here r_core_magic_at (core, file, addr, magicdepth, v); if (addr != core->offset) r_core_seek (core, addr, true); }