From 1b88200e3166136079f95d5cf00f15433131983f Mon Sep 17 00:00:00 2001 From: pancake Date: Thu, 22 Oct 2015 02:13:26 +0200 Subject: [PATCH] Add support for 'interpreter' in RBin, ELF and MACH0 --- libr/anal/p/anal_arm_cs.c | 2 +- libr/bin/bin.c | 6 ++-- libr/bin/format/elf/elf.c | 28 +++++++++++++++++- libr/bin/format/elf/elf.h | 1 + libr/bin/format/mach0/mach0.c | 53 ++++++++++++++++++++++++++++++++--- libr/bin/format/mach0/mach0.h | 2 ++ libr/bin/p/bin_elf.c | 1 + libr/bin/p/bin_mach0.c | 1 + libr/core/bin.c | 1 + libr/core/cmd_debug.c | 4 +++ libr/core/cmd_info.c | 13 +++++---- libr/core/core.c | 2 +- libr/include/r_bin.h | 1 + libr/include/r_bp.h | 1 + 14 files changed, 99 insertions(+), 17 deletions(-) diff --git a/libr/anal/p/anal_arm_cs.c b/libr/anal/p/anal_arm_cs.c index 3fe8a50860..adef5f21a0 100644 --- a/libr/anal/p/anal_arm_cs.c +++ b/libr/anal/p/anal_arm_cs.c @@ -265,7 +265,7 @@ static int analop_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len switch (insn->id) { case ARM_INS_IT: - r_strbuf_setf (&op->esil, ""); + // TODO: See #3486 break; case ARM_INS_NOP: r_strbuf_setf (&op->esil, ","); diff --git a/libr/bin/bin.c b/libr/bin/bin.c index 50d78a1aa7..13bcb737b3 100644 --- a/libr/bin/bin.c +++ b/libr/bin/bin.c @@ -1949,16 +1949,14 @@ R_API void r_bin_force_plugin (RBin *bin, const char *name) { } else bin->force = NULL; } -R_API int r_bin_read_at (RBin *bin, ut64 addr, ut8 *buf, int size) -{ +R_API int r_bin_read_at (RBin *bin, ut64 addr, ut8 *buf, int size) { RIOBind *iob; if (!bin || !(iob = &(bin->iob))) return false; return iob->read_at (iob->io, addr, buf, size); } -R_API int r_bin_write_at (RBin *bin, ut64 addr, const ut8 *buf, int size) -{ +R_API int r_bin_write_at (RBin *bin, ut64 addr, const ut8 *buf, int size) { RIOBind *iob; if (!bin || !(iob = &(bin->iob))) return false; diff --git a/libr/bin/format/elf/elf.c b/libr/bin/format/elf/elf.c index 22cafbc6e4..a58e0ab663 100644 --- a/libr/bin/format/elf/elf.c +++ b/libr/bin/format/elf/elf.c @@ -79,7 +79,6 @@ static int init_ehdr(struct Elf_(r_bin_elf_obj_t) *bin) { eprintf ("Warning: read (ehdr)\n"); return false; } - return handle_e_ident (bin); } @@ -777,6 +776,33 @@ int Elf_(r_bin_elf_get_stripped)(struct Elf_(r_bin_elf_obj_t) *bin) { return true; } +char *Elf_(r_bin_elf_intrp)(struct Elf_(r_bin_elf_obj_t) *bin) { + int i; + if (!bin || !bin->phdr) + return NULL; + for (i = 0; i < bin->ehdr.e_phnum; i++) { + if (bin->phdr[i].p_type == PT_INTERP) { + ut64 addr = bin->phdr[i].p_offset; + int sz = bin->phdr[i].p_memsz; + sdb_num_set (bin->kv, "elf_header.intrp_addr", addr, 0); + sdb_num_set (bin->kv, "elf_header.intrp_size", sz, 0); + if (sz <1) { + return NULL; + } + char *str = malloc (sz +1); + if (!str) return NULL; + if (r_buf_read_at (bin->b, addr, (ut8*)str, sz) == -1) { + eprintf ("Warning: read (main)\n"); + return 0; + } + str[sz] = 0; + sdb_set (bin->kv, "elf_header.intrp", str, 0); + return str; + } + } + return NULL; +} + int Elf_(r_bin_elf_get_static)(struct Elf_(r_bin_elf_obj_t) *bin) { int i; if (!bin->phdr) diff --git a/libr/bin/format/elf/elf.h b/libr/bin/format/elf/elf.h index d8f9e95ed9..b381f46655 100644 --- a/libr/bin/format/elf/elf.h +++ b/libr/bin/format/elf/elf.h @@ -108,6 +108,7 @@ ut64 Elf_(r_bin_elf_get_entry_offset)(struct Elf_(r_bin_elf_obj_t) *bin); ut64 Elf_(r_bin_elf_get_main_offset)(struct Elf_(r_bin_elf_obj_t) *bin); ut64 Elf_(r_bin_elf_get_init_offset)(struct Elf_(r_bin_elf_obj_t) *bin); ut64 Elf_(r_bin_elf_get_fini_offset)(struct Elf_(r_bin_elf_obj_t) *bin); +char *Elf_(r_bin_elf_intrp)(struct Elf_(r_bin_elf_obj_t) *bin); int Elf_(r_bin_elf_get_stripped)(struct Elf_(r_bin_elf_obj_t) *bin); int Elf_(r_bin_elf_get_static)(struct Elf_(r_bin_elf_obj_t) *bin); char* Elf_(r_bin_elf_get_data_encoding)(struct Elf_(r_bin_elf_obj_t) *bin); diff --git a/libr/bin/format/mach0/mach0.c b/libr/bin/format/mach0/mach0.c index ec084d0d97..0008a92060 100644 --- a/libr/bin/format/mach0/mach0.c +++ b/libr/bin/format/mach0/mach0.c @@ -533,7 +533,6 @@ static int parse_function_starts (struct MACH0_(obj_t)* bin, ut64 off) { return false; } buf[fc.datasize] = 0; // null-terminated buffer -eprintf ("%p %d\n", buf, buf[0]); bin->func_start = buf; return true; } @@ -607,13 +606,16 @@ static int init_items(struct MACH0_(obj_t)* bin) { //eprintf ("%d\n", lc.cmd); switch (lc.cmd) { case LC_DATA_IN_CODE: + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "data_in_code", 0); // TODO table of non-instructions in __text break; case LC_RPATH: + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "rpath", 0); //eprintf ("--->\n"); break; case LC_SEGMENT_64: case LC_SEGMENT: + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "segment", 0); bin->nsegs++; if (!parse_segments (bin, off)) { eprintf ("error parsing segment\n"); @@ -622,31 +624,37 @@ static int init_items(struct MACH0_(obj_t)* bin) { } break; case LC_SYMTAB: + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "symtab", 0); if (!parse_symtab (bin, off)) { eprintf ("error parsing symtab\n"); return false; } break; case LC_DYSYMTAB: + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "dysymtab", 0); if (!parse_dysymtab(bin, off)) { eprintf ("error parsing dysymtab\n"); return false; } break; case LC_DYLIB_CODE_SIGN_DRS: + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "dylib_code_sign_drs", 0); //eprintf ("[mach0] code is signed\n"); break; case LC_VERSION_MIN_MACOSX: + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "version_min_macosx", 0); bin->os = 1; // set OS = osx //eprintf ("[mach0] Requires OSX >= x\n"); break; case LC_VERSION_MIN_IPHONEOS: + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "version_min_iphoneos", 0); bin->os = 2; // set OS = ios //eprintf ("[mach0] Requires iOS >= x\n"); break; case LC_UUID: + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "uuid", 0); { struct uuid_command uc = {0}; if (off + sizeof (struct uuid_command) > bin->size) { @@ -666,6 +674,7 @@ static int init_items(struct MACH0_(obj_t)* bin) { case LC_ENCRYPTION_INFO_64: /* TODO: the struct is probably different here */ case LC_ENCRYPTION_INFO: + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "encryption_info", 0); { struct encryption_info_command eic = {0}; if (off + sizeof (struct encryption_info_command) > bin->size) { @@ -682,7 +691,30 @@ static int init_items(struct MACH0_(obj_t)* bin) { } } break; case LC_LOAD_DYLINKER: - //eprintf ("[mach0] load dynamic linker\n"); + { + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "dylinker", 0); + free (bin->intrp); + bin->intrp = NULL; + //eprintf ("[mach0] load dynamic linker\n"); + struct dylinker_command dy = {0}; + if (off + sizeof (struct dylinker_command) > bin->size){ + eprintf ("Warning: Cannot parse dylinker command\n"); + return false; + } + if (r_buf_fread_at (bin->b, off, (ut8*)&dy, + bin->endian?"3I":"3i", 1) == -1) { + eprintf ("Warning: read (LC_DYLD_INFO) at 0x%08"PFMT64x"\n", off); + } else { + int len = dy.cmdsize; + char *buf = malloc (len+1); + if (buf) { + r_buf_read_at (bin->b, off + 0xc, (ut8*)buf, len); + buf[len] = 0; + free (bin->intrp); + bin->intrp = buf; + } + } + } break; case LC_MAIN: { @@ -690,6 +722,7 @@ static int init_items(struct MACH0_(obj_t)* bin) { ut64 eo; ut64 ss; } ep = {0}; + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "main", 0); if (!is_first_thread) { eprintf("Error: LC_MAIN with other threads\n"); @@ -711,19 +744,21 @@ static int init_items(struct MACH0_(obj_t)* bin) { } break; case LC_UNIXTHREAD: + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "unixthread", 0); if (!is_first_thread) { eprintf("Error: LC_UNIXTHREAD with other threads\n"); return false; } case LC_THREAD: + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "thread", 0); if (!parse_thread(bin, &lc, off, is_first_thread)) { eprintf ("Cannot parse thread\n"); return false; } - is_first_thread = false; break; case LC_LOAD_DYLIB: + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "load_dylib", 0); bin->nlibs++; if (!parse_dylib(bin, off)){ eprintf ("Cannot parse dylib\n"); @@ -733,6 +768,7 @@ static int init_items(struct MACH0_(obj_t)* bin) { break; case LC_DYLD_INFO: case LC_DYLD_INFO_ONLY: + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "dyld_info", 0); bin->dyld_info = malloc (sizeof(struct dyld_info_command)); if (off + sizeof (struct dyld_info_command) > bin->size){ eprintf ("Cannot parse dyldinfo\n"); @@ -747,24 +783,29 @@ static int init_items(struct MACH0_(obj_t)* bin) { } break; case LC_CODE_SIGNATURE: + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "signature", 0); //eprintf ("mach0: TODO: show code signature\n"); /* ut32 dataoff // ut32 datasize */ break; case LC_SOURCE_VERSION: + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "version", 0); /* uint64_t version; */ /* A.B.C.D.E packed as a24.b10.c10.d10.e10 */ //eprintf ("mach0: TODO: Show source version\n"); break; case LC_SEGMENT_SPLIT_INFO: + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "split_info", 0); /* TODO */ break; case LC_FUNCTION_STARTS: + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "function_starts", 0); if (!parse_function_starts (bin, off)) { eprintf ("Cannot parse LC_FUNCTION_STARTS\n"); } break; case LC_REEXPORT_DYLIB: + sdb_set (bin->kv, sdb_fmt (0, "mach0_cmd_%d.cmd", i), "dylib", 0); /* TODO */ break; default: @@ -1334,7 +1375,7 @@ struct reloc_t* MACH0_(get_relocs)(struct MACH0_(obj_t)* bin) { if (stridx < 0 || stridx >= bin->symstrlen) continue; } - if (!strcmp((char *)bin->symstr + stridx, sym_name)) { + if (!strcmp ((char *)bin->symstr + stridx, sym_name)) { sym_ord = j; break; } @@ -1529,6 +1570,10 @@ int MACH0_(is_big_endian)(struct MACH0_(obj_t)* bin) { return bin && bin->endian; } +const char* MACH0_(get_intrp)(struct MACH0_(obj_t)* bin) { + return bin? bin->intrp: NULL; +} + const char* MACH0_(get_os)(struct MACH0_(obj_t)* bin) { if (bin) switch (bin->os) { diff --git a/libr/bin/format/mach0/mach0.h b/libr/bin/format/mach0/mach0.h index 1ce8d5a274..e2bc991239 100644 --- a/libr/bin/format/mach0/mach0.h +++ b/libr/bin/format/mach0/mach0.h @@ -58,6 +58,7 @@ struct lib_t { struct MACH0_(obj_t) { struct MACH0_(mach_header) hdr; struct MACH0_(segment_command)* segs; + char *intrp; int nsegs; struct MACH0_(section)* sects; int nsects; @@ -120,6 +121,7 @@ char* MACH0_(get_class)(struct MACH0_(obj_t)* bin); int MACH0_(get_bits)(struct MACH0_(obj_t)* bin); int MACH0_(is_big_endian)(struct MACH0_(obj_t)* bin); int MACH0_(is_pie)(struct MACH0_(obj_t)* bin); +const char* MACH0_(get_intrp)(struct MACH0_(obj_t)* bin); const char* MACH0_(get_os)(struct MACH0_(obj_t)* bin); char* MACH0_(get_cputype)(struct MACH0_(obj_t)* bin); char* MACH0_(get_cpusubtype)(struct MACH0_(obj_t)* bin); diff --git a/libr/bin/p/bin_elf.c b/libr/bin/p/bin_elf.c index 4c72605f19..59d3942880 100644 --- a/libr/bin/p/bin_elf.c +++ b/libr/bin/p/bin_elf.c @@ -553,6 +553,7 @@ static RBinInfo* info(RBinFile *arch) { ret->big_endian = Elf_(r_bin_elf_is_big_endian) (arch->o->bin_obj); ret->has_va = Elf_(r_bin_elf_has_va) (arch->o->bin_obj); ret->has_nx = Elf_(r_bin_elf_has_nx) (arch->o->bin_obj); + ret->intrp = Elf_(r_bin_elf_intrp) (arch->o->bin_obj); ret->dbg_info = 0; if (!Elf_(r_bin_elf_get_stripped) (arch->o->bin_obj)) ret->dbg_info |= R_BIN_DBG_LINENUMS | R_BIN_DBG_SYMS | R_BIN_DBG_RELOCS; diff --git a/libr/bin/p/bin_mach0.c b/libr/bin/p/bin_mach0.c index b5c45a0911..9bec4953c0 100644 --- a/libr/bin/p/bin_mach0.c +++ b/libr/bin/p/bin_mach0.c @@ -319,6 +319,7 @@ static RBinInfo* info(RBinFile *arch) { ret->dbg_info = bin->dbg_info; ret->lang = bin->lang; } + ret->intrp = r_str_dup (NULL, MACH0_(get_intrp)(arch->o->bin_obj)); ret->rclass = strdup ("mach0"); ret->os = strdup (MACH0_(get_os)(arch->o->bin_obj)); ret->subsystem = strdup ("darwin"); diff --git a/libr/core/bin.c b/libr/core/bin.c index 746fa414d4..573728c4a6 100644 --- a/libr/core/bin.c +++ b/libr/core/bin.c @@ -413,6 +413,7 @@ static int bin_info(RCore *r, int mode) { pair_bool ("nx", info->has_nx, mode, false); pair_bool ("crypto", info->has_crypto, mode, false); pair_bool ("va", info->has_va, mode, false); + pair_str ("intrp", info->intrp, mode, false); pair_str ("bintype", info->rclass, mode, false); pair_str ("class", info->bclass, mode, false); pair_str ("lang", info->lang, mode, false); diff --git a/libr/core/cmd_debug.c b/libr/core/cmd_debug.c index 5db3d4c55b..7ac76adc5c 100644 --- a/libr/core/cmd_debug.c +++ b/libr/core/cmd_debug.c @@ -43,6 +43,10 @@ static ut64 r_debug_get_baddr(RCore *r, const char *file) { return 0LL; } +static void cmd_debug_software_libs(RCore *core) { + // on linux: + //.!rabin2 -rsB 0x7f516ab31000 '/usr/lib/ld-2.22.so' +} static void cmd_debug_cont_syscall (RCore *core, const char *_str) { // TODO : handle more than one stopping syscall diff --git a/libr/core/cmd_info.c b/libr/core/cmd_info.c index bb6f68d6c4..4606388ca8 100644 --- a/libr/core/cmd_info.c +++ b/libr/core/cmd_info.c @@ -160,15 +160,15 @@ static void cmd_info_bin(RCore *core, int va, int mode) { } r_core_file_info (core, mode); if (obj && bin_is_executable (obj)) { - if ((mode & R_CORE_BIN_JSON)) { - r_cons_printf (",\"bin\":"); - } - r_core_bin_info (core, R_CORE_BIN_ACC_INFO, - mode, va, NULL, NULL); + if ((mode & R_CORE_BIN_JSON)) { + r_cons_printf (",\"bin\":"); + } + r_core_bin_info (core, R_CORE_BIN_ACC_INFO, + mode, va, NULL, NULL); } if (mode == R_CORE_BIN_JSON && array == 0) r_cons_printf ("}\n"); - } else eprintf ("No selected file\n"); + } else eprintf ("No file selected\n"); } static int cmd_info(void *data, const char *input) { @@ -246,6 +246,7 @@ static int cmd_info(void *data, const char *input) { default: eprintf ("Usage: ik [sdb-query]\n"); } + goto done; break; case 'o': { diff --git a/libr/core/core.c b/libr/core/core.c index ed339b1c05..7c56459d9b 100644 --- a/libr/core/core.c +++ b/libr/core/core.c @@ -403,7 +403,7 @@ static const char *radare_argv[] = { "wx", "ww", "w?", "p6d", "p6e", "p8", "pb", "pc", "pd", "pda", "pdb", "pdc", "pdj", "pdr", "pdf", "pdi", "pdl", "pds", "pdt", - "pD", "px", "pX", "po", "pf", + "pD", "px", "pX", "po", "pf", "pv", "p=", "p-", "pm", "pr", "pt", "ptd", "ptn", "pt?", "ps", "pz", "pu", "pU", "p?", NULL }; diff --git a/libr/include/r_bin.h b/libr/include/r_bin.h index eceb3f28eb..3263ce24ca 100644 --- a/libr/include/r_bin.h +++ b/libr/include/r_bin.h @@ -107,6 +107,7 @@ typedef struct r_bin_info_t { ut64 dbg_info; RBinHash sum[3]; ut64 baddr; + char *intrp; #if 0 // stored in sdb /* crypto (iOS bins) */ diff --git a/libr/include/r_bp.h b/libr/include/r_bp.h index f77a1b6c60..7bf1287f06 100644 --- a/libr/include/r_bp.h +++ b/libr/include/r_bp.h @@ -46,6 +46,7 @@ typedef struct r_bp_item_t { int rwx; int hw; int trace; + int internal; /* used for internal purposes */ int enabled; int hits; ut8 *obytes; /* original bytes */