Add support for 'interpreter' in RBin, ELF and MACH0

This commit is contained in:
pancake 2015-10-22 02:13:26 +02:00
parent 680d354942
commit 1b88200e31
14 changed files with 99 additions and 17 deletions

View File

@ -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, ",");

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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) {

View File

@ -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);

View File

@ -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;

View File

@ -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");

View File

@ -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);

View File

@ -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

View File

@ -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':
{

View File

@ -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
};

View File

@ -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) */

View File

@ -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 */