Пример #1
0
unsigned int x86_disasm_range( unsigned char *buf, uint32_t buf_rva,
                      unsigned int offset, unsigned int len,
                      DISASM_CALLBACK func, void *arg ) {
        x86_insn_t insn;
        unsigned int buf_len, size, count = 0, bytes = 0;

        /* buf_len is implied by the arguments */
        buf_len = len + offset;

        while ( bytes < 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 */
                }

		x86_oplist_free( &insn );
        }

        return( count );
}
Пример #2
0
char *ropit_x86_list_disasm (uint8_t *bytes, int len) {
    int pos = 0;             // current position in buffer
    int size;                // size of instruction
    x86_insn_t insn;         // instruction
    char line[4096] = {0};
    int linelen = 4096;
    char *listing = NULL;

    listing = calloc(2048, sizeof(*listing));

    x86_init(opt_none, NULL, NULL);
    while ( pos < len ) {
        // disassemble address
        size = x86_disasm(bytes, len, 0, pos, &insn);
        if ( size ) {
            // print instruction
            x86_format_insn(&insn, line, linelen, intel_syntax);
            // printf("%s\n", line);
            strcat(listing, line);
            strcat(listing, "\n");
            pos += size;
        }
        else {
            pos++;
        }
        x86_oplist_free(&insn);
    }
    x86_cleanup();

    return listing;
}
Пример #3
0
// disasm 1 instruction
char *ropit_x86_disasm (uint8_t *bytes, int len, int *sz_dis)
{
    int sz_inst, len_disasm;             /* sz_inst of instruction */
    x86_insn_t insn;         /* instruction */
    char line[1024];
    int sz_line = 1024;
    char *disasm;

    if (!bytes || len <= 0 || !sz_dis) {
        debug_printf (MESSAGE_ERROR, stderr, "error: ropit_x86_disasm(): Bad parameter(s)\n");
        return NULL;
    }

    len_disasm = 0;

    x86_init(opt_none, NULL, NULL);
    sz_inst = x86_disasm (bytes, len, 0, 0, &insn);
    if (sz_inst > 0) {
        len_disasm = x86_format_insn (&insn, line, sz_line, intel_syntax);
        *sz_dis = sz_inst;
    }
    x86_oplist_free (&insn);
    x86_cleanup();

    if (len_disasm == 0)
        return NULL;

    disasm = calloc (len_disasm, sizeof(*disasm));
    if (!disasm) {
        debug_printf (MESSAGE_ERROR, stderr, "error: ropit_x86_disasm(): Failed disasm alloc\n");
        return NULL;
    }

    memcpy (disasm, line, len_disasm);

    return disasm;
}
Пример #4
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 );
}
Пример #5
0
void IMG_addrlabels(Image_t *img, int secid) {
    assert(img != NULL);
    Section_t *sec;
    x86_insn_t insn;

    sec = IMG_getsection(img, secid);
    if (sec->plan == NULL) {
        return;
    }
    #if 0
    sec->data = (uint8_t *)BUF_getptr(sec->buf_data);
    printf("%d %02X\n", secid, sec->data[0]);
    printf("%d %02X\n", 1, *((uint8_t *)IMG_getptr(img, uaddr_mk(1, 0))));
    return;
    #endif
    uaddr_t min_target = uaddr_mk(secid, 0);
    uaddr_t max_target = uaddr_mk(secid, IMG_getsecsize(img, secid));
    IMG_begintransaction(img);
    //for (int pos = 0; pos < 349; pos++) {
    int count = 0;
    for (int pos = 0; pos < sec->size; pos++) {
        int len = plan_size(sec->plan, pos);
        if (PLAN_ISCODE(sec->plan, pos)) {
            x86_disasm((unsigned char *)sec->data, sec->size, uaddr_mk(secid, 0), pos, &insn);
            x86_op_t *op = x86_get_branch_target(&insn);
            int rel;
            int relsize = 0;
            bool found = false;
            // ve se essa instrucao tem algum operando
            if (op != NULL) {
                // so nos interessam operandos relativos (jumps)
                if (op->type == op_relative_near) {
                    found = true;
                    rel = (int)op->data.relative_near;
                    relsize = 1;
                } else if (op->type == op_relative_far) {
                    found = true;
                    rel = op->data.relative_far;
                    relsize = 4;                   //// FIXME pode ser 2 em 16 bits
                }
            }
            if (found) {
                int disp = 0;
                uaddr_t target = insn.addr + insn.size + rel;
                //printf("%d ADD LABEL L%08X\n", pos, target);
                //IMG_addlabel(img, target, NULL);
                // Se necessário, desloca o label até o início de uma instrução
                if ((target < min_target) || (target >= max_target)) {
                    printf("ERROR: relative jump/call at %08X points to %08X\n", uaddr_mk(secid, pos), target);
                    x86_oplist_free(&insn);
                    IMG_endtransaction(img);
                    return;
                }
        #if 1
                for (;;) {
                    uint8_t uuu = sec->plan[uaddr_off(target)];
                    //if (!((uuu & CP_INSIDE) || (uuu == CP_DATA2))) {
                    if (!(uuu & PLAN_INSIDE)) {
                        break;
                    }
                    disp++;
                    target--;
                }
        #endif
                //printf("%d\n", disp);
                //printf("%08X %08X\n", uaddr_mk(secid, pos), target);
                //printf("%08X %08X\n", uaddr_mk(secid, pos), target);
        #if 1
                uaddr_t afrom = uaddr_mk(secid, pos) + 1;
                if (sec->data[pos] == 0x0F) {
                    afrom += 1;
                }
                IMG_addreloc(img, afrom, target, relsize, disp, RELOC_REL); // FIXME::: SIZE 0??
        #endif
                count++;
            }
            x86_oplist_free(&insn);
        }
        pos += len - 1;
    }
    IMG_endtransaction(img);
    //printf("; %d labels added\n", count);
}
Пример #6
0
// find valid instructions offsets before ret
int _ropit_x86_find_gadgets (uint8_t *bytes, int len, int64_t *rets, int n_rets) {
    int sz_inst;                /* size of instruction */
    x86_insn_t insn;         /* instruction */
    int idx_ret, sz_ret;
    int valid_gadget;
    // back track instruction count
    int n_backtrack_inst, n_backtrack_bytes;
    // start for rop search
    uint8_t *start, *gadget_start;
    // disassemble
    int len_disasm;
    int sz_dst;
    char disassembled[DISASSEMBLED_SIZE_MAX] = {0};
    // cache
    FILE *fp_cache;
    struct cache_t *caches;
    int idx_caches, n_caches;
    struct gadget_t *gadgets;
    int idx_gadgets, n_gadgets;
    // cache queue
    struct gadget_cache_queue_t *cache_queue;
    // count
    int count_gadgets;

    // check params
    if (!bytes || len <= 0) {
        debug_printf (MESSAGE_ERROR, stderr, "error: _ropit_x86_find_gadgets(): Bytes null or len <= 0\n");
        return NULL;
    }

    // search rets
    if (!rets || n_rets <= 0) {
        debug_printf (MESSAGE_ERROR, stderr, "error: _ropit_x86_find_gadgets(): No rets\n");
        return NULL;
    }

    // init gadget_cache
    fp_cache = fopen("tmp/gadget_cache", "w");
    if (!fp_cache) {
        debug_printf (MESSAGE_ERROR, stderr, "error: _ropit_x86_find_gadgets(): Failed open (w)\n");
        return NULL;
    }

    // init cache_queue
    cache_queue = NULL;
    if (!gadget_cache_queue_init(&cache_queue)) {
        debug_printf (MESSAGE_ERROR, stderr, "error: _ropit_x86_find_gadgets(): Cache queue allocation failed\n");
        return NULL;
    }
    gadget_cache_queue_set_file (cache_queue, fp_cache);

    // init gadgets
    n_gadgets = 1024;
    gadgets = calloc(sizeof(struct gadget_t), n_gadgets);
    if (!gadgets) {
        debug_printf (MESSAGE_ERROR, stderr, "error: _ropit_x86_find_gadgets(): Failed allocating caches\n");
        return NULL;
    }

    for (idx_gadgets = 0; idx_gadgets < n_gadgets; idx_gadgets++)
        gadget_init(&(gadgets[idx_gadgets]), DISASSEMBLED_SIZE_MAX);

    // init caches
    n_caches = 1;
    caches = calloc(sizeof(struct cache_t), n_caches);
    if (!caches) {
        debug_printf (MESSAGE_ERROR, stderr, "error: _ropit_x86_find_gadgets(): Failed allocating caches\n");
        return NULL;
    }

    for (idx_caches = 0; idx_caches < n_caches; idx_caches++) {
        cache_init(&(caches[idx_caches]), 1024);
    }

    // init disasm
    x86_init(opt_none, NULL, NULL);

    idx_caches = 0;
    idx_gadgets = 0;
    count_gadgets = 0;
    for (idx_ret = 0; idx_ret < n_rets; idx_ret++) {
        start = bytes + rets[idx_ret];

        n_backtrack_inst = 0;
        n_backtrack_bytes = 0;
        while ( bytes <= start && start <= bytes + len ) {
            /* disassemble address */
            sz_inst = x86_disasm(start, len - (start - bytes), 0, 0, &insn);
            x86_oplist_free(&insn);

            if (sz_inst <= 0) {
                // printf("not found inst\n");
                n_backtrack_bytes++;
            }
            else {
                // printf("found inst\n");
                n_backtrack_bytes = 0;

                valid_gadget = 0;
                //
                gadget_start = start;
                if (gadget_start == bytes + rets[idx_ret])
                    valid_gadget = 1;
                else {
                    n_backtrack_inst = 0;
                    // check gadget validity
                    while (bytes <= gadget_start && gadget_start <= bytes + rets[idx_ret]) {
                        /* disassemble address */
                        sz_inst = x86_disasm(gadget_start, gadget_start - bytes, 0, 0, &insn);
                        x86_oplist_free(&insn);
                        if (sz_inst <= 0)
                            break;
                        else {
                            n_backtrack_inst++;
                            gadget_start += sz_inst;
                            if (gadget_start == bytes + rets[idx_ret]) {
                                valid_gadget = 1;
                                break;
                            }
                        }
                    }
                }

                if (valid_gadget == 1) {
                    //
                    ++count_gadgets;

                    // get ret size
                    sz_ret = x86_disasm(bytes + rets[idx_ret], 10, 0, 0, &insn);
                    x86_oplist_free(&insn);

                    // fill gadget structure
                    gadgets[idx_gadgets].ret_addr = rets[idx_ret];
                    gadgets[idx_gadgets].ret_bytes = rets[idx_ret] + bytes;
                    gadgets[idx_gadgets].address = start - bytes;
                    gadgets[idx_gadgets].len_bytes = (rets[idx_ret] - (start - bytes)) + sz_ret;
                    if (gadgets[idx_gadgets].sz_bytes < gadgets[idx_gadgets].len_bytes) {
                        gadgets[idx_gadgets].bytes = realloc (gadgets[idx_gadgets].bytes, gadgets[idx_gadgets].len_bytes);
                        gadgets[idx_gadgets].sz_bytes = gadgets[idx_gadgets].len_bytes;
                    }
                    memcpy(gadgets[idx_gadgets].bytes, start, gadgets[idx_gadgets].len_bytes);

                    if (cache_add (&(caches[idx_caches]), &(gadgets[idx_gadgets])) == -ERR_CACHE_FULL) {
                        gadget_cache_queue_add (cache_queue, &(caches[idx_caches]));
                        gadget_cache_queue_fwrite_worker (cache_queue);
                        cache_reset (&(caches[idx_caches]));
                    }

                    idx_gadgets = (idx_gadgets + 1) % n_gadgets;
                }
            }
            --start;

            // maximum intel instruction size is 15
            // maximum instructions in a gadget is hardcoded to 8 here
            /* TODO : Get more gadgets with n_backtrack_inst instructions
             * Effectively, we stop at the first gadget which has
             * n_backtrack_inst instructions while there might be multiple
             * possibilities.
             */
            if (n_backtrack_bytes >= 15 || n_backtrack_inst == 8)
                break;
        }
    }
    x86_cleanup();

    // write remaining gadgets
    gadget_cache_queue_add (cache_queue, &(caches[idx_caches]));
    gadget_cache_queue_fwrite_worker (cache_queue);
    cache_reset (&(caches[idx_caches]));

    // clean up
    for (idx_caches = 0; idx_caches < n_caches; idx_caches++)
        free(caches[idx_caches].objects);
    free(caches);

    for (idx_gadgets = 0; idx_gadgets < n_gadgets; idx_gadgets++) {
        // gadget_free(&(gadgets[idx_gadgets]));
        // free (gadgets[idx_gadgets].repr);
        free (gadgets[idx_gadgets].bytes);
    }
    free(gadgets);

    gadget_cache_queue_destroy (&cache_queue);

    fclose (fp_cache);

    return count_gadgets;
}