コード例 #1
0
int rdis_function_reachable (struct _rdis * rdis, uint64_t address)
{
    struct _function * function = map_fetch(rdis->functions, address);
    if (function == NULL)
        return -1;
    function->flags |= FUNCTION_REACHABLE;

    // get this function's call graph
    struct _graph * cg = create_call_graph(rdis->graph, address);
    struct _graph_it * git;
    // for each function in the graph
    for (git = graph_iterator(cg); git != NULL; git = graph_it_next(git)) {
        struct _list * ins_list = graph_it_data(git);
        struct _list_it * lit;
        // for each call in the function in the graph
        for (lit = list_iterator(ins_list); lit != NULL; lit = lit->next) {
            struct _ins * ins = lit->data;
            // insure function has correct flags
            if (    (ins->flags & (INS_TARGET_SET | INS_CALL))
                 == (INS_TARGET_SET | INS_CALL)) {

                function = map_fetch(rdis->functions, ins->target);
                if (function == NULL)
                    continue;
                function->flags |= FUNCTION_REACHABLE;
            }
        }
    }

    return 0;
}
コード例 #2
0
struct _map * rdis_g_references (struct _rdis * rdis)
{
    struct _map * references = map_create();

    struct _graph_it * git;
    // for each node
    for (git = graph_iterator(rdis->graph); git != NULL; git = graph_it_next(git)) {
        struct _graph_node * node = graph_it_node(git);
        struct _list_it * lit;

        // for each instruction
        for (lit = list_iterator(node->data); lit != NULL; lit = lit->next) {
            struct _ins * ins = lit->data;
            struct _list_it * rit;

            // for each reference
            for (rit = list_iterator(ins->references); rit != NULL; rit = rit->next) {
                struct _reference * reference = rit->data;
                int delete_reference = 0;

                if (reference->type == REFERENCE_CONSTANT) {
                    uint64_t lower = map_fetch_max_key(rdis->memory, reference->address);
                    struct _buffer * buffer = map_fetch(rdis->memory, lower);
                    if (buffer == NULL)
                        continue;
                    uint64_t upper = lower + buffer->size;
                    if (    (reference->address < lower)
                         || (reference->address >= upper))
                        continue;
                    reference = object_copy(reference);
                    reference->type = REFERENCE_CONSTANT_ADDRESSABLE;
                    delete_reference = 1;
                }


                struct _list * ref_list = map_fetch(references, reference->address);
                if (ref_list == NULL) {
                    ref_list = list_create();
                    map_insert(references, reference->address, ref_list);
                    object_delete(ref_list);
                    ref_list = map_fetch(references, reference->address);
                }

                list_append(ref_list, reference);

                if (delete_reference)
                    object_delete(reference);
            }
        }
    }

    return references;
}
コード例 #3
0
void rdis_check_references (struct _rdis * rdis)
{
    struct _graph_it * git;
    // for each node
    for (git = graph_iterator(rdis->graph); git != NULL; git = graph_it_next(git)) {
        struct _graph_node * node = graph_it_node(git);
        struct _list_it * lit;

        // for each instruction
        for (lit = list_iterator(node->data); lit != NULL; lit = lit->next) {
            struct _ins * ins = lit->data;
            struct _list_it * rit;

            // for each reference
            for (rit = list_iterator(ins->references); rit != NULL; rit = rit->next) {
                struct _reference * reference = rit->data;

                if (reference->type == REFERENCE_CONSTANT) {
                    uint64_t lower = map_fetch_max_key(rdis->memory, reference->address);
                    struct _buffer * buffer = map_fetch(rdis->memory, lower);
                    if (buffer == NULL)
                        continue;
                    uint64_t upper = lower + buffer->size;
                    if (    (reference->address < lower)
                         || (reference->address >= upper))
                        continue;
                    reference->type = REFERENCE_CONSTANT_ADDRESSABLE;
                }
            }
        }
    }
}
コード例 #4
0
ファイル: elf32.c プロジェクト: TDKPS/rdis
struct _map * elf32_functions_wqueue (struct _elf32 * elf32,
                                      struct _map *   memory,
                                      struct _list *  entries)
{
    struct _map * functions = map_create();
    struct _wqueue * wqueue = wqueue_create();
    struct _list_it * it;
    for (it = list_iterator(entries); it != NULL; it = it->next) {
        struct _function * function = it->data;

        if (map_fetch(functions, function->address) == NULL)
            map_insert(functions, function->address, function);

        struct _x86_wqueue * x86w;
        x86w = x86_wqueue_create(function->address, memory);

        wqueue_push(wqueue, WQUEUE_CALLBACK(x86_functions_wqueue), x86w);
        object_delete(x86w);
    }

