void reil_flag_spew_inst(RAnalEsil *esil, const char *flag) { ut8 bit; switch (flag[0]) { case 'z': // zero-flag r_anal_esil_push(esil, esil->Reil->cur); break; case 'b': bit = (ut8)r_num_get(NULL, &flag[1]); reil_generate_borrow_flag(esil, bit); break; case 'c': bit = (ut8)r_num_get(NULL, &flag[1]); reil_generate_carry_flag(esil, bit); break; case 'o': reil_generate_overflow_flag(esil); break; case 'p': reil_generate_partity_flag(esil); break; case 'r': r_anal_esil_pushnum(esil, esil->anal->bits / 8); break; case 's': reil_generate_signature(esil); break; default: return; } return; }
R_API RSyscallItem *r_syscall_item_new_from_string(const char *name, const char *s) { RSyscallItem *si; char *o; if (!name || !s) { return NULL; } si = R_NEW0 (RSyscallItem); if (!si) { return NULL; } o = strdup (s); r_str_split (o, ','); si->name = strdup (name); si->swi = r_num_get (NULL, r_str_word_get0 (o, 0)); si->num = r_num_get (NULL, r_str_word_get0 (o, 1)); si->args = r_num_get (NULL, r_str_word_get0 (o, 2)); //in a definition such as syscall=0x80,0,4, //the string at index 3 is 0 causing oob read afterwards si->sargs = calloc (si->args + 1, sizeof (char)); if (!si->sargs) { free (si); free (o); return NULL; } strncpy (si->sargs, r_str_word_get0 (o, 3), si->args); free (o); return si; }
R_API RSyscallItem *r_syscall_item_new_from_string(const char *name, const char *s) { RSyscallItem *si; char *o; if (!s) return NULL; si = R_NEW0 (RSyscallItem); o = strdup (s); r_str_split (o, ','); /* return r_syscall_item_new (name, r_num_get (NULL, r_str_word_get0 (o, 0)), r_num_get (NULL, r_str_word_get0 (o, 1)), r_num_get (NULL, r_str_word_get0 (o, 2)), r_str_word_get0 (o, 3)); */ si->name = strdup (name); si->swi = r_num_get (NULL, r_str_word_get0 (o, 0)); si->num = r_num_get (NULL, r_str_word_get0 (o, 1)); si->args = r_num_get (NULL, r_str_word_get0 (o, 2)); si->sargs = strdup (r_str_word_get0 (o, 3)); free (o); return si; }
static bool gb_parse_ld2 (ut8 *buf, char *buf_asm) { int i; ut64 num; if (strlen (buf_asm) < 6) return false; if (buf_asm[4] == ',') { if ((i = gb_reg_idx (buf_asm[3])) == (-1)) return false; buf[0] = 0x6 + (ut8)(i * 8); num = r_num_get (NULL, &buf_asm[5]); buf[1] = (ut8)(num & 0xff); return true; } else if (buf_asm[3] == '[' && buf_asm[4] == 'h' && buf_asm[5] == 'l' && buf_asm[6] == ']' && buf_asm[7] == ',' && buf_asm[8] != '\0') { buf[0] = 0x36; num = r_num_get (NULL, &buf_asm[8]); buf[1] = (ut8)(num & 0xff); return true; } return false; }
static int cmp(const void *a, const void *b) { char *da = NULL; char *db = NULL; const char *ca = r_str_trim_ro (a); const char *cb = r_str_trim_ro (b); if (!a || !b) { return (int) (size_t) ((char*) a - (char*) b); } if (sorted_column > 0) { da = strdup (ca); db = strdup (cb); int colsa = r_str_word_set0 (da); int colsb = r_str_word_set0 (db); ca = (colsa > sorted_column)? r_str_word_get0 (da, sorted_column): ""; cb = (colsb > sorted_column)? r_str_word_get0 (db, sorted_column): ""; } if (IS_DIGIT (*ca) && IS_DIGIT (*cb)) { ut64 na = r_num_get (NULL, ca); ut64 nb = r_num_get (NULL, cb); int ret = na > nb; free (da); free (db); return ret; } if (da && db) { int ret = strcmp (ca, cb); free (da); free (db); return ret; } free (da); free (db); return strcmp (a, b); }
static RIODesc *__open(RIO *io, const char *file, int rw, int mode) { int pid = getpid (); self_sections_count = 0; #if __APPLE__ mach_port_t task; kern_return_t rc; rc = task_for_pid (mach_task_self(),pid, &task); if (rc) { eprintf ("task_for_pid failed\n"); return NULL; } macosx_debug_regions (task, (void*)(size_t)1, 1000); io->va = R_TRUE; // nop return r_io_desc_new (&r_io_plugin_self, pid, file, rw, mode, NULL); #elif __linux__ char *pos_c; char null[64]; char path[1024], line[1024]; char region[100], region2[100], perms[5]; snprintf (path, sizeof (path)-1, "/proc/%d/maps", pid); FILE *fd = fopen (file, "r"); if (!fd) return NULL; while (!feof (fd)) { line[0]='\0'; fgets (line, sizeof (line)-1, fd); if (line[0]=='\0') break; path[0]='\0'; sscanf (line, "%s %s %s %s %s %s", ®ion[2], perms, null, null, null, path); pos_c = strchr (®ion[2], '-'); if (pos_c) strncpy (path, pos_c, sizeof (path)-1); else path[0] = 0; int i, perm = 0; for (i = 0; perms[i] && i < 4; i++) switch (perms[i]) { case 'r': perm |= R_IO_READ; break; case 'w': perm |= R_IO_WRITE; break; case 'x': perm |= R_IO_EXEC; break; } self_sections[self_sections_count].from = r_num_get (NULL, region); self_sections[self_sections_count].to = r_num_get (NULL, region2); self_sections[self_sections_count].perm = perm; self_sections_count++; r_num_get (NULL, region2); if (!pos_c) continue; } return r_io_desc_new (&r_io_plugin_self, pid, file, rw, mode, NULL); #else #warning not yet implemented for this platform #endif return NULL; }
static void xrefs_list_cb_rad(RAnal *anal, const char *k, const char *v) { ut64 dst, src = r_num_get (NULL, v); if (!strncmp (k, "ref.", 4)) { char *p = strchr (k+4, '.'); if (p) { dst = r_num_get (NULL, p+1); anal->printf ("ar 0x%"PFMT64x" 0x%"PFMT64x"\n", src, dst); } } }
static int r_debug_bochs_breakpoint (RBreakpointItem *bp, int set, void *user) { char cmd[64]; char num[4]; char addr[19]; char bufcmd[100]; ut64 a; int n,i,lenRec; //eprintf ("bochs_breakpoint\n"); if (!bp) { return false; } if (set) { //eprintf("[set] bochs_breakpoint %016"PFMT64x"\n",bp->addr); sprintf (cmd, "lb 0x%x", (ut32)bp->addr); bochs_send_cmd (desc, cmd, true); bCapturaRegs = true; } else { //eprintf("[unset] bochs_breakpoint %016"PFMT64x"\n",bp->addr); /* Num Type Disp Enb Address 1 lbreakpoint keep y 0x0000000000007c00 2 lbreakpoint keep y 0x0000000000007c00 <bochs:39> */ bochs_send_cmd (desc,"blist",true); lenRec = strlen (desc->data); a = -1; n = 0; if (!strncmp (desc->data, "Num Type", 8)) { i = 37; do { if (desc->data[i + 24] == 'y') { strncpy(num, &desc->data[i], 3); num[3] = 0; strncpy(addr, &desc->data[i + 28], 18); addr[18] = 0; n = r_num_get (NULL,num); a = r_num_get (NULL,addr); //eprintf("parseado %x %016"PFMT64x"\n",n,a); if (a == bp->addr) { break; } } i += 48; } while (desc->data[i] != '<' && i<lenRec-4); } if (a == bp->addr) { snprintf (bufcmd, sizeof (bufcmd), "d %i", n); //eprintf("[unset] Break point localizado indice = %x (%x) %s \n",n,(DWORD)a,bufcmd); bochs_send_cmd (desc, bufcmd, true); } } return true; }
static int xrefs_list_cb_rad(RAnal *anal, const char *k, const char *v) { ut64 dst, src = r_num_get (NULL, v); if (!strncmp (k, "ref.", 4)) { const char *p = r_str_rchr (k, NULL, '.'); if (p) { dst = r_num_get (NULL, p + 1); anal->cb_printf ("ax 0x%"PFMT64x" 0x%"PFMT64x"\n", src, dst); } } return 1; }
static void xrefs_list_cb_json(RAnal *anal, const char *k, const char *v) { ut64 dst, src = r_num_get (NULL, v); if (!strncmp (k, "ref.", 4) && (strlen (k)>8)) { char *p = strchr (k+4, '.'); if (p) { dst = r_num_get (NULL, p+1); sscanf (p+1, "0x%"PFMT64x, &dst); anal->printf ("%"PFMT64d":%"PFMT64d",", src, dst); } } }
static int xrefs_list_cb_any(RAnal *anal, const char *k, const char *v) { //ut64 dst, src = r_num_get (NULL, v); if (!strncmp (_kpfx, k, strlen (_kpfx))) { RAnalRef *ref = r_anal_ref_new (); if (ref) { ref->addr = r_num_get (NULL, k + strlen (_kpfx) + 1); ref->at = r_num_get (NULL, v); // XXX ref->type = _type; r_list_append (_list, ref); } } return true; }
static int gb_parse_arith1 (ut8 *buf, const int minlen, char *buf_asm, ut8 base, ut8 alt) { int i; ut64 num; if (strlen (buf_asm) < minlen) return 0; buf[0] = base; i = strlen (&buf_asm[minlen - 1]); r_str_replace_in (&buf_asm[minlen - 1], (ut32)i, "[ ", "[", R_TRUE); r_str_replace_in (&buf_asm[minlen - 1], (ut32)i, " ]", "]", R_TRUE); r_str_do_until_token (str_op, buf_asm, ' '); i = gb_reg_idx (buf_asm[minlen-1]); if (i != (-1)) buf[0] |= (ut8)i; else if (buf_asm[minlen - 1] == '[' && buf_asm[minlen] == 'h' && buf_asm[minlen + 1] == 'l' && buf_asm[minlen + 2] == ']' ) buf[0] |= 6; else { buf[0] = alt; num = r_num_get (NULL, &buf_asm[minlen - 1]); buf[1] = (ut8)(num & 0xff); return 2; } return 1; }
R_API RIO *r_io_new() { RIO *io = R_NEW0 (RIO); if (!io) { return NULL; } io->buffer = r_cache_new (); // RCache is a list of ranged buffers. maybe rename? io->write_mask_fd = -1; io->cb_printf = (void *)printf; io->bits = (sizeof (void *) == 8)? 64: 32; io->ff = true; io->Oxff = 0xff; io->aslr = 0; io->pava = false; io->raised = -1; io->autofd = true; r_io_map_init (io); r_io_desc_init (io); r_io_undo_init (io); r_io_cache_init (io); r_io_plugin_init (io); r_io_section_init (io); { char *env = r_sys_getenv ("R_IO_MAX_ALLOC"); if (env) { io->maxalloc = r_num_get (NULL, env); free (env); } } return io; }
R_API int r_anal_xrefs_from (RAnal *anal, RList *list, const char *kind, const RAnalRefType type, ut64 addr) { char *next, *s, *str, *ptr, key[256]; RAnalRef *ref = NULL; if (addr == UT64_MAX) { _type = type; _list = list; _kpfx = r_str_newf ("xref.%s", analref_toString (type)); sdb_foreach (DB, (SdbForeachCallback)xrefs_list_cb_any, anal); free (_kpfx); return true; } XREFKEY(key, sizeof (key), kind, type, addr); str = sdb_get (DB, key, 0); if (!str) { return false; } for (next = ptr = str; next; ptr = next) { s = sdb_anext (ptr, &next); if (!(ref = r_anal_ref_new ())) { return false; } ref->addr = r_num_get (NULL, s); ref->at = addr; ref->type = type; r_list_append (list, ref); } free (str); return true; }
static int cin_get_num(RNum *num, RNumCalc *nc, RNumCalcValue *n) { double d; char str[R_NUMCALC_STRSZ]; // TODO: move into the heap? int i = 0; char c; str[0] = 0; while (cin_get (num, nc, &c)) { if (c != '_' && c!=':' && c!='.' && !isalnum ((ut8)c)) { cin_putback (num, nc, c); break; } if (i < R_NUMCALC_STRSZ) { str[i++] = c; } } str[i] = 0; *n = Nset (r_num_get (num, str)); if (IS_DIGIT (*str) && strchr (str, '.')) { if (sscanf (str, "%lf", &d) < 1) { return 0; } if (n->n < d) { *n = Nsetf (d); } n->d = d; } return 1; }
static int r_buf_fcpy_at (RBuffer *b, ut64 addr, ut8 *buf, const char *fmt, int n, int write) { ut64 len, check_len; int i, j, k, tsize, endian, m = 1; if (!b || b->empty) return 0; if (addr == R_BUF_CUR) addr = b->cur; else addr -= b->base; if (addr == UT64_MAX || addr > b->length) return -1; tsize = 2; for (i = len = 0; i < n; i++) for (j = 0; fmt[j]; j++) { switch (fmt[j]) { case '0'...'9': if (m == 1) m = r_num_get (NULL, &fmt[j]); continue; case 's': tsize = 2; endian = 1; break; case 'S': tsize = 2; endian = 0; break; case 'i': tsize = 4; endian = 1; break; case 'I': tsize = 4; endian = 0; break; case 'l': tsize = 8; endian = 1; break; case 'L': tsize = 8; endian = 0; break; case 'c': tsize = 1; endian = 1; break; default: return -1; } /* Avoid read/write out of bound. tsize and m are not user controled, then don't need to check possible overflow. */ if (!UT64_ADD (&check_len, len, tsize*m)) return -1; if (!UT64_ADD (&check_len, check_len, addr)) return -1; if (check_len > b->length) { return check_len; // return -1; } for (k = 0; k < m; k++) { if (write) { r_mem_copyendian ( (ut8*)&buf[addr+len+(k*tsize)], (ut8*)&b->buf[len+(k*tsize)], tsize, endian); } else { r_mem_copyendian ( (ut8*)&buf[len+(k*tsize)], (ut8*)&b->buf[addr+len+(k*tsize)], tsize, endian); } } len += tsize*m; m = 1; } b->cur = addr + len; return len; }
static bool xrefs_list_cb_json(RAnal *anal, bool is_first, const char *k, const char *v) { ut64 dst, src = r_num_get (NULL, v); if (strlen (k) > 8) { const char *p = r_str_rchr (k, NULL, '.'); if (p) { if (is_first) { is_first = false; } else { anal->cb_printf (","); } dst = r_num_get (NULL, p + 1); sscanf (p + 1, "0x%"PFMT64x, &dst); anal->cb_printf ("\"%"PFMT64d"\":%"PFMT64d, src, dst); } } return is_first; }
static ut64 esil_get (RAnalEsil *e, const char *s) { RRegItem *item; // check for register if (!s) return 0LL; item = r_reg_get (e->anal->reg, s, 0); // GPR only wtf? if (item) return r_reg_get_value (e->anal->reg, item); return r_num_get (NULL, s); }
R_API void r_anal_esil_trace_show(RAnalEsil *esil, int idx) { PrintfCallback p = esil->anal->printf; const char *str2; const char *str; int trace_idx = esil->trace_idx; esil->trace_idx = idx; str2 = sdb_const_get (DB, KEY ("addr"), 0); if (!str2) { return; } p ("dr pc = %s\n", str2); /* registers */ str = sdb_const_get (DB, KEY ("reg.read"), 0); if (str) { char regname[32]; const char *next, *ptr = str; if (ptr && *ptr) { do { const char *ztr = sdb_const_anext (ptr, &next); int len = next? (int)(size_t)(next-ztr)-1 : strlen (ztr); if (len <sizeof(regname)) { memcpy (regname, ztr, len); regname[len] = 0; str2 = sdb_const_get (DB, KEYREG ("reg.read", regname), 0); p ("dr %s = %s\n", regname, str2); } else { eprintf ("Invalid entry in reg.read\n"); } ptr = next; } while (next); } } /* memory */ str = sdb_const_get (DB, KEY ("mem.read"), 0); if (str) { char addr[64]; const char *next, *ptr = str; if (ptr && *ptr) { do { const char *ztr = sdb_const_anext (ptr, &next); int len = next? (int)(size_t)(next-ztr)-1 : strlen (ztr); if (len <sizeof(addr)) { memcpy (addr, ztr, len); addr[len] = 0; str2 = sdb_const_get (DB, KEYAT ("mem.read.data", r_num_get (NULL, addr)), 0); p ("wx %s @ %s\n", str2, addr); } else { eprintf ("Invalid entry in reg.read\n"); } ptr = next; } while (next); } } esil->trace_idx = trace_idx; }
R_API int r_hex_str2bin(const char *in, ut8 *out) { unsigned int len = 0, j = 0; const char *ptr; ut8 c = 0, d = 0; if (!memcmp (in, "0x", 2)) in += 2; for (ptr = in; ; ptr++) { /* ignored chars */ if (*ptr==':' || *ptr=='\n' || *ptr=='\t' || *ptr=='\r' || *ptr==' ') continue; if (j==2) { out[len] = c; len++; c = j = 0; if (ptr[0]==' ') continue; } /* break after len++ */ if (ptr[0] == '\0') break; d = c; if (ptr[0]=='0' && ptr[1]=='x' ){ //&& c==0) { ut64 addr = r_num_get (NULL, ptr); unsigned int addr32 = (ut32) addr; if (addr & ~0xFFFFFFFF) { // 64 bit fun } else { // 32 bit fun ut8 *addrp = (ut8*) &addr32; // XXX always copy in native endian? out[len++] = addrp[0]; out[len++] = addrp[1]; out[len++] = addrp[2]; out[len++] = addrp[3]; while (*ptr && *ptr!=' ' && *ptr!='\t') ptr++; j = 0; } continue; } if (r_hex_to_byte (&c, ptr[0])) { //eprintf("binstr: Invalid hexa string at %d ('0x%02x') (%s).\n", (int)(ptr-in), ptr[0], in); return -1; } c |= d; if (j++ == 0) c <<= 4; } // has nibbles. requires a mask if (j) { out[len] = c; len = -len; } return (int)len; }
static int getswi(Sdb *p, int swi) { if (p && swi == -1) { // TODO: use array_get_num here const char *def = sdb_const_get (p, "_", 0); if (def && *def) { swi = r_num_get (NULL, def); } else swi = 0x80; // XXX hardcoded } return swi; }
// finds the address of the call function (essentially where to jump to). static ut64 get_cf_offset(RAnal *anal, const ut8 *data) { r_cons_push (); char *s = anal->coreb.cmdstrf (anal->coreb.core, "isq~[0:%d]", data[1]); r_cons_pop (); if (s) { ut64 n = r_num_get (NULL, s); free (s); return n; } return UT64_MAX; }
static int r_debug_bochs_wait(RDebug *dbg, int pid) { char strIP[19]; int i = 0; const char *x; char *ini = 0, *fin = 0; //eprintf ("bochs_wait:\n"); if (bStep) { bStep = false; } else { r_cons_break_push (bochs_debug_break, dbg); i = 500; do { bochs_wait (desc); if (bBreak) { if (desc->data[0]) { eprintf ("ctrl+c %s\n", desc->data); bBreak = false; break; } i--; if (!i) { bBreak = false; eprintf ("empty ctrl+c.\n"); break; } } else if (desc->data[0]) { //eprintf("stop on breakpoint%s\n",desc->data); break; } } while(1); r_cons_break_pop (); } //eprintf ("bochs_wait: loop done\n"); i = 0; // Next at t=394241428 // (0) [0x000000337635] 0020:0000000000337635 (unk. ctxt): add eax, esi ; 03c6 ripStop = 0; if ((x = strstr (desc->data, "Next at"))) { if ((ini = strstr (x, "[0x"))) { if ((fin = strstr (ini,"]"))) { int len = fin - ini - 1; strncpy (strIP, ini+1, len); strIP[len] = 0; //eprintf(" parada EIP = %s\n",strIP); ripStop = r_num_get (NULL, strIP); } } } desc->data[0] = 0; return true; }
static int getswi(RPair *p, int swi) { char *def; if (swi == -1) { def = r_pair_get (p, "_"); if (def && *def) { swi = r_num_get (NULL, def); free (def); } else swi = 0x80; // XXX hardcoded } return swi; }
R_API static ut64 r_num_math_internal(RNum *num, char *s) { ut64 ret = 0LL; char *p = s; int i, nop, op = 0; for (i=0; s[i]; i++) { switch (s[i]) { case '+': case '-': case '*': case '/': case '&': case '^': case '|': nop = s[i]; s[i] = '\0'; ret = r_num_op (op, ret, r_num_get (num, p)); op = s[i] = nop; p = s + i + 1; break; } } return r_num_op (op, ret, r_num_get (num, p)); }
R_API int r_syscall_get_num(RSyscall *ctx, const char *str) { char *o; int i = 0; if (!ctx->syspair) return 0; o = r_pair_get (ctx->syspair, str); if (o && *o) { r_str_split (o, ','); i = r_num_get (NULL, r_str_word_get0 (o, 1)); } free (o); return i; }
R_API int r_syscall_get_num(RSyscall *s, const char *str) { char *o; int i = -1; // TODO: use sdb array api here if (!s || !s->db) return -1; o = sdb_get (s->db, str, 0); if (o && *o) { r_str_split (o, ','); i = r_num_get (NULL, r_str_word_get0 (o, 1)); } free (o); return i; }
static RNumCalcValue prim(RNum *num, RNumCalc *nc, int get) { RNumCalcValue v = {0}; if (get) get_token (num, nc); switch (nc->curr_tok) { case RNCNUMBER: v = nc->number_value; get_token (num, nc); return v; case RNCNAME: //fprintf (stderr, "error: unknown keyword (%s)\n", nc->string_value); //double& v = table[nc->string_value]; r_str_chop (nc->string_value); v = Nset (r_num_get (num, nc->string_value)); get_token (num, nc); if (nc->curr_tok == RNCASSIGN) { v = expr (num, nc, 1); } if (nc->curr_tok == RNCINC) Naddi (v, 1); if (nc->curr_tok == RNCDEC) Nsubi (v, 1); return v; case RNCNEG: v = nc->number_value; get_token (num, nc); return Nneg (nc->number_value); //prim (num, nc, 1), 1); case RNCINC: return Naddi (prim (num, nc, 1), 1); case RNCDEC: return Naddi (prim (num, nc, 1), -1); case RNCORR: return Norr (v, prim (num, nc, 1)); case RNCMINUS: return Nsub (v, prim (num, nc, 1)); case RNCLEFTP: v = expr (num, nc, 1); if (nc->curr_tok == RNCRIGHTP) { get_token (num, nc); } else error (num, nc, " ')' expected"); case RNCEND: case RNCXOR: case RNCAND: case RNCPLUS: case RNCMOD: case RNCMUL: case RNCDIV: case RNCPRINT: case RNCASSIGN: case RNCRIGHTP: return v; //default: error (num, nc, "primary expected"); } return v; }
// finds the address of the call function (essentially where to jump to). static ut64 get_cf_offset(RAnal *anal, const ut8 *data, int len) { ut32 fcn_id; if (!read_u32_leb128 (&data[1], &data[len - 1], &fcn_id)) { return UT64_MAX; } r_cons_push (); // 0xfff.. are bad addresses for wasm // cgvwzq: 0xfff... can be external imported JS funcs char *s = anal->coreb.cmdstrf (anal->coreb.core, "is~FUNC[2:%u]", fcn_id); r_cons_pop (); if (s) { ut64 n = r_num_get (NULL, s); free (s); return n; } return UT64_MAX; }
R_API int r_anal_xrefs_from (RAnal *anal, RList *list, const char *kind, const char *type, ut64 addr) { char *s, *str, *ptr, key[256]; RAnalRef *ref = NULL; int hasnext = 1; snprintf (key, sizeof (key), "%s.%s.0x%"PFMT64x, kind, type, addr); str = sdb_get (DB, key, 0); if (!str) return R_FALSE; for (ptr=str; hasnext; ptr = (char *)sdb_anext (s)) { s = sdb_astring (ptr, &hasnext); if (!(ref = r_anal_ref_new ())) return R_FALSE; ref->addr = addr; ref->at = r_num_get (NULL, s); ref->type = (!strcmp (type, "code"))?'C':'d'; // XXX r_list_append (list, ref); } free (str); return R_TRUE; }