Пример #1
0
/*
* In this pass, we are fixing the edges from jmp-like instructions and their
* targets
*/
void x8664_graph_1 (struct _graph * graph,
                    uint64_t        address)
{
    struct _graph_it * it;
    ud_t               ud_obj;

    for (it = graph_iterator(graph); it != NULL; it = graph_it_next(it)) {
        struct _list * ins_list = graph_it_data(it);
        struct _ins  * ins = list_first(ins_list);

        ud_init      (&ud_obj);
        ud_set_mode  (&ud_obj, 64);
        ud_set_input_buffer(&ud_obj, ins->bytes, ins->size);
        ud_disassemble(&ud_obj);

        struct ud_operand * operand;
        switch (ud_obj.mnemonic) {
        case UD_Ijmp  :
        case UD_Ijo   :
        case UD_Ijno  :
        case UD_Ijb   :
        case UD_Ijae  :
        case UD_Ijz   :
        case UD_Ijnz  :
        case UD_Ijbe  :
        case UD_Ija   :
        case UD_Ijs   :
        case UD_Ijns  :
        case UD_Ijp   :
        case UD_Ijnp  :
        case UD_Ijl   :
        case UD_Ijge  :
        case UD_Ijle  :
        case UD_Ijg   :
            operand = &(ud_obj.operand[0]);

            if (operand->type != UD_OP_JIMM)
                break;
            
            uint64_t head = graph_it_index(it);
            uint64_t tail = head
                             + ud_insn_len(&ud_obj)
                             + udis86_sign_extend_lval(operand);

            int type = INS_EDGE_JCC_TRUE;
            if (ud_obj.mnemonic == UD_Ijmp)
                type = INS_EDGE_JUMP;

            struct _ins_edge * ins_edge = ins_edge_create(type);
            graph_add_edge(graph, head, tail, ins_edge);
            object_delete(ins_edge);
            break;
        default :
            break;
        }
    }
}
Пример #2
0
int rdis_update_memory (struct _rdis *   rdis,
                        uint64_t         address,
                        struct _buffer * buffer)
{
    if (buffer == NULL)
        return -1;

    mem_map_set (rdis->memory, address, buffer);

    // we will regraph functions whose bounds fall within this updated memory,
    // and all functions whose bounds fall within the bounds of functions to be
    // regraphed (step 2 simplifies things later on)
    struct _queue * queue = queue_create();
    struct _map_it * it;
    for (it = map_iterator(rdis->functions); it != NULL; it = map_it_next(it)) {
        struct _function * function = map_it_data(it);
        if (    (    (function->bounds.lower >= address)
                  && (function->bounds.lower <  address + buffer->size))
             || (    (function->bounds.upper >= address)
                  && (function->bounds.upper <  address + buffer->size))
             || (    (function->bounds.lower <= address)
                  && (function->bounds.upper >= address + buffer->size))) {
            queue_push(queue, function);
        }
    }

    struct _map * regraph_functions = map_create();
    while (queue->size > 0) {
        struct _function * function = queue_peek(queue);

        if (map_fetch(regraph_functions, function->address) != NULL) {
            queue_pop(queue);
            continue;
        }

        printf("adding regraph function %llx\n",
               (unsigned long long) function->address);

        map_insert(regraph_functions, function->address, function);

        for (it = map_iterator(rdis->functions); it != NULL; it = map_it_next(it)) {
            struct _function * cmp_function = map_it_data(it);

            if (    (    (cmp_function->bounds.lower >= function->bounds.lower)
                      && (cmp_function->bounds.lower <  function->bounds.upper))
                 || (    (cmp_function->bounds.upper >= function->bounds.lower)
                      && (cmp_function->bounds.upper <  function->bounds.upper))
                 || (    (cmp_function->bounds.lower <= function->bounds.lower)
                      && (cmp_function->bounds.upper >= function->bounds.upper)))
                queue_push(queue, cmp_function);
        }
    }

    // regraph dem functions
    struct _graph * new_graph;
    new_graph = loader_graph_functions(rdis->loader,
                                       rdis->memory,
                                       regraph_functions);

    // We are now going to go through all nodes in our regraph functions. We
    // will copy over comments to the new instructions and then remove the
    // regraph function nodes from the original graph
    for (it = map_iterator(regraph_functions); it != NULL; it = map_it_next(it)) {
        struct _function * function = map_it_data(it);
        struct _graph    * family   = graph_family(rdis->graph, function->address);
        if (family == NULL)
            continue;

        struct _graph_it * git;
        for (git  = graph_iterator(family);
             git != NULL;
             git  = graph_it_next(git)) {
            struct _list * ins_list = graph_it_data(git);
            struct _list_it * iit;
            for (iit = list_iterator(ins_list); iit != NULL; iit = iit->next) {
                struct _ins * ins = iit->data;

                if (ins->comment == NULL)
                    continue;

                struct _ins * new_ins = graph_fetch_ins(new_graph, ins->address);

                if (ins->size != new_ins->size)
                    continue;

                if (memcmp(ins->bytes, new_ins->bytes, ins->size) == 0) {
                    printf("copy over comment from instruction at %llx\n",
                           (unsigned long long) ins->address);
                    ins_s_comment(new_ins, ins->comment);
                }
            }
            // add node for deletion
            struct _index * index = index_create(graph_it_index(git));
            queue_push(queue, index);
            object_delete(index);
        }

        object_delete(family);

        while (queue->size > 0) {
            struct _index * index = queue_peek(queue);
            graph_remove_node(rdis->graph, index->index);
            queue_pop(queue);
        }
    }

    // merge the new graph with the old graph
    graph_merge(rdis->graph, new_graph);

    // reset bounds of these functions
    for (it = map_iterator(regraph_functions); it != NULL; it = map_it_next(it)) {
        struct _function * function = map_it_data(it);
        rdis_function_bounds(rdis, function->address);
    }

    objects_delete(queue, new_graph, regraph_functions, NULL);

    rdis_callback(rdis, RDIS_CALLBACK_ALL);

    return 0;
}