    wqueue_wait(wqueue);

    struct _map * fmap;
    while ((fmap = wqueue_peek(wqueue)) != NULL) {
        struct _map_it * mit;
        for (mit = map_iterator(fmap); mit != NULL; mit = map_it_next(mit)) {
            struct _function * function = map_it_data(mit);

            if (map_fetch(functions, function->address) == NULL)
                map_insert(functions, function->address, function);
        }
        wqueue_pop(wqueue);
    }

    object_delete(wqueue);

    return functions;
}
コード例 #5
0
int rdis_function_bounds (struct _rdis * rdis, uint64_t address)
{
    struct _function * function = map_fetch(rdis->functions, address);
    
    if (function == NULL)
        return -1;

    struct _graph * family = graph_family(rdis->graph, address);

    if (family == NULL)
        return -1;

    uint64_t lower = -1;
    uint64_t upper = 0;

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

            if (ins->address < lower)
                lower = ins->address;
            if (ins->address + ins->size > upper)
                upper = ins->address + ins->size;
        }
    }

    object_delete(family);

    function->bounds.lower = lower;
    function->bounds.upper = upper;

    return 0;
}
コード例 #6
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;
}
コード例 #7
0
int rdis_user_function (struct _rdis * rdis, uint64_t address)
{
    // get a tree of all functions reachable at this address
    struct _map * functions = loader_function_address(rdis->loader,
                                                      rdis->memory,
                                                      address);

    // add in this address as a new function as well
    struct _function * function = function_create(address);
    map_insert(functions, function->address, function);
    object_delete(function);

    // for each newly reachable function
    struct _map_it * mit;
    for (mit = map_iterator(functions); mit != NULL; mit = map_it_next(mit)) {
        struct _function * function = map_it_data(mit);
        uint64_t fitaddress = function->address;

        // if we already have this function, skip it
        if (map_fetch(rdis->functions, function->address) != NULL)
            continue;

        // add this function to the rdis->function_tree
        map_insert(rdis->functions, function->address, function);

        // add label
        struct _label * label = loader_label_address(rdis->loader,
                                                     rdis->memory,
                                                     fitaddress);
        map_insert(rdis->labels, fitaddress, label);
        object_delete(label);

        // if this function is already in our graph, all we need to do is make
        // sure its a separate node and then remove function predecessors
        struct _graph_node * node = graph_fetch_node_max(rdis->graph, fitaddress);
        if (node != NULL) {

            // already a node, remove function predecessors
            if (node->index == address) {
                remove_function_predecessors(rdis->graph, rdis->functions);
                continue;
            }

            // search for instruction with given address
            struct _list    * ins_list = node->data;
            struct _list_it * it;
            for (it = list_iterator(ins_list); it != NULL; it = it->next) {
                struct _ins * ins = it->data;
                // found instruction
                if (ins->address == fitaddress) {
                    // create a new instruction list.
                    // add remaining instructions to new list while removing them from
                    // the current list
                    struct _list * new_ins_list = list_create();
                    while (1) {
                        list_append(new_ins_list, it->data);
                        it = list_remove(ins_list, it);
                        if (it == NULL)
                            break;
                    }
                    // create a new graph node for this new function
                    graph_add_node(rdis->graph, fitaddress, new_ins_list);
                    // all graph successors from old node are added to new node
                    struct _queue   * queue      = queue_create();
                    struct _list    * successors = graph_node_successors(node);
                    struct _list_it * sit;
                    for (sit = list_iterator(successors);
                         sit != NULL;
                         sit = sit->next) {
                        struct _graph_edge * edge = sit->data;
                        graph_add_edge(rdis->graph,
                                       fitaddress,
                                       edge->tail,
                                       edge->data);
                        queue_push(queue, edge);
                    }
                    object_delete(successors);

                    // and removed from old node
                    while (queue->size > 0) {
                        struct _graph_edge * edge = queue_peek(queue);
                        graph_remove_edge(rdis->graph, edge->head, edge->tail);
                        queue_pop(queue);
                    }
                    object_delete(queue);

                    // that was easy
                    break;
                }
            }
            if (it != NULL)
                continue;
        }

        // we need to create a new graph for this node
        struct _graph * graph = loader_graph_address(rdis->loader,
                                                     rdis->memory,
                                                     fitaddress);
        graph_merge(rdis->graph, graph);
        object_delete(graph);
    }

    object_delete(functions);

    rdis_callback(rdis, RDIS_CALLBACK_ALL);

    return 0;
}
コード例 #8
0
ファイル: x8664.c プロジェクト: 0day1day/rdis
void x8664_functions_r (struct _map  * functions,
                        struct _tree * disassembled,
                        uint64_t       address,
                        struct _map  * memory)
{
    ud_t            ud_obj;
    int             continue_disassembling = 1;

