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); }
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; }
bool test_r_str_tokenize(void) { //XXX r_str_word0 doesn't work on "hello world" to // tokenize into ["hello", "world"] char* hi = strdup ("hello world"); mu_assert_eq (r_str_word_set0 (hi), 1, "tokenize hello world"); const char* hello = r_str_word_get0 (hi, 0); const char* world = r_str_word_get0 (hi, 1); mu_assert_streq (hello, "hello", "first string in split"); mu_assert_streq (world, "world", "second string in split"); free (hi); mu_end; }
R_API char *r_str_word_get0set(char *stra, int stralen, int idx, const char *newstr, int *newlen) { char *p = NULL; char *out; int alen, blen, nlen; if (!stra && !newstr) return NULL; if (stra) p = (char *)r_str_word_get0 (stra, idx); if (!p) { int nslen = strlen (newstr); out = malloc (nslen+1); if (!out) return NULL; strcpy (out, newstr); out[nslen] = 0; if (newlen) *newlen = nslen; return out; } alen = (size_t)(p-stra); blen = stralen - ((alen + strlen (p))+1); if (blen<0) blen = 0; nlen = alen+blen+strlen (newstr); out = malloc (nlen + 2); if (!out) return NULL; if (alen>0) memcpy (out, stra, alen); memcpy (out+alen, newstr, strlen (newstr)+1); if (blen>0) memcpy (out+alen+strlen (newstr)+1, p+strlen (p)+1, blen+1); out[nlen+1] = 0; if (newlen) *newlen = nlen + ((blen==0)?1:0); return out; }
static void setnewline(int old) { snprintf (prompt, sizeof (prompt), "%d: ", _n); r_line_set_prompt (prompt); strcpy (I->line->buffer.data, r_str_word_get0 (lines, _n)); I->line->buffer.index = I->line->buffer.length = strlen (I->line->buffer.data); I->line->contents = I->line->buffer.data; }
/* Get offset of given named field inside the table */ int r_db_table_key(struct r_db_table_t *table, const char *name) { const char *word; int i; for(i=0;i<table->nelems;i++) { word = r_str_word_get0(table->args, i); if (!strcmp(name, word)) break; } return table->offset[i]; }
R_API char *r_type_get_struct_memb(Sdb *TDB, const char *type, int offset) { int i, typesize = 0; char *res = NULL; if (offset < 0) { return NULL; } char* query = sdb_fmt ("struct.%s", type); char *members = sdb_get (TDB, query, 0); if (!members) { //eprintf ("%s is not a struct\n", type); return NULL; } int nargs = r_str_split (members, ','); for (i = 0; i < nargs ; i++) { const char *name = r_str_word_get0 (members, i); if (!name) { break; } query = sdb_fmt ("struct.%s.%s", type, name); char *subtype = sdb_get (TDB, query, 0); if (!subtype) { break; } int len = r_str_split (subtype, ','); if (len < 3) { free (subtype); break; } int val = r_num_math (NULL, r_str_word_get0 (subtype, len - 1)); int arrsz = val ? val : 1; if ((typesize / 8) == offset) { res = r_str_newf ("%s.%s", type, name); free (subtype); break; } typesize += r_type_get_bitsize (TDB, subtype) * arrsz; free (subtype); } free (members); return res; }
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; }
/* Get name of the N field in the table */ const char *r_db_table_field_i(struct r_db_table_t *table, int elem) { const char *name = NULL; if (elem>=0 && table->nelems<elem) name = r_str_word_get0 (table->args, elem); return name; }
R_API int r_print_format(RPrint *p, ut64 seek, const ut8* b, const int len, const char *formatname, int mode, const char *setval, char *ofield) { int nargs, i, j, invalid, nexti, idx, times, otimes, endian, isptr = 0; const int old_bits = p->bits; char *args = NULL, *bracket, tmp, last = 0; ut64 addr = 0, addr64 = 0, seeki = 0; static int slide = 0, oldslide = 0; char namefmt[8], *field = NULL; const char *arg = NULL; const char *fmt = NULL; const char *argend; int viewflags = 0; char *oarg = NULL; ut8 *buf; /* Load format from name into fmt */ if (!formatname) return 0; fmt = r_strht_get (p->formats, formatname); if (!fmt) fmt = formatname; while (*fmt && iswhitechar (*fmt)) fmt++; argend = fmt+strlen (fmt); arg = fmt; nexti = nargs = i = j = 0; if (len < 1) return 0; // len+2 to save space for the null termination in wide strings buf = calloc (1,len + 2); if (!buf) return 0; memcpy (buf, b, len); endian = p->big_endian; if (ofield && ofield != MINUSONE) field = strdup (ofield); /* get times */ otimes = times = atoi (arg); if (times > 0) { while (*arg >= '0' && *arg <= '9') arg++; } bracket = strchr (arg,'{'); if (bracket) { char *end = strchr (arg, '}'); if (end == NULL) { eprintf ("No end bracket. Try pm {ecx}b @ esi\n"); goto beach; } *end = '\0'; times = r_num_math (NULL, bracket+1); arg = end + 1; } if (*arg=='\0') { goto beach; } /* get args */ args = get_args_offset (arg); if (args) { int l=0, maxl = 0; argend = args; args = strdup (args+1); nargs = r_str_word_set0 (args); if (nargs == 0) R_FREE (args); for (i=0; i<nargs; i++) { const int len = strlen (r_str_word_get0 (args, i)); if (len > maxl) maxl = len; } l++; snprintf (namefmt, sizeof (namefmt), "%%%ds : ", maxl+6*slide%STRUCTPTR); } #define ISPOINTED ((slide%STRUCTFLAG)/STRUCTPTR<=(oldslide%STRUCTFLAG)/STRUCTPTR) #define ISNESTED ((slide%STRUCTPTR)<=(oldslide%STRUCTPTR)) if (mode == R_PRINT_JSON && slide==0) p->cb_printf("["); if (arg[0] == '0') { mode |= R_PRINT_UNIONMODE; arg++; } else { mode &= ~R_PRINT_UNIONMODE; } if (mode & R_PRINT_DOT) { char *fmtname; if (formatname && *formatname) { if (strchr (formatname, ' ')) { fmtname = r_str_newf ("0x%"PFMT64x, seek); } else { fmtname = strdup (formatname); } } else { fmtname = r_str_newf ("0x%"PFMT64x, seek); } p->cb_printf ("digraph g { graph [ rank=same; rankdir=LR; ];\n"); p->cb_printf ("root [ rank=1; shape=record\nlabel=\"%s", fmtname); } /* go format */ i = 0; if (!times) otimes = times = 1; for (; times; times--) { // repeat N times const char * orig = arg; int first = 1; if (otimes>1) { if (mode & R_PRINT_JSON) { if (otimes > times) p->cb_printf (","); p->cb_printf ("[{\"index\":%d,\"offset\":%d},", otimes-times, seek+i); } else { p->cb_printf ("0x%08"PFMT64x" [%d] {\n", seek+i, otimes-times); } } arg = orig; for (idx=0; i<len && arg<argend && *arg; arg++) { int size = 0, elem = 0; /* size of the array, element of the array */ char *fieldname = NULL, *fmtname = NULL; if (mode & R_PRINT_UNIONMODE) { i = 0; } seeki = seek+i; addr = 0LL; invalid = 0; p->bits = old_bits; if (arg[0] == '[') { char *end = strchr (arg,']'); if (end == NULL) { eprintf ("No end bracket.\n"); goto beach; } *end = '\0'; size = r_get_size (p->num, buf, endian, arg+1); arg = end + 1; *end = ']'; } else { size = -1; } if (i+7<len) { // Max byte number where updateAddr will look into updateAddr (buf, i, endian, &addr, &addr64); } else { eprintf ("Likely a heap buffer overflow in %s at %d\n", __FILE__, __LINE__); goto beach; } tmp = *arg; if (args == NULL) mode |= R_PRINT_ISFIELD; if (mode & R_PRINT_MUSTSEE && otimes>1) p->cb_printf (" "); if (idx<nargs && tmp != 'e' && isptr == 0) { char *dot = NULL, *bracket = NULL; if (field) dot = strchr (field, '.'); if (dot) *dot = '\0'; if (oarg != NULL) free (oarg); oarg = fieldname = strdup(r_str_word_get0 (args, idx)); if (ISSTRUCT || tmp=='E' || tmp=='B' || tmp=='r') { if (*fieldname == '(') { fmtname = fieldname+1; fieldname = strchr (fieldname, ')'); if (fieldname) *fieldname++ = '\0'; else { eprintf ("Missing closing parenthesis in format ')'\n"); goto beach; } } else { eprintf ("Missing name (%s)\n", fieldname); goto beach; } } if (args == NULL || (field==NULL && ofield != MINUSONE) || (field && !strncmp(field, fieldname, strchr(field, '[')!=NULL?strchr(field, '[')-field:strlen(field)+1))) { mode |= R_PRINT_ISFIELD; } else { mode &= ~R_PRINT_ISFIELD; } /* There we handle specific element in array */ if (field != NULL && (bracket = strchr (field, '[')) != NULL && mode & R_PRINT_ISFIELD) { char *end = strchr (field, ']'); if (end == NULL) { eprintf ("Missing closing bracket\n"); goto beach; } *end = '\0'; elem = r_num_math (NULL, bracket+1)+1; // +1 to handle 0 index easily for ( ; bracket < end; bracket++) *bracket = '\0'; size += elem*ARRAYINDEX_COEF; } else { elem = -1; } idx++; if (MUSTSEE && !SEEVALUE) { p->cb_printf (namefmt, fieldname); } } feed_me_again: switch (isptr) { case PTRSEEK: { nexti = i + (p->bits/8); i = 0; if (tmp == '?' ) seeki = addr; memset (buf, '\0', len); if (MUSTSEE) p->cb_printf ("(*0x%"PFMT64x") ", addr); if (addr == 0) isptr = NULLPTR; else isptr = PTRBACK; if (/*addr<(b+len) && addr>=b && */p->iob.read_at) { /* The test was here to avoid segfault in the next line, but len make it doesnt work... */ p->iob.read_at (p->iob.io, (ut64)addr, buf, len-4); if (i+3<len || i+7<len) updateAddr (buf, i, endian, &addr, &addr64); else { eprintf ("Likely a heap buffer overflow at %s at %d\n", __FILE__, __LINE__); goto beach; } } else { eprintf ("(SEGFAULT: cannot read memory at 0x%08"PFMT64x", Block: %s, blocksize: 0x%x)\n", addr, b, len); p->cb_printf("\n"); goto beach; } } break; case PTRBACK: // restore state after pointer seek i = nexti; memcpy (buf, b, len); isptr = NOPTR; arg--; continue; } if (tmp == 0 && last != '*') break; /* skip chars */ switch (tmp) { case '*': // next char is a pointer isptr = PTRSEEK; arg++; tmp = *arg; //last; goto feed_me_again; case '+': // toggle view flags viewflags = !viewflags; continue; case 'e': // tmp swap endian endian ^= 1; continue; case ':': // skip 4 bytes if (size == -1) i+=4; else while (size--) i+=4; continue; case '.': // skip 1 byte if (size == -1) i++; else i+=size; continue; case 'p': // pointer reference if (*(arg+1) == '2') { p->bits = 16; arg++; } else if (*(arg+1) == '4') { p->bits = 32; arg++; } else if (*(arg+1) == '8') { p->bits = 64; arg++; } switch (p->bits) { case 16: tmp = 'w'; break; case 32: tmp = 'x'; break; default: tmp = 'q'; break; } break; } /* flags */ if (mode & R_PRINT_SEEFLAGS && isptr != NULLPTR) { char *newname = NULL; if (!fieldname) { newname = fieldname = r_str_newf ("pf.%d", seeki); } if (mode & R_PRINT_UNIONMODE) { p->cb_printf ("f %s=0x%08"PFMT64x"\n", formatname, seeki); goto beach; } else if (tmp == '?') { p->cb_printf ("f %s.%s_", fmtname, fieldname); } else if (tmp == 'E') { p->cb_printf ("f %s=0x%08"PFMT64x"\n", fieldname, seeki); } else if (slide/STRUCTFLAG>0 && idx==1) { p->cb_printf ("%s=0x%08"PFMT64x"\n", fieldname, seeki); } else p->cb_printf ("f %s=0x%08"PFMT64x"\n", fieldname , seeki); if (newname) { free (newname); newname = fieldname = NULL; } } /* dot */ if (mode & R_PRINT_DOT) { if (fieldname) { p->cb_printf ("|{0x%"PFMT64x"|%c|%s|<%s>", seeki, tmp, fieldname, fieldname); } else { p->cb_printf ("|{0x%"PFMT64x"|%c|", seeki, tmp); } } /* json */ if (MUSTSEEJSON && mode & R_PRINT_JSON) { if (oldslide <= slide) { if (first) first = 0; else p->cb_printf (","); } else if (oldslide) { p->cb_printf ("]},"); } p->cb_printf ("{\"name\":\"%s\",\"type\":\"", fieldname); if (ISSTRUCT) { p->cb_printf ("%s", fmtname); } else { p->cb_printf ("%c", tmp); } if (isptr) p->cb_printf ("*"); p->cb_printf ("\",\"offset\":%d,\"value\":",(isptr)?(seek+nexti-(p->bits/8)):seek+i); } if (isptr == NULLPTR) { if (MUSTSEEJSON) p->cb_printf ("\"NULL\"}", tmp, seek+i); else if (MUSTSEE) p->cb_printf ("NULL\n"); isptr = PTRBACK; } else /* format chars */ // before to enter in the switch statement check buf boundaries due to updateAddr // might go beyond its len and it's usually called in each of the following functions if (((i+3)<len) || (i+7)<len) { switch (tmp) { case 'u': i+= r_print_format_uleb (p, endian, mode, setval, seeki, buf, i, size); break; case 't': r_print_format_time (p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 4 : 4*size; break; case 'q': r_print_format_quadword (p, endian, mode, setval, seeki, buf, i, size); i += (size==-1) ? 8 : 8*size; break; case 'b': r_print_format_byte (p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 1 : size; break; case 'C': r_print_format_decchar (p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 1 : size; break; case 'c': r_print_format_char (p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 1 : size; break; case 'X': size = r_print_format_hexpairs (p, endian, mode, setval, seeki, buf, i, size); i += size; break; case 'T': if (r_print_format_10bytes (p, mode, setval, seeki, addr, buf) == 0) i += (size==-1) ? 4 : 4*size; break; case 'f': r_print_format_float (p, endian, mode, setval, seeki, buf, i, size); i += (size==-1) ? 4 : 4*size; break; case 'i': case 'd': r_print_format_hex (p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 4 : 4*size; break; case 'D': if (size>0) p->cb_printf ("Size not yet implemented\n"); if (p->disasm && p->user) i += p->disasm (p->user, seeki); break; case 'o': r_print_format_octal (p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 4 : 4*size; break; case 'x': r_print_format_hexflag (p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 4 : 4*size; break; case 'w': r_print_format_word(p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 2 : 2*size; break; case 'z': // zero terminated string r_print_format_nulltermstring (p, len, endian, mode, setval, seeki, buf, i, size); if (size == -1) i+=strlen((char*)buf+i)+1; else while (size--) i++; break; case 'Z': // zero terminated wide string r_print_format_nulltermwidestring (p, len, endian, mode, setval, seeki, buf, i, size); if (size == -1) i += r_wstr_clen((char*)(buf+i))*2+2; else while (size--) i+=2; break; case 's': if (r_print_format_string (p, seeki, addr64, addr, 0, mode) == 0) i += (size==-1) ? 4 : 4*size; break; case 'S': if (r_print_format_string (p, seeki, addr64, addr, 1, mode) == 0) i += (size==-1) ? 8 : 8*size; break; case 'B': // resolve bitfield if (size >= ARRAYINDEX_COEF) size %= ARRAYINDEX_COEF; r_print_format_bitfield (p, seeki, fmtname, fieldname, addr, mode, size); i+=(size==-1)?1:size; break; case 'E': // resolve enum if (size >= ARRAYINDEX_COEF) size %= ARRAYINDEX_COEF; r_print_format_enum (p, seeki, fmtname, fieldname, addr, mode, size); i+=(size==-1)?1:size; break; case 'r': r_print_format_register (p, mode, fmtname, setval); break; case '?': { int s = 0; char *nxtfield = NULL; if (size >= ARRAYINDEX_COEF) { elem = size/ARRAYINDEX_COEF-1; size %= ARRAYINDEX_COEF; } if (!(mode & R_PRINT_ISFIELD)) nxtfield = MINUSONE; else if (field) nxtfield = strchr (ofield, '.'); if (nxtfield != MINUSONE && nxtfield != NULL) nxtfield++; if (MUSTSEE) if (!SEEVALUE) p->cb_printf ("\n"); if (MUSTSEEJSON) { if (isptr) p->cb_printf ("%d},", seeki); else p->cb_printf ("["); } if (mode & R_PRINT_SEEFLAGS) slide+=STRUCTFLAG; oldslide = slide; slide += (isptr) ? STRUCTPTR : NESTEDSTRUCT; if (size == -1) { s = r_print_format_struct (p, seeki, buf+i, len-i, fmtname, slide, mode, setval, nxtfield); i+= (isptr) ? 4 : s; } else { if (mode & R_PRINT_ISFIELD) if (!SEEVALUE) p->cb_printf ("[\n"); while (size--) { if (elem == -1 || elem == 0) { mode |= R_PRINT_MUSTSEE; if (elem == 0) elem = -2; } else { mode &= ~R_PRINT_MUSTSEE; } s = r_print_format_struct (p, seek+i, buf+i, len-i, fmtname, slide, mode, setval, nxtfield); if ((MUSTSEE || MUSTSEEJSON) && size != 0 && elem == -1) { p->cb_printf (","); if (MUSTSEE) p->cb_printf ("\n"); } if (elem > -1) elem--; i+= (isptr) ? 4 : s; } if (mode & R_PRINT_ISFIELD) if (!SEEVALUE) p->cb_printf ("]"); if (MUSTSEEJSON) p->cb_printf ("]}]}"); } oldslide = slide; slide -= (isptr) ? STRUCTPTR : NESTEDSTRUCT; if (mode & R_PRINT_SEEFLAGS) { oldslide = slide; slide-=STRUCTFLAG; } break; } default: /* ignore unknown chars */ invalid = 1; break; } //switch } else { eprintf ("Likely a heap buffer overflow in %s at %d\n", __FILE__, __LINE__); goto beach; } if (mode & R_PRINT_DOT) { p->cb_printf ("}"); } if (viewflags && p->offname) { const char *s = p->offname (p->user, seeki); if (s) p->cb_printf ("@(%s)", s); s = p->offname (p->user, addr); if (s) p->cb_printf ("*(%s)", s); } if (tmp != 'D' && !invalid && fmtname==NULL && MUSTSEE) p->cb_printf ("\n"); last = tmp; } if (otimes>1) { if (MUSTSEEJSON) p->cb_printf ("]"); else p->cb_printf ("}\n"); } arg = orig; oldslide = 0; } if (mode & R_PRINT_JSON && slide==0) p->cb_printf("]\n"); if (mode & R_PRINT_DOT) { p->cb_printf ("\"];\n}\n"); // TODO: show nested structs and field reference lines } beach: free (oarg); free (buf); free (field); free (args); return i; }
R_API int r_print_format(RPrint *p, ut64 seek, const ut8* b, const int len, const char *fmt, int mode, const char *setval, char *ofield) { int nargs, i, j, invalid, nexti, idx, times, otimes, endian, isptr = 0; const char *argend; ut64 addr = 0, addr64 = 0, seeki = 0;; char *args = NULL, *bracket, tmp, last = 0; const char *arg = fmt; int viewflags = 0; char namefmt[8], *field = NULL; static int slide=0, oldslide=0; ut8 *buf; if (!fmt) return 0; argend = fmt+strlen (fmt); nexti = nargs = i = j = 0; if (len < 1) return 0; buf = malloc (len); if (!buf) return 0; memcpy (buf, b, len); endian = p->big_endian; if (ofield && ofield != MINUSONE) field = strdup (ofield); while (*arg && iswhitechar (*arg)) arg++; /* get times */ otimes = times = atoi (arg); if (times > 0) while ((*arg>='0'&&*arg<='9')) arg++; bracket = strchr (arg,'{'); if (bracket) { char *end = strchr (arg, '}'); if (end == NULL) { eprintf ("No end bracket. Try pm {ecx}b @ esi\n"); goto beach; } *end='\0'; times = r_num_math (NULL, bracket+1); arg = end + 1; } if (*arg=='\0') { goto beach; } /* get args */ args = strchr (arg, ' '); if (args) { int l=0, maxl = 0; argend = args; args = strdup (args+1); nargs = r_str_word_set0 (args); if (nargs == 0) R_FREE (args); for (i=0; i<nargs; i++) { const int len = strlen (r_str_word_get0 (args, i)); if (len > maxl) maxl = len; } l++; snprintf (namefmt, sizeof (namefmt), "%%%ds : ", maxl+6*slide%STRUCTPTR); } #define ISPOINTED ((slide%STRUCTFLAG)/STRUCTPTR<=(oldslide%STRUCTFLAG)/STRUCTPTR) #define ISNESTED ((slide%STRUCTPTR)<=(oldslide%STRUCTPTR)) if (mode == R_PRINT_JSON && slide==0) p->printf("["); if (arg[0] == '0') { mode |= R_PRINT_UNIONMODE; arg++; } else { mode &= ~R_PRINT_UNIONMODE; } /* go format */ i = 0; if (!times) otimes = times = 1; for (; times; times--) { // repeat N times const char * orig = arg; int first = 1; if (otimes>1) { if (mode & R_PRINT_JSON) { if (otimes > times) p->printf (","); p->printf ("[{\"index\":%d,\"offset\":%d},", otimes-times, seek+i); } else p->printf ("0x%08"PFMT64x" [%d] {\n", seek+i, otimes-times); } arg = orig; for (idx=0; i<len && arg<argend && *arg; arg++) { int size, elem; /* size of the array, element of the array */ char *fieldname = NULL, *fmtname = NULL, *oarg = NULL; if (mode & R_PRINT_UNIONMODE) { i = 0; } seeki = seek+i; addr = 0LL; invalid = 0; if (arg[0] == '[') { char *end = strchr (arg,']'); if (end == NULL) { eprintf ("No end bracket.\n"); goto beach; } *end = '\0'; size = r_num_math (NULL, arg+1); arg = end + 1; *end = ']'; } else { size = -1; } updateAddr (buf, i, endian, &addr, &addr64); tmp = *arg; if (args == NULL) mode |= R_PRINT_ISFIELD; if (mode & R_PRINT_MUSTSEE && otimes>1) p->printf (" "); if (idx<nargs && tmp != 'e' && isptr == 0) { char *dot = NULL, *bracket = NULL; if (field) dot = strchr (field, '.'); if (dot) *dot = '\0'; oarg = fieldname = strdup(r_str_word_get0 (args, idx)); if (ISSTRUCT || tmp=='E' || tmp=='B') { if (*fieldname == '(') { fmtname = fieldname+1; fieldname = strchr (fieldname, ')'); if (fieldname) *fieldname++ = '\0'; else { eprintf ("Missing closing parenthesis in format ')'\n"); free (oarg); goto beach; } } else { eprintf ("Missing name (%s)\n", fieldname); free(oarg); goto beach; } } if (args == NULL || (field==NULL && ofield != MINUSONE) || (field && !strncmp(field, fieldname, strlen(fieldname)))) { mode |= R_PRINT_ISFIELD; } else { mode &= ~R_PRINT_ISFIELD; } /* There we handle specific element in array */ if (field != NULL && (bracket = strchr (field, '[')) != NULL && mode & R_PRINT_ISFIELD) { char *end = strchr (field, ']'); if (end == NULL) { eprintf ("Missing closing bracket\n"); goto beach; } *end = '\0'; elem = r_num_math (NULL, bracket+1)+1; // +1 to handle 0 index easily for ( ; bracket < end; bracket++) *bracket = '\0'; size += elem*ARRAYINDEX_COEF; } else { elem = -1; } idx++; if (MUSTSEE) { p->printf (namefmt, fieldname); } } feed_me_again: switch (isptr) { case 1: { nexti = i + (p->bits/8); i = 0; if(tmp == '?' )seeki = addr; memset (buf, '\0', len); if (MUSTSEE) p->printf ("(*0x%"PFMT64x") ", addr); if (addr == 0) isptr = NULLPTR; else isptr = PTRBACK; if (/*addr<(b+len) && addr>=b && */p->iob.read_at) { /* The test was here to avoid segfault in the next line, but len make it doesnt work... */ p->iob.read_at (p->iob.io, (ut64)addr, buf, len-4); updateAddr (buf, i, endian, &addr, &addr64); } else { eprintf ("(SEGFAULT: cannot read memory at 0x%08"PFMT64x", Block: %s, blocksize: 0x%x)\n", addr, b, len); p->printf("\n"); free (oarg); goto beach; } } break; case 2: // restore state after pointer seek i = nexti; seeki = seek+i; memcpy (buf, b, len); isptr = NOPTR; arg--; continue; } if (tmp == 0 && last != '*') break; /* skip chars */ switch (tmp) { case '*': // next char is a pointer isptr = PTRSEEK; arg++; tmp = *arg; //last; goto feed_me_again; case '+': // toggle view flags viewflags = !viewflags; continue; case 'e': // tmp swap endian endian ^= 1; continue; case ':': // skip 4 bytes if (size == -1) i+=4; else while (size--) i+=4; continue; case '.': // skip 1 byte if (size == -1) i++; else i+=size; continue; case 'p': // pointer reference tmp = (p->bits == 64)? 'q': 'x'; break; } /* flags */ if (mode & R_PRINT_SEEFLAGS && isptr != NULLPTR) { if (tmp == '?') { p->printf ("f %s.%s_", fmtname, fieldname); } else if (tmp == 'E') { p->printf ("f %s=0x%08"PFMT64x"\n", fieldname, seeki); } else if (slide/STRUCTFLAG>0 && idx==1) { p->printf ("%s=0x%08"PFMT64x"\n", fieldname, seeki); } else p->printf ("f %s=0x%08"PFMT64x"\n", fieldname , seeki); } /* json */ if (mode & R_PRINT_JSON) { if (oldslide<=slide) { if (!first) p->printf (","); else first = 0; } else if(oldslide!=0) { p->printf ("]},"); } p->printf ("{\"name\":\"%s\",\"type\":\"", fieldname); if (ISSTRUCT) { p->printf ("%s", fmtname); } else { p->printf ("%c", tmp); } if (isptr) p->printf ("*"); p->printf ("\",\"offset\":%d,\"value\":",(isptr)?(seek+nexti-(p->bits/8)):seek+i); } if (isptr == NULLPTR) { if (MUSTSEEJSON) p->printf ("\"NULL\"}", tmp, seek+i); else if (MUSTSEE) p->printf ("NULL\n"); isptr = PTRBACK; } else /* format chars */ switch (tmp) { case 't': r_print_format_time(p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 4 : 4*size; break; case 'q': r_print_format_quadword(p, endian, mode, setval, seeki, buf, i, size); i += (size==-1) ? 8 : 8*size; break; case 'b': r_print_format_byte(p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 1 : size; break; case 'c': r_print_format_char (p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 1 : size; break; case 'X': size = r_print_format_hexpairs (p, endian, mode, setval, seeki, buf, size); i += size; break; case 'T': if(r_print_format_10bytes(p, mode, setval, seeki, addr, buf) == 0) i += (size==-1) ? 4 : 4*size; break; case 'f': r_print_format_float(p, endian, mode, setval, seeki, buf, i, size); i += (size==-1) ? 4 : 4*size; break; case 'i': case 'd': r_print_format_hex(p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 4 : 4*size; break; case 'D': if (size>0) p->printf ("Size not yet implemented\n"); if (p->disasm && p->user) i += p->disasm (p->user, seeki); break; case 'o': r_print_format_octal (p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 4 : 4*size; break; case 'x': r_print_format_hexflag(p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 4 : 4*size; break; case 'w': r_print_format_word(p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 2 : 2*size; break; case 'z': // zero terminated string r_print_format_nulltermstring (p, len, endian, mode, setval, seeki, buf, i, size); if (size == -1) i+=strlen((char*)buf+i)+1; else while (size--) i++; break; case 'Z': // zero terminated wide string r_print_format_nulltermwidestring (p, len, endian, mode, setval, seeki, buf, i, size); if (size == -1) i+=r_wstr_clen((char*)(buf+seeki))*2+2; else while (size--) i+=2; break; case 's': if (r_print_format_string (p, seeki, addr64, addr, 0, mode) == 0) i += (size==-1) ? 4 : 4*size; break; case 'S': if (r_print_format_string (p, seeki, addr64, addr, 1, mode) == 0) i += (size==-1) ? 8 : 8*size; break; case 'B': // resolve bitfield if (size >= ARRAYINDEX_COEF) size %= ARRAYINDEX_COEF; r_print_format_bitfield (p, seeki, fmtname, fieldname, addr, mode, size); i+=(size==-1)?1:size; break; case 'E': // resolve enum if (size >= ARRAYINDEX_COEF) size %= ARRAYINDEX_COEF; r_print_format_enum (p, seeki, fmtname, fieldname, addr, mode, size); i+=(size==-1)?1:size; break; case '?': { int s = 0; char *nxtfield = NULL; if (size >= ARRAYINDEX_COEF) { elem = size/ARRAYINDEX_COEF-1; size %= ARRAYINDEX_COEF; } if (!(mode & R_PRINT_ISFIELD)) nxtfield = MINUSONE; else if (field) nxtfield = strchr (ofield, '.'); if (nxtfield != MINUSONE && nxtfield != NULL) nxtfield++; if (MUSTSEE) p->printf ("\n"); if (MUSTSEEJSON) { if (isptr) p->printf ("%d},", seeki); else p->printf ("["); } if (mode & R_PRINT_SEEFLAGS) slide+=STRUCTFLAG; oldslide = slide; slide += (isptr) ? STRUCTPTR : NESTEDSTRUCT; if (size == -1) { s = r_print_format_struct (p, seeki, buf+i, len-i, fmtname, slide, mode, setval, nxtfield); i+= (isptr) ? 4 : s; } else { p->printf ("[\n"); while (size--) { if (elem == -1 || elem == 0) { mode |= R_PRINT_MUSTSEE; if (elem == 0) elem = -2; } else { mode &= ~R_PRINT_MUSTSEE; } s = r_print_format_struct (p, seek+i, buf+i, len-i, fmtname, slide, mode, setval, nxtfield); if (size != 0 && elem == -1) p->printf (",\n"); if (elem > -1) elem--; i+= (isptr) ? 4 : s; } if (MUSTSEEJSON) p->printf ("]]}"); else p->printf ("]"); } oldslide = slide; slide -= (isptr) ? STRUCTPTR : NESTEDSTRUCT; if (mode & R_PRINT_SEEFLAGS) { oldslide = slide; slide-=STRUCTFLAG; } break; } default: /* ignore unknown chars */ invalid = 1; break; } if (viewflags && p->offname) { const char *s = p->offname (p->user, seeki); if (s) p->printf ("@(%s)", s); s = p->offname (p->user, addr); if (s) p->printf ("*(%s)", s); } if (tmp != 'D' && !invalid && fmtname==NULL && MUSTSEE) p->printf ("\n"); last = tmp; if (oarg) free (oarg); } if (otimes>1) { if (MUSTSEEJSON) p->printf ("]"); else p->printf ("}\n"); } arg = orig; oldslide = 0; } if (mode & R_PRINT_JSON && slide==0) p->printf("]"); beach: free (buf); free (field); if (args) free (args); return i; }
R_API int r_print_format(RPrint *p, ut64 seek, const ut8* b, const int len, const char *fmt, int elem, const char *setval) { int nargs, i, j, invalid, nexti, idx, times, otimes, endian, isptr = 0; int (*oldprintf)(const char *str, ...); const char *argend = fmt+strlen (fmt); ut64 addr = 0, addr64 = 0, seeki = 0;; char *args = NULL, *bracket, tmp, last = 0; const char *arg = fmt; int viewflags = 0, flag = (elem==SEEFLAG)?1:0; char namefmt[8]; static int slide=0; ut8 *buf; nexti = nargs = i = j = 0; if (len < 1) return 0; buf = malloc (len); if (!buf) return 0; memcpy (buf, b, len); endian = p->big_endian; oldprintf = NULL; realprintf = p->printf; while (*arg && iswhitechar (*arg)) arg++; /* get times */ otimes = times = atoi (arg); if (times > 0) while ((*arg>='0'&&*arg<='9')) arg++; bracket = strchr (arg,'{'); if (bracket) { char *end = strchr (arg, '}'); if (end == NULL) { eprintf ("No end bracket. Try pm {ecx}b @ esi\n"); goto beach; } *end='\0'; times = r_num_math (NULL, bracket+1); arg = end + 1; } if (*arg=='\0' || *arg=='?') { print_format_help (p); goto beach; } /* get args */ args = strchr (arg, ' '); if (args) { int l=0, maxl = 0; argend = args; args = strdup (args+1); nargs = r_str_word_set0 (args); if (nargs == 0) R_FREE (args); for (i=0; i<nargs; i++) { const int len = strlen (r_str_word_get0 (args, i)); if (len > maxl) maxl = len; } l++; snprintf (namefmt, sizeof (namefmt), "%%%ds : ", maxl+6*slide%STRUCTPTR); } /* go format */ i = 0; if (!times) otimes = times = 1; for (; times; times--) { // repeat N times const char * orig = arg; if (otimes>1) p->printf ("0x%08"PFMT64x" [%d] {\n", seek+i, otimes-times); arg = orig; for (idx=0; i<len && arg<argend && *arg; arg++) { int size; char *name = NULL; seeki = seek+i; addr = 0LL; invalid = 0; if (arg[0] == '[') { char *end = strchr (arg,']'); if (end == NULL) { eprintf ("No end bracket.\n"); goto beach; } *end = '\0'; size = r_num_math (NULL, arg+1); arg = end + 1; *end = ']'; } else { size = -1; } updateAddr (buf, i, endian, &addr, &addr64); tmp = *arg; if (otimes>1) p->printf (" "); #define MUSTSET (setval && elem == idx) #define MUSTSEE (elem == -1 || elem == idx) if (MUSTSEE && !flag) { if (!(MUSTSET)) { if (oldprintf) p->printf = oldprintf; if (idx<nargs && tmp != 'e' && isptr == 0) { p->printf (namefmt, r_str_word_get0 (args, idx)); idx++; } } } else { if (!oldprintf) oldprintf = p->printf; p->printf = nullprintf; } feed_me_again: switch (isptr) { case 1: { nexti = i + (p->bits/8); i = 0; if(tmp == '?' )seeki = addr; memset (buf, '\0', len); p->printf ("(*0x%"PFMT64x") ", addr); if (addr == 0) isptr = NULLPTR; else isptr = PTRBACK; if (/*addr<(b+len) && addr>=b && */p->iob.read_at) { /* The test was here to avoid segfault in the next line, but len make it doesnt work... */ p->iob.read_at (p->iob.io, (ut64)addr, buf, len-4); updateAddr (buf, i, endian, &addr, &addr64); } else { eprintf ("(SEGFAULT: cannot read memory at 0x%08"PFMT64x", Block: %s, blocksize: 0x%x)\n", addr, b, len); p->printf("\n"); goto beach; } } break; case 2: // restore state after pointer seek i = nexti; seeki = seek+i; memcpy (buf, b, len); isptr = NOPTR; arg--; continue; } if (tmp == 0 && last != '*') break; /* skip chars */ switch (tmp) { case '*': // next char is a pointer isptr = PTRSEEK; arg++; tmp = *arg; //last; goto feed_me_again; case '+': // toggle view flags viewflags = !viewflags; continue; case 'e': // tmp swap endian endian ^= 1; continue; case ':': // skip 4 bytes if (size == -1) i+=4; else while (size--) i+=4; continue; case '.': // skip 1 byte if (size == -1) i++; else while (size--) i++; continue; case 'p': // pointer reference tmp = (p->bits == 64)? 'q': 'x'; //tmp = (sizeof (void*)==8)? 'q': 'x'; break; } if (flag && isptr != NULLPTR) { if (tmp == '?') { char *n = strdup (r_str_word_get0 (args, idx)+1); char *par = strchr (n, ')'); if (par == NULL) { eprintf ("No end parenthesis for struct name"); free (n); goto beach; } else { *par = '.'; } realprintf ("f %s_", n); free(n); } else if (slide>0 && idx==0) { realprintf ("%s=0x%08"PFMT64x"\n", r_str_word_get0 (args, idx), seeki); } else realprintf ("f %s=0x%08"PFMT64x"\n", r_str_word_get0 (args, idx) , seeki); idx++; } if (isptr == NULLPTR) { p->printf ("NULL"); isptr = PTRBACK; } else /* cmt chars */ switch (tmp) { #if 0 case 't': /* unix timestamp */ D cons_printf("0x%08x = ", config.seek+i); { /* dirty hack */ int oldfmt = last_print_format; ut64 old = config.seek; radare_seek(config.seek+i, SEEK_SET); radare_read(0); print_data(config.seek+i, "8", buf+i, 4, FMT_TIME_UNIX); last_print_format=oldfmt; radare_seek(old, SEEK_SET); } break; #endif case 'e': //WTF is this? 'e' is supposed to swap endians?! if (size > 0) p->printf ("Size not yet implemented\n"); if (MUSTSET) { realprintf ("?e pf e not yet supported\n"); } else { double doub; memcpy (&doub, buf+i, sizeof (double)); p->printf ("0x%08"PFMT64x" = (double) ", seeki); p->printf ("%e", doub); i += 8; } break; case 'q': r_print_format_quadword(p, endian, MUSTSET, setval, seeki, buf, i, size); i += (size==-1) ? 8 : 8*size; break; case 'b': r_print_format_byte(p, endian, MUSTSET, setval, seeki, buf, i, size); i+= (size==-1) ? 1 : size; break; case 'c': r_print_format_char (p, endian, MUSTSET, setval, seeki, buf, i, size); i+= (size==-1) ? 1 : size; break; case 'X': size = r_print_format_hexpairs (p, endian, MUSTSET, setval, seeki, buf, size); i += size; break; case 'T': if(r_print_format_10bytes(p, MUSTSET, setval, seeki, addr, buf) == 0) i += (size==-1) ? 4 : 4*size; break; case 'f': r_print_format_float(p, endian, MUSTSET, setval, seeki, buf, i, size); i += (size==-1) ? 4 : 4*size; break; case 'i': case 'd': r_print_format_hex(p, endian, MUSTSET, setval, seeki, buf, i, size); i+= (size==-1) ? 4 : 4*size; break; case 'D': if (size>0) p->printf ("Size not yet implemented\n"); if (p->disasm && p->user) i += p->disasm (p->user, seeki); break; case 'o': r_print_format_octal (p, endian, MUSTSET, setval, seeki, buf, i, size); i+= (size==-1) ? 4 : 4*size; break; case 'x': r_print_format_hexflag(p, endian, MUSTSET, setval, seeki, buf, i, size); i+= (size==-1) ? 4 : 4*size; break; case 'w': case '1': // word (16 bits) r_print_format_word(p, endian, MUSTSET, setval, seeki, buf, i, size); i+= (size==-1) ? 2 : 2*size; break; case 'z': // zero terminated string if (MUSTSET) { int buflen = strlen ((const char *)buf); if (buflen>seeki) { buflen = strlen ((const char *)buf+seeki); } if (strlen (setval) > buflen) { eprintf ("Warning: new string is longer than previous one \n"); } realprintf ("w %s @ 0x%08"PFMT64x"\n", setval, seeki); } else { p->printf ("0x%08"PFMT64x" = ", seeki); for (; ((size || size==-1) && buf[i]) && i<len; i++) { if (IS_PRINTABLE (buf[i])) p->printf ("%c", buf[i]); else p->printf ("."); size -= (size==-1) ? 0 : 1; } } if (size == -1) i++; else while (size--) i++; break; case 'Z': // zero terminated wide string if (MUSTSET) { if ((size = strlen(setval)) > r_wstr_clen((char*)(buf+seeki))) eprintf ("Warning: new string is longer than previous one\n"); realprintf ("ww %s @ 0x%08"PFMT64x"\n", setval, seeki); } else { p->printf ("0x%08"PFMT64x" = ", seeki); for (; ((size || size==-1) && buf[i]) && i<len; i+=2) { if (IS_PRINTABLE (buf[i])) p->printf ("%c", buf[i]); else p->printf ("."); size -= (size==-1) ? 0 : 1; } } if (size == -1) i+=2; else while (size--) i+=2; break; case 's': if (r_print_format_ptrstring (p, seeki, addr64, addr, 0) == 0) i += (size==-1) ? 4 : 4*size; break; case 'S': if (r_print_format_ptrstring (p, seeki, addr64, addr, 1) == 0) i += (size==-1) ? 8 : 8*size; break; case 'B': // resolve bitfield { char *structname, *osn; char *bitfield = NULL; structname = osn = strdup (r_str_word_get0 (args, idx-1)); switch (size) { case 1: addr &= UT8_MAX; break; case 2: addr &= UT16_MAX; break; case 4: addr &= UT32_MAX; break; } if (*structname == '(') { name = strchr (structname, ')'); } else { eprintf ("Bitfield name missing (%s)\n", structname); free (structname); goto beach; } structname++; if (name) *(name++) = '\0'; else eprintf ("No ')'\n"); if (p->get_bitfield) bitfield = p->get_bitfield (p->user, structname, addr); if (bitfield && *bitfield) { p->printf (" %s (bitfield) = %s\n", name, bitfield); } else { p->printf (" %s (bitfield) = `tb %s 0x%x`\n", name, structname, addr); } i+= 4; //(isptr) ? 4 : s; free (osn); free (bitfield); } break; case 'E': // resolve enum { char *enumname, *osn; char *enumvalue = NULL; enumname = osn = strdup (r_str_word_get0 (args, idx-1)); switch (size) { case 1: addr &= UT8_MAX; break; case 2: addr &= UT16_MAX; break; case 4: addr &= UT32_MAX; break; } if (*enumname == '(') { name = strchr (enumname, ')'); } else { eprintf ("Enum name missing (%s)\n", enumname); free (enumname); goto beach; } enumname++; if (name) *(name++) = '\0'; else eprintf ("No ')'\n"); if (p->get_enumname) enumvalue = p->get_enumname (p->user, enumname, addr); if (enumvalue && *enumvalue) { p->printf (" %s (enum) = 0x%"PFMT64x" ; %s\n", name, addr, enumvalue); } else { p->printf (" %s (enum) = `te %s 0x%x`\n", name, enumname, addr); } i+= (size==-1) ? 1 : size; free (osn); free (enumvalue); } break; case '?': { int s; char *structname, *osn; structname = osn = strdup (r_str_word_get0 (args, idx-1)); if (*structname == '(') { name = strchr (structname, ')'); } else { eprintf ("Struct name missing (%s)\n", structname); free (structname); goto beach; } structname++; if (name) *(name++) = '\0'; else eprintf ("No ')'\n"); p->printf ("<struct>\n"); if (flag) slide+=STRUCTFLAG; slide += (isptr) ? STRUCTPTR : NESTEDSTRUCT; s = r_print_format_struct (p, seeki, buf+i, len, structname--, slide); i+= (isptr) ? 4 : s; slide -= (isptr) ? STRUCTPTR : NESTEDSTRUCT; if (flag) slide-=STRUCTFLAG; free (osn); break; } default: /* ignore unknown chars */ invalid = 1; break; } if (!flag && (!MUSTSEE || MUSTSET)) idx++; if (viewflags && p->offname) { const char *s = p->offname (p->user, seeki); if (s) p->printf ("@(%s)", s); s = p->offname (p->user, addr); if (s) p->printf ("*(%s)", s); } if (tmp != 'D' && !invalid && name==NULL) p->printf ("\n"); last = tmp; } if (otimes>1) p->printf ("}\n"); arg = orig; } if (oldprintf) p->printf = oldprintf; beach: free (buf); if (args) free (args); return i; }
R_API int r_core_rtr_http(RCore *core, int launch, const char *path) { char buf[32]; RSocketHTTPRequest *rs; int iport, oldsandbox = -1; int timeout = r_config_get_i (core->config, "http.timeout"); int x = r_config_get_i (core->config, "scr.html"); int y = r_config_get_i (core->config, "scr.color"); int z = r_config_get_i (core->config, "asm.bytes"); int u = r_config_get_i (core->config, "scr.interactive"); int v = r_config_get_i (core->config, "asm.cmtright"); const char *port = r_config_get (core->config, "http.port"); char *allow = (char *)r_config_get (core->config, "http.allow"); if (core->http_up) { eprintf ("http server is already running\n"); return 1; } if (r_sandbox_enable (0)) { eprintf ("sandbox: connect disabled\n"); return 1; } if (path && atoi (path)) { port = path; path = NULL; } if (!strcmp (port, "0")) { r_num_irand (); iport = 1024+r_num_rand (45256); snprintf (buf, sizeof (buf), "%d", iport); port = buf; } s = r_socket_new (R_FALSE); s->local = !r_config_get_i (core->config, "http.public"); if (!r_socket_listen (s, port, NULL)) { eprintf ("Cannot listen on http.port\n"); return 1; } if (launch) { char cmd[128]; const char *browser = r_config_get (core->config, "http.browser"); snprintf (cmd, sizeof (cmd)-1, "%s http://localhost:%d/%s &", browser, atoi (port), path?path:""); r_sys_cmd (cmd); } r_config_set (core->config, "asm.cmtright", "false"); r_config_set (core->config, "scr.html", "true"); r_config_set (core->config, "scr.color", "false"); r_config_set (core->config, "asm.bytes", "false"); r_config_set (core->config, "scr.interactive", "false"); if (r_config_get_i (core->config, "http.sandbox")) { oldsandbox = r_config_get_i (core->config, "cfg.sandbox"); r_config_set (core->config, "cfg.sandbox", "true"); } eprintf ("Starting http server...\n"); eprintf ("http://localhost:%d/\n", atoi (port)); core->http_up = R_TRUE; while (!r_cons_singleton ()->breaked) { r_cons_break ((RConsBreak)http_break, core); rs = r_socket_http_accept (s, timeout); if (!rs) { if (!s) break; r_sys_usleep (100); continue; } if (allow && *allow) { int accepted = R_FALSE; const char *host; char *p, *peer = r_socket_to_string (rs->s); char *allows = strdup (allow); //eprintf ("Firewall (%s)\n", allows); int i, count = r_str_split (allows, ','); p = strchr (peer, ':'); if (p) *p = 0; for (i=0; i<count; i++) { host = r_str_word_get0 (allows, i); //eprintf ("--- (%s) (%s)\n", host, peer); if (!strcmp (host, peer)) { accepted = R_TRUE; break; } } free (peer); free (allows); if (!accepted) { r_socket_http_close (rs); continue; } } if (!rs->method || !rs->path) { eprintf ("Invalid http headers received from client\n"); r_socket_http_close (rs); continue; } char *dir = NULL; if (r_config_get_i (core->config, "http.dirlist")) if (r_file_is_directory (rs->path)) dir = strdup (rs->path); if (!strcmp (rs->method, "GET")) { if (!memcmp (rs->path, "/up", 3)) { if (r_config_get_i (core->config, "http.upget")) { const char *uproot = r_config_get (core->config, "http.uproot"); if (!rs->path[3] || (rs->path[3]=='/'&&!rs->path[4])) { char *ptr = rtr_dir_files (uproot); r_socket_http_response (rs, 200, ptr, 0, NULL); free (ptr); } else { char *path = r_file_root (uproot, rs->path + 4); if (r_file_exists (path)) { int sz = 0; char *f = r_file_slurp (path, &sz); if (f) { r_socket_http_response (rs, 200, f, sz, NULL); free (f); } else { r_socket_http_response (rs, 403, "Permission denied", 0, NULL); eprintf ("http: Cannot open '%s'\n", path); } } else { if (dir) { char *resp = rtr_dir_files (dir); r_socket_http_response (rs, 404, resp, 0, NULL); free (resp); } else { eprintf ("File '%s' not found\n", path); r_socket_http_response (rs, 404, "File not found\n", 0, NULL); } } free (path); } } else { r_socket_http_response (rs, 403, "Permission denied\n", 0, NULL); } } else if (!memcmp (rs->path, "/cmd/", 5)) { char *cmd = rs->path +5; char foo[32]; const char *httpcmd = r_config_get (core->config, "http.uri"); while (*cmd=='/') cmd++; if (httpcmd && *httpcmd) { int len; char *res; // do remote http query and proxy response snprintf (foo, sizeof (foo), "%s/%s", httpcmd, cmd); res = r_socket_http_get (foo, NULL, &len); if (res) { res[len]=0; r_cons_printf ("%s\n", res); } } else { char *out, *cmd = rs->path+5; r_str_uri_decode (cmd); // eprintf ("CMD (%s)\n", cmd); out = r_core_cmd_str_pipe (core, cmd); // eprintf ("\nOUT LEN = %d\n", strlen (out)); if (out) { char *res = r_str_uri_encode (out); r_socket_http_response (rs, 200, out, 0, "Content-Type: text/plain\n"); free (out); free (res); } else r_socket_http_response (rs, 200, "", 0, NULL); } } else { const char *root = r_config_get (core->config, "http.root"); char *path = r_file_root (root, rs->path); // FD IS OK HERE if (rs->path [strlen (rs->path)-1] == '/') { path = r_str_concat (path, "index.html"); //rs->path = r_str_concat (rs->path, "index.html"); } else { //snprintf (path, sizeof (path), "%s/%s", root, rs->path); if (r_file_is_directory (path)) { char res[128]; snprintf (res, sizeof (res), "Location: %s/\n", rs->path); r_socket_http_response (rs, 302, NULL, 0, res); r_socket_http_close (rs); free (path); free (dir); dir = NULL; continue; } } if (r_file_exists (path)) { int sz = 0; char *f = r_file_slurp (path, &sz); if (f) { const char *contenttype = NULL; if (strstr (path, ".js")) contenttype = "Content-Type: application/javascript\n"; if (strstr (path, ".css")) contenttype = "Content-Type: text/css\n"; if (strstr (path, ".html")) contenttype = "Content-Type: text/html\n"; r_socket_http_response (rs, 200, f, sz, contenttype); free (f); } else { r_socket_http_response (rs, 403, "Permission denied", 0, NULL); eprintf ("http: Cannot open '%s'\n", path); } } else { if (dir) { char *resp = rtr_dir_files (dir); eprintf ("Dirlisting %s\n", dir); r_socket_http_response (rs, 404, resp, 0, NULL); free (resp); } else { eprintf ("File '%s' not found\n", path); r_socket_http_response (rs, 404, "File not found\n", 0, NULL); } } free (path); } } else if (!strcmp (rs->method, "POST")) { ut8 *ret; int retlen; char buf[128]; if (r_config_get_i (core->config, "http.upload")) { ret = r_socket_http_handle_upload ( rs->data, rs->data_length, &retlen); if (ret) { ut64 size = r_config_get_i (core->config, "http.maxsize"); if (size && retlen > size) { r_socket_http_response (rs, 403, "403 File too big\n", 0, NULL); } else { char *filename = r_file_root ( r_config_get (core->config, "http.uproot"), rs->path + 4); eprintf ("UPLOADED '%s'\n", filename); r_file_dump (filename, ret, retlen); free (filename); snprintf (buf, sizeof (buf), "<html><body><h2>uploaded %d bytes. Thanks</h2>\n", retlen); r_socket_http_response (rs, 200, buf, 0, NULL); } free (ret); } } else { r_socket_http_response (rs, 403, "403 Forbidden\n", 0, NULL); } } else { r_socket_http_response (rs, 404, "Invalid protocol", 0, NULL); } r_socket_http_close (rs); free (dir); } core->http_up = R_FALSE; r_socket_free (s); r_cons_break_end (); r_config_set_i (core->config, "scr.html", x); r_config_set_i (core->config, "scr.color", y); r_config_set_i (core->config, "asm.bytes", z); r_config_set_i (core->config, "scr.interactive", u); r_config_set_i (core->config, "asm.cmtright", v); if (oldsandbox != -1) r_config_set_i (core->config, "cfg.sandbox", oldsandbox); return 0; }
// XXX: this is very incomplete. must be updated to handle all format chars int r_print_format_struct_size(const char *f, RPrint *p, int mode) { char *o = strdup(f); char *end = strchr (o, ' '), *args, *fmt = o; int size = 0, tabsize=0, i, idx=0, biggest = 0; if (!end && !(end = strchr (o, '\0'))) return -1; if (*end) { *end = 0; args = strdup (end+1); } else { args = strdup (""); } if (fmt[0] == '0') { mode |= R_PRINT_UNIONMODE; fmt++; } else { mode &= ~R_PRINT_UNIONMODE; } r_str_word_set0 (args); for (i=0; i<strlen (fmt); i++) { if (fmt[i] == '[') { char *end = strchr (fmt+i,']'); if (end == NULL) { eprintf ("No end bracket.\n"); continue; } *end = '\0'; tabsize = r_num_math (NULL, fmt+i+1); *end = ']'; while (fmt[i++]!=']'); } else { tabsize = 1; } switch (fmt[i]) { case 'c': case 'b': case '.': size+=tabsize*1; break; case 'w': size += tabsize*2; break; case 'd': case 'o': case 'i': case 'x': case 'f': case 's': case 't': case ':': size += tabsize*4; break; case 'S': case 'q': size += tabsize*8; break; case 'z': case 'Z': size += tabsize; break; case '*': size += tabsize*4; i++; break; case 'B': case 'E': switch (tabsize) { case 1: size+=1; break; case 2: size+=2; break; case 4: size+=4; break; default: break; } break; case '?': { const char *format = NULL; char *endname = NULL, *structname = NULL; structname = strdup(r_str_word_get0 (args, idx)); if (*structname == '(') { endname = strchr (structname, ')'); } else { eprintf ("Struct name missing (%s)\n", structname); free(structname); break; } if (endname) *endname = '\0'; format = r_strht_get (p->formats, structname+1); free (structname); size += tabsize * r_print_format_struct_size (format, p, mode); } break; // TODO continue list default: break; } idx++; if (mode & R_PRINT_UNIONMODE) { if (size > biggest) biggest = size; size = 0; } } free (o); free (args); if (mode & R_PRINT_UNIONMODE) return biggest; else return size; }
/* TODO: needs refactoring */ R_API int r_print_format(RPrint *p, ut64 seek, const ut8* b, int len, const char *fmt, int elem, const char *setval) { int nargs, i, j, nexti, idx, times, otimes, endian, isptr = 0; int (*realprintf)(const char *str, ...); int (*oldprintf)(const char *str, ...); const char *argend = fmt+strlen (fmt); ut64 addr = 0, addr64 = 0, seeki = 0;; char *args = NULL, *bracket, tmp, last = 0; const char *arg = fmt; int viewflags = 0; char namefmt[8]; ut8 *buf, buffer[256]; nexti = nargs = endian = i = j = 0; if (len<1) return 0; buf = malloc (len); if (!buf) return 0; memcpy (buf, b, len); endian = p->big_endian; oldprintf = NULL; realprintf = p->printf; while (*arg && iswhitechar (*arg)) arg++; /* get times */ otimes = times = atoi (arg); if (times > 0) while ((*arg>='0'&&*arg<='9')) arg++; bracket = strchr (arg,'{'); if (bracket) { char *end = strchr (arg,'}'); if (end == NULL) { eprintf ("No end bracket. Try pm {ecx}b @ esi\n"); goto beach; } *end='\0'; times = r_num_math (NULL, bracket+1); arg = end + 1; } if (*arg=='\0') { print_format_help (p); goto beach; } /* get args */ args = strchr (arg, ' '); if (args) { int l=0, maxl = 0; argend = args; args = strdup (args+1); nargs = r_str_word_set0 (args+1); if (nargs == 0) R_FREE (args); for (i=0; i<nargs; i++) { int len = strlen (r_str_word_get0 (args+1, i)); if (len>maxl) maxl = len; } l++; snprintf (namefmt, sizeof (namefmt), "%%%ds : ", maxl); } /* go format */ i = 0; if (!times) otimes = times = 1; for (; times; times--) { // repeat N times const char * orig = arg; if (otimes>1) p->printf ("0x%08"PFMT64x" [%d] {\n", seek+i, otimes-times); idx = 0; arg = orig; for (idx=0; i<len && arg<argend && *arg; idx++, arg++) { seeki = seek+i; addr = 0LL; if (endian) addr = (*(buf+i))<<24 | (*(buf+i+1))<<16 | *(buf+i+2)<<8 | *(buf+i+3); else addr = (*(buf+i+3))<<24 | (*(buf+i+2))<<16 | *(buf+i+1)<<8 | *(buf+i); if (endian) addr64 = (ut64)(*(buf+i))<<56 | (ut64)(*(buf+i+1))<<48 | (ut64)*(buf+i+2)<<40 | (ut64)(*(buf+i+3))<<32 | (*(buf+i+4))<<24 | (*(buf+i+5))<<16 | *(buf+i+6)<<8 | *(buf+i+7); else addr64 = ((ut64)(*(buf+i+7)))<<56 | (ut64)(*(buf+i+6))<<48 | (ut64)(*(buf+i+5))<<40 | (ut64)(*(buf+i+4))<<32 | (*(buf+i+3))<<24 | (*(buf+i+2))<<16 | *(buf+i+1)<<8 | *(buf+i); tmp = *arg; feed_me_again: switch (isptr) { case 1: nexti = i + (p->bits/8); i = 0; tmp = *arg; memset (buf, '\0', len); p->printf ("(*0x%"PFMT64x") ", addr); if (p->iob.read_at) { p->iob.read_at (p->iob.io, (ut64)addr, buf, len-4); } else { eprintf ("(cannot read memory)\n"); break; } isptr = 2; break; case 2: // restore state after pointer seek i = nexti; seeki = seek+i; memcpy (buf, b, len); isptr = 0; arg--; idx--; continue; } if (tmp == 0 && last != '*') break; /* skip chars */ switch (tmp) { case '*': isptr = 1; if (i<=0 || !arg[1]) break; arg++; tmp = *arg; //last; // arg--; // idx--; goto feed_me_again; case '+': idx--; viewflags = !viewflags; continue; case 'e': // tmp swap endian idx--; endian ^= 1; continue; case ':': // skip char i+=4; idx-=4; continue; case '.': // skip char i++; idx--; continue; case 'p': tmp = (p->bits==64)?'q': 'x'; //tmp = (sizeof (void*)==8)? 'q': 'x'; break; case '?': // help print_format_help (p); idx--; i = len; // exit continue; } if (otimes>1) p->printf (" "); #define MUSTSET (setval && elem == idx) #define MUSTSEE (elem == -1 || elem == idx) if (MUSTSEE) { if (!(MUSTSET)) { if (oldprintf) p->printf = oldprintf; if (idx<nargs) p->printf (namefmt, r_str_word_get0 (args, idx)); } } else { if (!oldprintf) oldprintf = p->printf; p->printf = nullprintf; } /* cmt chars */ switch (tmp) { #if 0 case 'n': // enable newline j ^= 1; continue; #endif #if 0 case 't': /* unix timestamp */ D cons_printf("0x%08x = ", config.seek+i); { /* dirty hack */ int oldfmt = last_print_format; ut64 old = config.seek; radare_seek(config.seek+i, SEEK_SET); radare_read(0); print_data(config.seek+i, "8", buf+i, 4, FMT_TIME_UNIX); last_print_format=oldfmt; radare_seek(old, SEEK_SET); } break; #endif case 'e': if (MUSTSET) { realprintf ("?e pf e not yet supported\n"); } else { double doub; memcpy (&doub, buf+i, sizeof (double)); p->printf ("0x%08"PFMT64x" = (double) ", seeki); p->printf ("%e", doub); i += 8; } break; case 'q': if (MUSTSET) { realprintf ("wv8 %s @ 0x%08"PFMT64x"\n", setval, seeki); } else { p->printf ("0x%08"PFMT64x" = ", seeki); p->printf ("(qword) "); p->printf ("0x%08"PFMT64x" ", addr64); } i += 8; break; case 'b': if (MUSTSET) { realprintf ("w %s @ 0x%08"PFMT64x"\n", setval, seeki); } else { p->printf ("0x%08"PFMT64x" = ", seeki); p->printf ("%d ; 0x%02x ; '%c' ", buf[i], buf[i], IS_PRINTABLE (buf[i])?buf[i]:0); } i++; break; case 'c': if (MUSTSET) { realprintf ("?e pf c not yet implemented\n"); } else { p->printf ("0x%08"PFMT64x" = ", seeki); p->printf ("%d ; %d ; '%c' ", buf[i], (char)buf[i], IS_PRINTABLE (buf[i])?buf[i]:0); } i++; break; case 'B': if (MUSTSET) { realprintf ("?e pf B not yet implemented\n"); } else { memset (buffer, '\0', 255); if (!p->iob.read_at) { printf ("(cannot read memory)\n"); break; } else p->iob.read_at (p->iob.io, (ut64)addr, buffer, 248); p->printf ("0x%08"PFMT64x" = ", seeki); for (j=0; j<10; j++) p->printf ("%02x ", buf[j]); p->printf (" ... ("); for (j=0; j<10; j++) if (IS_PRINTABLE (buf[j])) p->printf ("%c", buf[j]); p->printf (")"); } i += 4; break; case 'f': if (MUSTSET) { realprintf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki); } else { p->printf ("0x%08"PFMT64x" = %f", seeki, (float)(addr)); } i += 4; break; case 'i': case 'd': // TODO: support unsigned int? if (MUSTSET) { realprintf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki); } else { p->printf ("0x%08"PFMT64x" = ", seeki); p->printf ("%"PFMT64d" ", addr); } i += 4; break; case 'D': if (p->disasm && p->user) i += p->disasm (p->user, seeki); break; case 'x': if (MUSTSET) { realprintf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki); } else { ut32 addr32 = (ut32)addr; p->printf ("0x%08"PFMT64x" = ", seeki); p->printf ("0x%08"PFMT64x" ", addr32); } //if (string_flag_offset(buf, (ut64)addr32, -1)) // p->printf("; %s", buf); i += 4; break; case 'w': case '1': // word (16 bits) if (MUSTSET) { realprintf ("wv2 %s @ 0x%08"PFMT64x"\n", setval, seeki); } else { p->printf ("0x%08x = ", seeki); if (endian) addr = (*(buf+i))<<8 | (*(buf+i+1)); else addr = (*(buf+i+1))<<8 | (*(buf+i)); p->printf ("0x%04x ", addr); } i+=2; break; case 'z': // zero terminated string if (MUSTSET) { realprintf ("?e pf z not yet supported\n"); } else { p->printf ("0x%08"PFMT64x" = ", seeki); for (; buf[i]&&i<len; i++) { if (IS_PRINTABLE (buf[i])) p->printf ("%c", buf[i]); else p->printf ("."); } } break; case 'Z': // zero terminated wide string p->printf ("0x%08"PFMT64x" = ", seeki); for (; buf[i] && i<len; i+=2) { if (IS_PRINTABLE (buf[i])) p->printf ("%c", buf[i]); else p->printf ("."); } p->printf (" "); break; case 's': p->printf ("0x%08"PFMT64x" = ", seeki); memset (buffer, '\0', 255); if (p->iob.read_at) { p->iob.read_at (p->iob.io, (ut64)addr, buffer, sizeof (buffer)-8); } else { printf ("(cannot read memory)\n"); break; } p->printf ("0x%08"PFMT64x" -> 0x%08"PFMT64x" ", seeki, addr); p->printf ("%s ", buffer); i += 4; break; case 'S': p->printf ("0x%08"PFMT64x" = ", seeki); memset (buffer, '\0', 255); if (p->iob.read_at) { p->iob.read_at (p->iob.io, addr64, buffer, sizeof (buffer)-8); } else { printf ("(cannot read memory)\n"); break; } p->printf ("0x%08"PFMT64x" -> 0x%08"PFMT64x" ", seeki, addr); p->printf ("%s ", buffer); i += 8; break; default: /* ignore unknown chars */ break; } if (viewflags && p->offname) { const char *s = p->offname (p->user, seeki); if (s) p->printf ("@(%s)", s); s = p->offname (p->user, addr); if (s) p->printf ("*(%s)", s); } if (tmp != 'D') p->printf ("\n"); last = tmp; } if (otimes>1) p->printf ("}\n"); arg = orig; idx = 0; } if (oldprintf) p->printf = oldprintf; beach: free (buf); if (args) { free (args); } return i; }
R_API char *r_type_get_struct_memb(Sdb *TDB, const char *type, int offset) { int i, prev_typesize, typesize = 0; char *res = NULL; if (offset < 0) { return NULL; } char* query = sdb_fmt ("struct.%s", type); char *members = sdb_get (TDB, query, 0); if (!members) { //eprintf ("%s is not a struct\n", type); return NULL; } int nargs = r_str_split (members, ','); for (i = 0; i < nargs ; i++) { const char *name = r_str_word_get0 (members, i); if (!name) { break; } query = sdb_fmt ("struct.%s.%s", type, name); char *subtype = sdb_get (TDB, query, 0); if (!subtype) { break; } int len = r_str_split (subtype, ','); if (len < 3) { free (subtype); break; } int val = r_num_math (NULL, r_str_word_get0 (subtype, len - 1)); int arrsz = val ? val : 1; if ((typesize / 8) == offset) { res = r_str_newf ("%s.%s", type, name); free (subtype); break; } prev_typesize = typesize; typesize += r_type_get_bitsize (TDB, subtype) * arrsz; // Handle nested structs if (offset < (typesize / 8)) { char *nested_type = (char *)r_str_word_get0 (subtype, 0); if (r_str_startswith (nested_type, "struct ") && !r_str_endswith (nested_type, " *")) { len = r_str_split (nested_type, ' '); if (len < 2) { free (subtype); break; } nested_type = (char *)r_str_word_get0 (nested_type, 1); char *nested_res = r_type_get_struct_memb (TDB, nested_type, offset - (prev_typesize / 8)); if (nested_res) { len = r_str_split(nested_res, '.'); res = r_str_newf ("%s.%s.%s", type, name, r_str_word_get0 (nested_res, len - 1)); free (nested_res); free (subtype); break; } } } free (subtype); } free (members); return res; }
/* hack from print */ R_API int r_print_format_length (const char *fmt) { int nargs, i, j, idx, times, endian; char *args, *bracket, tmp, last = 0; const char *arg = fmt; const char *argend = arg+strlen (fmt); char namefmt[8]; int viewflags = 0; nargs = endian = i = j = 0; while (*arg && iswhitechar (*arg)) arg++; /* get times */ times = atoi (arg); if (times > 0) while ((*arg>='0'&&*arg<='9')) arg++; bracket = strchr (arg,'{'); if (bracket) { char *end = strchr (arg,'}'); if (end == NULL) { eprintf ("No end bracket. Try pm {ecx}b @ esi\n"); return 0; } *end='\0'; times = r_num_math (NULL, bracket+1); arg = end + 1; } if (*arg=='\0') return 0; /* get args */ args = strchr (arg, ' '); if (args) { int l=0, maxl = 0; argend = args; args = strdup (args+1); nargs = r_str_word_set0 (args+1); if (nargs == 0) R_FREE (args); for (i=0; i<nargs; i++) { int len = strlen (r_str_word_get0 (args+1, i)); if (len>maxl) maxl = len; } l++; snprintf (namefmt, sizeof (namefmt), "%%%ds : ", maxl); } /* go format */ i = 0; if (!times) times = 1; for (; times; times--) { // repeat N times const char * orig = arg; idx = 0; arg = orig; for (idx=0; arg<argend && *arg; idx++, arg++) { tmp = *arg; feed_me_again: if (tmp == 0 && last != '*') break; /* skip chars */ switch (tmp) { case '*': if (i<=0) break; tmp = last; arg--; idx--; goto feed_me_again; case '+': idx--; viewflags = !viewflags; continue; case 'e': // tmp swap endian idx--; endian ^= 1; continue; case '.': // skip char i++; idx--; continue; case 'p': tmp = (sizeof (void*)==8)? 'q': 'x'; break; case '?': // help idx--; return 0; } switch (tmp) { case 'e': i += 8; break; case 'q': i += 8; break; case 'b': i++; break; case 'c': i++; break; case 'B': i += 4; break; case 'i': i += 4; break; case 'd': i += 4; break; case 'x': i += 4; break; case 'w': case '1': i+=2; break; case 'z': // XXX unsupported case 'Z': // zero terminated wide string break; case 's': i += 4; break; // S for 8? case 'S': i += 8; break; // S for 8? default: /* ignore unknown chars */ break; } last = tmp; } arg = orig; idx = 0; } // free((void *)&args); return i; }