Beispiel #1
0
static int analyze(RAnal *anal, RAnalOp *op, ut64 offset, ut8* buf, int len) {
	char *bytes, *optype = NULL, *stackop = NULL;
	int ret;

	ret = r_anal_op (anal, op, offset, buf, len);
	if (ret) {
		stackop = stackop2str (op->stackop);
		optype = optype2str (op->type);
		bytes = r_hex_bin2strdup (buf, ret);
		printf ("bytes:    %s\n", bytes);
		printf ("type:     %s\n", optype);
		if (op->jump != -1LL)
			printf ("jump:     0x%08"PFMT64x"\n", op->jump);
		if (op->fail != -1LL)
			printf ("fail:     0x%08"PFMT64x"\n", op->fail);
		//if (op->ref != -1LL)
		//	printf ("ref:      0x%08"PFMT64x"\n", op->ref);
		if (op->val != -1LL)
			printf ("value:    0x%08"PFMT64x"\n", op->val);
		printf ("stackop:  %s\n", stackop);
		printf ("esil:     %s\n", r_strbuf_get (&op->esil));
		printf ("stackptr: %"PFMT64d"\n", op->stackptr);
		printf ("decode str: %s\n", r_anal_op_to_string (anal, op));
		printf ("--\n");
		free (optype);
		free (stackop);
		free (bytes);
	}
	return ret;
}
Beispiel #2
0
static RList *r_core_asm_back_disassemble (RCore *core, ut64 addr, int len, ut64 max_hit_count, ut8 disassmble_each_addr, ut32 extra_padding) {
	RList *hits;;
	RAsmOp op;
	ut8 *buf = NULL;
	ut8 max_invalid_b4_exit = 4,
		last_num_invalid = 0;
	int current_instr_len = 0;
	ut64 current_instr_addr = addr,
		current_buf_pos = 0,
		next_buf_pos = len;

	RCoreAsmHit dummy_value;
	ut32 hit_count = 0;

	if (disassmble_each_addr){
		return r_core_asm_back_disassemble_all(core, addr, len, max_hit_count, extra_padding+1);
	}

	hits = r_core_asm_hit_list_new ();
	buf = malloc (len + extra_padding);

	if (!hits || !buf ){
		if (hits) {
			r_list_purge (hits);
			free (hits);
		}
		free (buf);
		return NULL;
	}

	if (r_io_read_at (core->io, (addr + extra_padding)-len, buf, len+extra_padding) != len+extra_padding) {
		r_list_purge (hits);
		free (hits);
		free (buf);
		return NULL;
	}

	//
	// XXX - This is a heavy handed approach without a
	// 		an appropriate btree or hash table for storing
	//	 hits, because are using:
	//			1) Sorted RList with many inserts and searches
	//			2) Pruning hits to find the most optimal disassembly

	// greedy approach
	// 1) Consume previous bytes
	// 1a) Instruction is invalid (incr current_instr_addr)
	// 1b) Disasm is perfect
	// 1c) Disasm is underlap (disasm(current_instr_addr, next_instr_addr - current_instr_addr) short some bytes)
	// 1d) Disasm is overlap (disasm(current_instr_addr, next_instr_addr - current_instr_addr) over some bytes)

	memset (&dummy_value, 0, sizeof (RCoreAsmHit));
	// disassemble instructions previous to current address, extra_padding can move the location of addr
	// so we need to account for that with current_buf_pos
	current_buf_pos = len - extra_padding - 1;
	next_buf_pos = len + extra_padding - 1;
	current_instr_addr = addr-1;
	do {
		if (r_cons_singleton ()->breaked) break;
		// reset assembler
		r_asm_set_pc (core->assembler, current_instr_addr);
		current_instr_len = next_buf_pos - current_buf_pos;
		current_instr_len = r_asm_disassemble (core->assembler, &op, buf+current_buf_pos, current_instr_len);

		IFDBG {
			ut32 byte_cnt =  current_instr_len ? current_instr_len : 1;
			eprintf("current_instr_addr: 0x%"PFMT64x", current_buf_pos: 0x%"PFMT64x", current_instr_len: %d \n", current_instr_addr, current_buf_pos, current_instr_len);

			ut8 *hex_str = (ut8*)r_hex_bin2strdup(buf+current_buf_pos, byte_cnt);
			eprintf("==== current_instr_bytes: %s ",hex_str);

			if (current_instr_len > 0)
				eprintf("op.buf_asm: %s\n", op.buf_asm);
			else
				eprintf("op.buf_asm: <invalid>\n");

			free(hex_str);
		}

		// disassembly invalid
		if (current_instr_len == 0 || strstr (op.buf_asm, "invalid")) {
			if (current_instr_len == 0) current_instr_len = 1;
			add_hit_to_sorted_hits(hits, current_instr_addr, current_instr_len, /* is_valid */ false);
			hit_count ++;
			last_num_invalid ++;
		// disassembly perfect
		} else if (current_buf_pos + current_instr_len == next_buf_pos) {
			// i think this may be the only case where an invalid instruction will be
			// added because handle_forward_disassemble and handle_disassembly_overlap
			// are only called in cases where a valid instruction has been found.
			// and they are lazy, since they purge the hit list
			ut32 purge_results = 0;
			ut8 is_valid = true;
			IFDBG eprintf(" handling underlap case: current_instr_addr: 0x%"PFMT64x".\n", current_instr_addr);
			purge_results =  prune_hits_in_addr_range(hits, current_instr_addr, current_instr_len, /* is_valid */ true);
			if (purge_results) {
				handle_forward_disassemble(core, hits, buf, len, current_buf_pos+current_instr_len, current_instr_addr+current_instr_len, addr);
				hit_count = r_list_length(hits);
			}
			add_hit_to_sorted_hits(hits, current_instr_addr, current_instr_len, is_valid);
			//handle_forward_disassemble(core, hits, buf, len, current_buf_pos+current_instr_len, current_instr_addr+current_instr_len, addr/*end_addr*/);
			hit_count ++;
			next_buf_pos = current_buf_pos;
			last_num_invalid = 0;
		// disassembly underlap
		} else if (current_buf_pos + current_instr_len < next_buf_pos) {
			ut32 purge_results = 0;
			ut8 is_valid = true;
			purge_results =  prune_hits_in_addr_range(hits, current_instr_addr, current_instr_len, /* is_valid */ true);
			add_hit_to_sorted_hits(hits, current_instr_addr, current_instr_len, is_valid);

			if (hit_count < purge_results ) hit_count = 0; // WTF??
			else hit_count -= purge_results;

			next_buf_pos = current_buf_pos;
			handle_forward_disassemble(core, hits, buf, len - extra_padding, current_buf_pos+current_instr_len, current_instr_addr+current_instr_len, addr);
			hit_count = r_list_length(hits);
			last_num_invalid = 0;
		// disassembly overlap
		} else if (current_buf_pos + current_instr_len > next_buf_pos) {
			//ut64 value = handle_disassembly_overlap(core, hits, buf, len, current_buf_pos, current_instr_addr);
			next_buf_pos = current_buf_pos;
			hit_count = r_list_length (hits);
			last_num_invalid = 0;
		}

		// walk backwards by one instruction
		IFDBG eprintf(" current_instr_addr: 0x%"PFMT64x" current_instr_len: %d next_instr_addr: 0x%04"PFMT64x"\n",
			current_instr_addr, current_instr_len, next_buf_pos);
		IFDBG eprintf(" hit count: %d \n", hit_count );
		current_instr_addr -= 1;
		current_buf_pos -= 1;

		if ( hit_count >= max_hit_count &&
			 (last_num_invalid >= max_invalid_b4_exit || last_num_invalid == 0))
			break;
	} while (((int) current_buf_pos >= 0) && (int)(len - current_buf_pos) >= 0);

	r_asm_set_pc (core->assembler, addr);
	free (buf);
	return hits;
}
Beispiel #3
0
static int r_print_format_uleb(const RPrint* p, int endian, int mode,
		const char* setval, ut64 seeki, ut8* buf, int i, int size) {
	int elem = -1;
	int s = 0, sum = 0;
	ut64 value = 0, offset = 0;
	if (size >= ARRAYINDEX_COEF) {
		elem = size / ARRAYINDEX_COEF - 1;
		size %= ARRAYINDEX_COEF;
	}
	// offset = seeki+((elem>=0)?16*elem:0);
	if (MUSTSET) {
		ut8 *tmp;
		char *nbr;
		do {
			offset += s;
			r_uleb128_decode (buf+offset, &s, &value);
		} while (elem--);
		tmp = (ut8*) r_uleb128_encode (r_num_math (NULL, setval), &s);
		nbr = r_hex_bin2strdup (tmp, s);
		p->cb_printf ("\"wx %s\" @ 0x%08"PFMT64x"\n", nbr, seeki+offset);
		free (tmp);
		free (nbr);
		// sum = size of the converted number
	} else if (MUSTSEE) {
		if (!SEEVALUE) p->cb_printf ("0x%08"PFMT64x" = ", seeki);
		if (size==-1) {
			r_uleb128_decode (buf+i, &s, &value);
			p->cb_printf ("%"PFMT64d, value);
			sum = s;
		} else {
			if (!SEEVALUE) p->cb_printf ("[ ");
			while (size--) {
				if (elem == -1 || elem == 0) {
					r_uleb128_decode (buf+i, &s, &value);
					sum += s;
					p->cb_printf ("%"PFMT64d, value);
					if (elem == 0) elem = -2;
				}
				if (size != 0 && elem == -1)
					p->cb_printf (", ");
				if (elem > -1) elem--;
				i+=s;
			}
			if (!SEEVALUE) p->cb_printf (" ]");
		}
	} else if (MUSTSEEJSON) {
		if (size==-1) {
			r_uleb128_decode (buf+i, &s, &value);
			p->cb_printf ("\"%"PFMT64d"\"", value);
			sum = s;
		} else {
			p->cb_printf ("[ ");
			while (size--) {
				if (elem == -1 || elem == 0) {
					r_uleb128_decode (buf+i, &s, &value);
					sum += s;
					p->cb_printf ("\"%"PFMT64d"\"", value);
					if (elem == 0) elem = -2;
				}
				if (size != 0 && elem == -1)
					p->cb_printf (", ");
				if (elem > -1) elem--;
				i+=s;
			}
			p->cb_printf (" ]");
		}
		p->cb_printf ("}");
	}
	return sum;
}