    struct _buffer * buffer = map_fetch_max(memory, address);

    if (buffer == NULL)
        return;

    uint64_t base_address   = map_fetch_max_key(memory, address);

    if (base_address + buffer->size < address)
        return;

    uint64_t offset = address - base_address;

    ud_init      (&ud_obj);
    ud_set_mode  (&ud_obj, 64);
    ud_set_syntax(&ud_obj, UD_SYN_INTEL);
    ud_set_input_buffer(&ud_obj, &(buffer->bytes[offset]), buffer->size - offset);

    while (continue_disassembling == 1) {
        size_t bytes_disassembled = ud_disassemble(&ud_obj);
        if (bytes_disassembled == 0) {
            break;
        }

        if (    (ud_obj.mnemonic == UD_Icall)
             && (ud_obj.operand[0].type == UD_OP_JIMM)) {

            uint64_t target_addr = address
                                   + ud_insn_len(&ud_obj)
                                   + udis86_sign_extend_lval(&(ud_obj.operand[0]));

            if (map_fetch(functions, target_addr) == NULL) {
                struct _function * function = function_create(target_addr);
                map_insert(functions, target_addr, function);
                object_delete(function);
            }
        }

        struct _index * index = index_create(address);
        if (tree_fetch(disassembled, index) != NULL) {
            object_delete(index);
            return;
        }
        tree_insert(disassembled, index);
        object_delete(index);

        // these mnemonics cause us to continue disassembly somewhere else
        struct ud_operand * operand;
        switch (ud_obj.mnemonic) {
        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   :
        case UD_Ijmp  :
        case UD_Iloop :
        case UD_Icall :
            operand = &(ud_obj.operand[0]);

            if (operand->type == UD_OP_JIMM) {
                x8664_functions_r(functions,
                                  disassembled,
                                  address
                                   + ud_insn_len(&ud_obj)
                                   + udis86_sign_extend_lval(operand),
                                  memory);
            }
            break;
        default :
            break;
        }

        // these mnemonics cause disassembly to stop
        switch (ud_obj.mnemonic) {
        case UD_Iret :
        case UD_Ihlt :
        case UD_Ijmp :
            continue_disassembling = 0;
            break;
        default :
            break;
        }

        address += bytes_disassembled;
    }
}
コード例 #9
0
ファイル: elf32.c プロジェクト: TDKPS/rdis
struct _map * elf32_functions (struct _elf32 * elf32, struct _map * memory)
{
    struct _list * entries   = list_create();

    // add the entry point
    struct _function * function = function_create(elf32_entry(elf32));
    list_append(entries, function);
    object_delete(function);

