Пример #1
0
unsigned int x86_disasm( unsigned char *buf, unsigned int buf_len,
                uint32_t buf_rva, unsigned int offset,
                x86_insn_t *insn ){
        int len, size;
        x86_oplist_t *op_save;
	unsigned char bytes[MAX_INSTRUCTION_SIZE];

        if ( ! buf || ! insn || ! buf_len ) {
                /* caller screwed up somehow */
                return 0;
        }


	/* ensure we are all NULLed up */
        op_save = insn->operands;
        memset( insn, 0, sizeof(x86_insn_t) );
        insn->operands = op_save;
        insn->addr = buf_rva + offset;
        insn->offset = offset;
	/* default to invalid insn */
	insn->type = insn_invalid;
	insn->group = insn_none;

        if ( offset >= buf_len ) {
                /* another caller screwup ;) */
                x86_report_error(report_disasm_bounds, (void*)(long)(buf_rva+offset));
                return 0;
        }

        len = buf_len - offset;

	/* copy enough bytes for disassembly into buffer : this
	 * helps prevent buffer overruns at the end of a file */
	memset( bytes, 0, MAX_INSTRUCTION_SIZE );
	memcpy( bytes, &buf[offset], (len < MAX_INSTRUCTION_SIZE) ? len : 
		MAX_INSTRUCTION_SIZE );

        /* actually do the disassembly */
	/* TODO: allow switching when more disassemblers are added */
        size = ia32_disasm_addr( bytes, len, insn);

        /* check and see if we had an invalid instruction */
        if (! size ) {
                x86_report_error(report_invalid_insn, (void*)(long)(buf_rva+offset) );
                return 0;
        }

        /* check if we overran the end of the buffer */
        if ( size > len ) {
                x86_report_error( report_insn_bounds, (void*)(long)(buf_rva + offset) );
		MAKE_INVALID( insn, bytes );
		return 0;
	}

        /* fill bytes field of insn */
        memcpy( insn->bytes, bytes, size );

        return size;
}
Пример #2
0
unsigned int x86_disasm_forward( unsigned char *buf, unsigned int buf_len,
                        uint32_t buf_rva, unsigned int offset,
                        DISASM_CALLBACK func, void *arg,
                        DISASM_RESOLVER resolver, void *r_arg ){
        x86_insn_t insn;
        x86_op_t *op;
        int32_t next_addr;
        uint32_t next_offset;
        unsigned int size, count = 0, bytes = 0, cont = 1;

        while ( cont && bytes < buf_len ) {
                size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
                           &insn );

                if ( size ) {
                        /* invoke callback if it exists */
                        if ( func ) {
                                (*func)( &insn, arg );
                        }
                        bytes += size;
                        count ++;
                } else {
                        /* error */
                        bytes++;        /* try next byte */
                }

                if ( follow_insn_dest(&insn) ) {
                        op = x86_get_dest_operand( &insn );
                        next_addr = -1;

                        /* if caller supplied a resolver, use it to determine
                         * the address to disassemble */
                        if ( resolver ) {
                                next_addr = resolver(op, &insn, r_arg);
                        } else {
                                next_addr = internal_resolver(op, &insn);
                        }

                        if (next_addr != -1 ) {
                                next_offset = next_addr - buf_rva;
                                /* if offset is in this buffer... */
                                if ( next_addr >= buf_rva &&
                                     next_offset < buf_len ) {
                                        /* go ahead and disassemble */
                                        count += x86_disasm_forward( buf,
                                                            buf_len,
                                                            buf_rva,
                                                            next_offset,
                                                            func, arg,
                                                            resolver, r_arg );
                                } else  {
                                        /* report unresolved address */
                                        x86_report_error( report_disasm_bounds,
                                                     (void*)(long)next_addr );
                                }
                        }
                } /* end follow_insn */

                if ( insn_doesnt_return(&insn) ) {
                        /* stop disassembling */
                        cont = 0;
                }

		x86_oplist_free( &insn );
        }
        return( count );
}