    // check for __libc_start_main loader
    uint64_t target_offset = elf32_entry(elf32) - elf32_base_address(elf32) + 0x17;
    if (target_offset + 0x10 < elf32->data_size) {
        uint8_t * data = &(elf32->data[target_offset]);
        size_t    size = elf32->data_size - target_offset;

        ud_t ud_obj;
        ud_init      (&ud_obj);
        ud_set_mode  (&ud_obj, 32);
        ud_set_syntax(&ud_obj, UD_SYN_INTEL);
        ud_set_input_buffer(&ud_obj, data, size);
        ud_disassemble(&ud_obj);
        if (ud_obj.mnemonic == UD_Ipush) {
            printf("found __libc_start_main loader, main at %llx\n",
                   (unsigned long long) udis86_sign_extend_lval(&(ud_obj.operand[0])));

            // add main to function tree
            struct _function * function;
            function = function_create(udis86_sign_extend_lval(&(ud_obj.operand[0])));
            list_append(entries, function);
            object_delete(function);

        }
        else
            printf("disassembled: %s\n disassembled at %llx\n",
                   ud_insn_asm(&ud_obj),
                   (unsigned long long) target_offset);
    }

    struct _map * functions = elf32_functions_wqueue(elf32, memory, entries);

    // these are the reachable functions
    struct _map_it * mit;
    for (mit = map_iterator(functions); mit != NULL; mit = map_it_next(mit)) {
        struct _function * function = map_it_data(mit);
        function->flags |= FUNCTION_REACHABLE;
    }

    // reset entries
    object_delete(entries);
    entries = list_create();

    // symbols are easy
    int sec_i;
    for (sec_i = 0; sec_i < elf32->ehdr->e_shnum; sec_i++) {
        Elf32_Shdr * shdr = elf32_shdr(elf32, sec_i);
        if (shdr == NULL)
            break;

        if ((shdr->sh_type != SHT_SYMTAB) && (shdr->sh_type != SHT_DYNSYM))
            continue;

        int sym_i;
        for (sym_i = 0; sym_i < shdr->sh_size / shdr->sh_entsize; sym_i++) {
            Elf32_Sym * sym = elf32_section_element(elf32, sec_i, sym_i);
            if (sym == NULL)
                break;

            if (ELF32_ST_TYPE(sym->st_info) != STT_FUNC)
                continue;

            if (sym->st_value == 0)
                continue;

            struct _function * function = function_create(sym->st_value);
            list_append(entries, function);
            object_delete(function);
        }
    }

    struct _map * sym_functions = elf32_functions_wqueue(elf32, memory, entries);
    for (mit = map_iterator(sym_functions); mit != NULL; mit = map_it_next(mit)) {
        struct _function * function = map_it_data(mit);
        if (map_fetch(functions, function->address) == NULL)
            map_insert(functions, function->address, function);
    }

    object_delete(sym_functions);
    object_delete(entries);

    return functions;
}
コード例 #10
0
ファイル: redis_x86_graph.c プロジェクト: 0day1day/rdis
struct _graph * redis_x86_graph (uint64_t address, struct _map * memory)
{
    uint64_t next_index = 1;
    uint64_t this_index = 0;
    uint64_t last_index = 0;

    struct _redis_x86 * redis_x86 = redis_x86_create();
    redis_x86_mem_from_mem_map(redis_x86, memory);
    redis_x86->regs[RED_EIP] = address;
    redis_x86_false_stack(redis_x86);

    struct _map * ins_map = map_create();
    struct _graph * graph = graph_create();

    while (redis_x86_step(redis_x86) == REDIS_SUCCESS) {
        uint64_t address = redis_x86->ins_addr;

        // do we have an instruction at this address already?
        struct _index * index = map_fetch(ins_map, address);
        // we have an instruction, fetch it, make sure it matches
        if (index) {
            struct _graph_node * node = graph_fetch_node(graph, index->index);
            struct _ins * ins = list_first(node->data);

            // instructions diverge, create new instruction
            if (    (ins->size != redis_x86->ins_size)
                 || (memcmp(ins->bytes, redis_x86->ins_bytes, redis_x86->ins_size))) {
                ins = redis_x86_create_ins(redis_x86);
                if (ins == NULL) {
                    fprintf(stderr, "could not create ins, eip=%llx\n",
                            (unsigned long long) redis_x86->ins_addr);
                    break;
                }

                struct _list * list = list_create();
                list_append(list, ins);
                object_delete(ins);

                graph_add_node(graph, next_index, list);
                object_delete(list);

                map_remove(ins_map, redis_x86->ins_addr);
                index = index_create(next_index++);
                map_insert(ins_map, redis_x86->ins_addr, index);
                this_index = index->index;
                object_delete(index);
            }
            else
                this_index = index->index;
        }
        // no instruction at this address, create it
        else {
            struct _ins * ins = redis_x86_create_ins(redis_x86);
            if (ins == NULL) {
                fprintf(stderr, "could not create ins eip=%llx\n",
                        (unsigned long long) redis_x86->ins_addr);
                break;
            }
            struct _list * list = list_create();
            list_append(list, ins);
            object_delete(ins);

            graph_add_node(graph, next_index, list);
            object_delete(list);

            index = index_create(next_index++);
            map_insert(ins_map, redis_x86->ins_addr, index);
            this_index = index->index;
            object_delete(index);
        }

        /*
        * create an edge from last index to this index
        * because our graph library enforces both the condition that the head
        * and tail nodes are valid, and that there exists only one edge per
        * head->tail combination, we can blindly add edges here and let the
        * graph library work out the details
        */
        printf("[edge] %llx -> %llx\n",
               (unsigned long long) last_index,
               (unsigned long long) this_index);
        struct _ins_edge * ins_edge = ins_edge_create(INS_EDGE_NORMAL);
        graph_add_edge(graph, last_index, this_index, ins_edge);
        object_delete(ins_edge);
        last_index = this_index;
        printf("%llx -> %llx\n",
               (unsigned long long) last_index,
               (unsigned long long) this_index);
    }

    object_delete(ins_map);
    object_delete(redis_x86);

    return graph;
}
コード例 #11
0
ファイル: recursive_dis.c プロジェクト: TDKPS/rdis2
struct _graph * recursive_disassemble (const struct _map * mem_map,
                                       uint64_t entry,
                struct _ins * (* ins_callback) (const struct _map *, uint64_t))
{
    struct _queue * queue = queue_create();
    struct _map * map     = map_create();

    struct _index * index = index_create(entry);
    queue_push(queue, index);
    object_delete(index);

    while (queue->size > 0) {
        struct _index * index = queue_peek(queue);

        if (map_fetch(map, index->index)) {
            queue_pop(queue);
            continue;
        }

        struct _ins * ins = ins_callback(mem_map, index->index);
        if (ins == NULL) {
            queue_pop(queue);
            continue;
        }
        map_insert(map, index->index, ins);

        struct _list_it * lit;
        for (lit = list_iterator(ins->successors); lit != NULL; lit = lit->next) {
            struct _ins_value * successor = lit->data;
            if (successor->type == INS_SUC_CALL)
                continue;
            struct _index * index = index_create(successor->address);
            queue_push(queue, index);
            object_delete(index);
        }

        queue_pop(queue);
    }

    object_delete(queue);

    // create graph nodes
    struct _graph * graph = graph_create();

    struct _map_it * mit;
    for (mit = map_iterator(map); mit != NULL; mit = map_it_next(mit)) {
        graph_add_node(graph, map_it_key(mit), map_it_data(mit));
    }

    // create graph edges
    for (mit = map_iterator(map); mit != NULL; mit = map_it_next(mit)) {
        struct _ins * ins = map_it_data(mit);
        struct _list_it * lit;
        for (lit = list_iterator(ins->successors); lit != NULL; lit = lit->next) {
            struct _ins_value * successor = lit->data;
            // don't add call edges
            if (successor->type == INS_SUC_CALL)
                continue;
            graph_add_edge(graph, ins->address, successor->address, successor);
        }
    }

    object_delete(map);

    return graph;
}