diff --git a/README.md b/README.md index d8492ae..277f0cc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # libelfmaster +## Update as of 11/17/18 -- I have a local branch with many new fixes that will be finished and committed by the end of December, been very busy. ## Secure ELF parsing library diff --git a/TODO b/TODO index d45477b..f725658 100644 --- a/TODO +++ b/TODO @@ -4,6 +4,13 @@ Fix all parsing bugs in crashes. I have some more fixing and testing to go befor the release tag of this alpha version, so this last commit is not a complete update to the code base, but resolves quite a number of the existing issues. +## Handle SCOP (Secure code partitioning) + +We must determine how functions such as elf_text_base are going to work +when there are multiple LOAD segments in SCOP linked binaries. + +## Merge in Ignacios work for code injection + ## 9/17/2018 Make sure that we take into account dynamic segments that exist in diff --git a/examples/Makefile b/examples/Makefile index 0dd7d43..b614460 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,21 +1,25 @@ +CC=gcc all: - gcc -O2 -g -fPIC -pie elfparse.c ../src/libelfmaster.a -o elfparse - gcc -O3 -g ldd.c ../src/libelfmaster.a -o ldd - gcc -O2 -g read_mem.c ../src/libelfmaster.a -o read_mem - gcc -O2 -g plt_dump.c ../src/libelfmaster.a -o plt_dump - gcc -O2 -g plt_dump2.c ../src/libelfmaster.a -o plt_dump2 - gcc -O2 -g sections.c ../src/libelfmaster.a -o sections - gcc -O0 -ggdb symbols.c ../src/libelfmaster.a -o symbols - gcc -O2 -g eh_frame.c ../src/libelfmaster.a -o eh_frame - gcc -O2 -g checksec.c ../src/libelfmaster.a -o checksec - gcc -O2 -g -fPIC -pie test.c -o test_pie - gcc -O2 -no-pie test.c ../src/libelfmaster.a -o test - gcc -O2 -fPIC -pie test.c ../src/libelfmaster.a -o test2_pie - gcc -O2 -no-pie test.c ../src/libelfmaster.a -o test_stripped - gcc -O2 -no-pie -m32 test.c ../src/libelfmaster.a -o test32bit - gcc -O2 -fPIC -pie -m32 test.c ../src/libelfmaster.a -o test32bit_pie - gcc -no-pie -m32 test.c -o test32_stripped - gcc ../utils/stripx.c -o stripx + $(CC) -O0 -g -fPIC -pie elfparse.c ../src/libelfmaster.a -o elfparse + $(CC) -O0 -g ldd.c ../src/libelfmaster.a -o ldd + $(CC) -O2 -g read_mem.c ../src/libelfmaster.a -o read_mem + $(CC) -O2 -g plt_dump.c ../src/libelfmaster.a -o plt_dump + $(CC) -O2 -g plt_dump2.c ../src/libelfmaster.a -o plt_dump2 + $(CC) -O2 -g sections.c ../src/libelfmaster.a -o sections + $(CC) -O0 -ggdb symbols.c ../src/libelfmaster.a -o symbols + $(CC) -O2 -g eh_frame.c ../src/libelfmaster.a -o eh_frame + $(CC) -O2 -g checksec.c ../src/libelfmaster.a -o checksec + $(CC) -O2 -g -fPIC -pie test.c -o test_pie + $(CC) -O2 -no-pie test.c ../src/libelfmaster.a -o test + $(CC) -O2 -fPIC -pie test.c ../src/libelfmaster.a -o test2_pie + $(CC) -O2 -no-pie test.c ../src/libelfmaster.a -o test_stripped + $(CC) -O2 -no-pie -m32 test.c ../src/libelfmaster.a -o test32bit + $(CC) -O2 -fPIC -pie -m32 test.c ../src/libelfmaster.a -o test32bit_pie + $(CC) -no-pie -m32 test.c -o test32_stripped + $(CC) -m32 -fPIC -pie -Wl,-z,separate-code test.c -o test32_scop + $(CC) -g objdump_libelfmaster.c ../src/libelfmaster.a -o objdump_elfmaster -lcapstone + $(CC) -fPIC -pie -Wl,-z,separate-code,-z,relro,-z,now test.c -o test_scop + $(CC) ../utils/stripx.c -o stripx ./stripx test_stripped ./stripx test32_stripped clean: diff --git a/examples/checksec.c b/examples/checksec.c index b6d9ddd..3d3bf3d 100644 --- a/examples/checksec.c +++ b/examples/checksec.c @@ -31,7 +31,7 @@ int main(int argc, char **argv) struct elf_symbol symbol; elf_linking_type_t link_type; bool dynamic = false, relro = false, strict_linking = false, executable_data = false, - pax = false, writable_text = false, executable_stack = false; + pax = false, writable_text = false, executable_stack = false, scop = false; unsigned int pax_flags; char pax_string[256] = {0}; @@ -48,6 +48,9 @@ int main(int argc, char **argv) printf("%s\n", elf_error_msg(&error)); return -1; } + if (elf_flags(&obj, ELF_SCOP_F) == true) + printf("SCOP (Secure code partitioning) is enabled\n"); + if ((link_type = elf_linking_type(&obj)) == ELF_LINKING_UNDEF) { printf("Object: %s is not an executable or shared library\n", argv[0]); exit(EXIT_SUCCESS); diff --git a/examples/code_injection.c b/examples/code_injection.c new file mode 100644 index 0000000..68deab7 --- /dev/null +++ b/examples/code_injection.c @@ -0,0 +1,95 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../include/libelfmaster.h" +#include "../include/internal.h" + +/* + * Opens a given file and checks if it contains an ELF magic. (More checks can be implemented). + */ +int main (int argc, char **argv) +{ + elfobj_t obj1; + elfobj_t obj2; + elfobj_t objdest; + elf_error_t error; + uint64_t p_address; + uint64_t p_offset; + bool res; + + // http://shell-storm.org/shellcode/files/shellcode-806.php + uint8_t stub[] = "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48" \ + "\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05"; + + if (argc != 3) { + printf("Usage: %s \n", argv[0]); + exit(EXIT_SUCCESS); + } + if (elf_open_object(argv[1], &obj1, ELF_LOAD_F_STRICT, &error) == false) { + fprintf(stderr, "%s\n", elf_error_msg(&error)); + return -1; + } + /* + * In case the binary payload is residing in disk, we can use these functions to load + * it, as if it was an ELF file or some binary blob. + * + if (elf_has_header(argv[2], &res, &error) == false) { + fprintf(stderr, "%s\n", elf_error_msg(&error)); + return -1; + } + if (res) { + if (elf_open_object(argv[2], &obj2, ELF_LOAD_F_STRICT, &error) == false) { + fprintf(stderr, "%s\n", elf_error_msg(&error)); + return -1; + } + } else { + if (elf_open_stub(argv[2], &obj2, &error) == false) { + fprintf(stderr, "%s\n", elf_error_msg(&error)); + return -1; + } + } + * Otherwise stubs can be also operated as byte-arrays. + */ + + if (elf_init_stub(&obj2, stub, sizeof(stub), &error) == false) { + fprintf(stderr, "%s\n", elf_error_msg(&error)); + return -1; + } + if (elf_create_object(argv[2], &objdest, &obj1, obj1.size + obj2.size, + ELF_LOAD_F_STRICT, &error) == false) { + fprintf(stderr, "%s\n", elf_error_msg(&error)); + return -1; + } + if (elf_inject_code(&objdest, &obj2, &p_offset, ELF_INJECT_F_POSTPEND, &error) == false) { + fprintf(stderr, "%s\n", elf_error_msg(&error)); + return -1; + } + if(internal_offset_to_address(&objdest, p_offset, &p_address, &error) == false) { + fprintf(stderr, "%s\n", elf_error_msg(&error)); + return -1; + } + printf("Payload written at offset: 0x%lx, address: 0x%lx\n", p_offset, p_address); + + if (elf_commit_object(&objdest, objdest.size, 0, &error) == false) { + fprintf(stderr, "%s\n", elf_error_msg(&error)); + return -1; + } + return 0; +} diff --git a/examples/elfparse.c b/examples/elfparse.c index 42b95aa..db19e8c 100644 --- a/examples/elfparse.c +++ b/examples/elfparse.c @@ -33,6 +33,7 @@ int main(int argc, char **argv) struct elf_shared_object_iterator so_iter; struct timeval tv, tv2; unsigned int count = 0; + bool scop = false; if (elf_open_object(argv[1], &obj, ELF_LOAD_F_FORENSICS, &error) == false) { @@ -76,6 +77,10 @@ int main(int argc, char **argv) elf_segment_iterator_init(&obj, &p_iter); while (elf_segment_iterator_next(&p_iter, &segment) == ELF_ITER_OK) { + if (elf_flags(&obj, ELF_SCOP_F) == true && scop == false) { + printf("SCOP enabled\n"); + scop = true; + } printf("\nAddr: %#lx\n", segment.vaddr); printf("Filesz: %#lx\n", segment.filesz); printf("MemSz: %#lx\n", segment.memsz); diff --git a/examples/objdump_libelfmaster.c b/examples/objdump_libelfmaster.c new file mode 100644 index 0000000..c9d434b --- /dev/null +++ b/examples/objdump_libelfmaster.c @@ -0,0 +1,81 @@ +/* + * NOTE Very quick prototype does not take section header sh_align + * into consideration so it sometimes shows the wrong instructions + * on section borders. Also without some tweaking capstone won't + * show sections that have non-code, so we only get several contiguous + * sections of code disassembled + */ + +#define _GNU_SOURCE +#include +#include + +#include "../include/libelfmaster.h" +#include + +int main(int argc, char **argv) +{ + csh handle; + cs_insn *insn; + size_t count; + elfobj_t obj; + elf_error_t error; + struct elf_section section; + elf_section_iterator_t s_iter; + uint64_t base_vaddr, base_offset; + size_t len; + uint8_t *ptr; + int i; + + if (argc < 2) { + printf("Usage: %s \n", argv[0]); + exit(EXIT_SUCCESS); + } + if (elf_open_object(argv[1], &obj, ELF_LOAD_F_FORENSICS, &error) == false) { + fprintf(stderr, "%s\n", elf_error_msg(&error)); + return -1; + } + elf_section_iterator_init(&obj, &s_iter); + while (elf_section_iterator_next(&s_iter, §ion) == ELF_ITER_OK) { + if (strcmp(section.name, ".init") == 0) { + base_vaddr = section.address; + base_offset = section.offset; + break; + } + } + len = elf_text_filesz(&obj) + elf_data_filesz(&obj); + ptr = elf_offset_pointer(&obj, base_offset); + if (ptr == NULL) { + printf("Unable to get offset: %lx\n", base_offset); + return -1; + } + if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle) != CS_ERR_OK) + return -1; + + printf("Disassembling %lu bytes\n", len - base_offset); + count = cs_disasm(handle, ptr, len - base_offset, base_vaddr, base_offset, &insn); + if (count > 0) { + size_t j; + bool checked = false; + for (j = 0; j < count; j++) { + char *sname = ".unknown"; + char *symname = "sub_unknown"; + struct elf_symbol symbol; + + if (elf_symbol_by_value(&obj, insn[j].address, &symbol) == true) + symname = symbol.name; + + if (elf_section_by_address(&obj, insn[j].address, §ion) == true) + sname = section.name; + + printf("%s:%s:0x%"PRIx64":\t%s\t\t%s\n", section.name, symname, + insn[j].address, insn[j].mnemonic, + insn[j].op_str); + } + cs_free(insn, count); + } else + printf("ERROR: Failed to disassemble given code!\n"); + cs_close(&handle); + + return 0; +} diff --git a/examples/pltgot.c b/examples/pltgot.c index a0b8b14..96ec466 100644 --- a/examples/pltgot.c +++ b/examples/pltgot.c @@ -17,7 +17,7 @@ int main(int argc, char **argv) elfobj_t obj; elf_error_t error; elf_pltgot_iterator_t pltgot_iter; - struct elf_pltgot pltgot; + struct elf_pltgot_entry pltgot; if (argc < 2) { printf("Usage: %s \n", argv[0]); diff --git a/examples/symbols.c b/examples/symbols.c index 264fdf5..71727fe 100644 --- a/examples/symbols.c +++ b/examples/symbols.c @@ -23,7 +23,7 @@ int main(int argc, char **argv) exit(EXIT_SUCCESS); } if (elf_open_object(argv[1], &obj, - ELF_LOAD_F_SMART|ELF_LOAD_F_FORENSICS, &error) == false) { + ELF_LOAD_F_STRICT, &error) == false) { fprintf(stderr, "%s\n", elf_error_msg(&error)); return -1; } diff --git a/include/internal.h b/include/internal.h index b6b5da5..dbd2426 100644 --- a/include/internal.h +++ b/include/internal.h @@ -197,7 +197,9 @@ void free_arrays(elfobj_t *); void free_misc(elfobj_t *); -bool insane_headers(elfobj_t *); +bool insane_section_headers(elfobj_t *); + +bool insane_dynamic_segment(elfobj_t *); bool reconstruct_elf_sections(elfobj_t *, elf_error_t *); diff --git a/include/libelfmaster.h b/include/libelfmaster.h index ddf8d9d..56fb9c2 100644 --- a/include/libelfmaster.h +++ b/include/libelfmaster.h @@ -40,9 +40,17 @@ #define MAX_ERROR_STR_LEN 128 /* - * In reality will never exceed 2,3, or 4 at the highest. + * DT_PLTREL tag has two valid + * values, 0x7 and 0x11 */ -#define MAX_LOADABLE_MAPPINGS 8 +#define ELF_DT_PLTREL_RELA 0x7 +#define ELF_DT_PLTREL_REL 0x11 + +/* + * In reality will never exceed 2,3, or 4 at the highest + * i.e. 4 PT_LOAD with SCOP (secure code partitioning) + */ +#define MAX_LOADABLE_MAPPINGS 12 #define ELFNOTE_NAME(_n_) ((unsigned char*)(_n_) + sizeof(*(_n_))) #define ELFNOTE_ALIGN(_n_) (((_n_)+3)&~3) @@ -106,7 +114,8 @@ typedef enum elf_obj_flags { ELF_FULL_PIE_F = (1 << 14), /* fully relocatable ET_DYN */ ELF_SYMTAB_RECONSTRUCTION_F = (1 << 15), /* .symtab is being reconstructed */ ELF_FORENSICS_F = (1 << 16), /* elf sections at the least are reconstructed */ - ELF_DT_DEBUG_F = (1 << 17) + ELF_DT_DEBUG_F = (1 << 17), + ELF_SCOP_F = (1 << 18) /* secure code partitioning */ } elf_obj_flags_t; /* @@ -192,6 +201,10 @@ struct pt_load { uint32_t flag; }; +/* + * TODO + * Move the anomaly values to internal.h. + */ /* * Flags for anomalies on section headers */ @@ -202,6 +215,12 @@ struct pt_load { #define INVALID_F_SHENTSIZE (1ULL << 4) #define INVALID_F_SH_HEADERS (1ULL << 5) #define INVALID_F_SHSTRTAB (1ULL << 6) + +/* + * Flags for anomalies on dynamic segment + */ +#define INVALID_F_VITAL_DTAG_VALUE (1ULL << 7) + /* * This struct is not meant to access directly. It is an opaque * type. It is only accessed directly from within the API code @@ -256,6 +275,9 @@ typedef struct elfobj { #define ELF_PT_LOAD_TEXT_F (1 << 0) #define ELF_PT_LOAD_DATA_F (1 << 1) #define ELF_PT_LOAD_MISC_F (1 << 2) + /* Handle SCOP cases */ +#define ELF_PT_LOAD_TEXT_RDONLY_F (1 << 3) + struct pt_load *pt_load; size_t load_count; /* @@ -295,6 +317,9 @@ typedef struct elfobj { struct { uint64_t size; } relent; + struct { + uint64_t size; + } relaent; struct { uint64_t addr; uint64_t size; @@ -498,6 +523,7 @@ typedef struct elf_shared_object_iterator { //if the section header tables and symbols are missing or are corrupted. #define ELF_LOAD_F_MODIFY (1UL << 3) //Used for modifying binaries #define ELF_LOAD_F_ULEXEC (1UL << 4) //Used for ulexec based debugging API +#define ELF_LOAD_F_MAP_WRITE (1UL << 5) /* * Loads an ELF object of any type, for reading or modifying. @@ -567,6 +593,7 @@ bool elf_plt_by_name(elfobj_t *, const char *, struct elf_plt *); uint64_t elf_entry_point(elfobj_t *); uint32_t elf_type(elfobj_t *); +size_t elf_size(elfobj_t *); uint16_t elf_machine(elfobj_t *); bool elf_map_loadable_segments(elfobj_t *, struct elf_mapping *, elf_error_t *); @@ -578,6 +605,8 @@ bool elf_symbol_by_name(elfobj_t *, const char *, struct elf_symbol *); bool elf_symbol_by_index(elfobj_t *, unsigned int, struct elf_symbol *, const int); +bool elf_symbol_by_value(elfobj_t *, uint64_t, struct elf_symbol *); + /* * Return a pointer to an offset into the memory mapped ELF file. */ @@ -592,6 +621,10 @@ void * elf_offset_pointer(elfobj_t *, uint64_t); */ void * elf_section_pointer(elfobj_t *, void *); +/* + * ELF section by address + */ +bool elf_section_by_address(elfobj_t *, uint64_t, struct elf_section *); /* * Success: returns section name * failure: returns NULL diff --git a/libelfmaster_talk_hushcon.odp b/libelfmaster_talk_hushcon.odp new file mode 100644 index 0000000..b8de688 Binary files /dev/null and b/libelfmaster_talk_hushcon.odp differ diff --git a/libelfmaster_talk_hushcon.pdf b/libelfmaster_talk_hushcon.pdf new file mode 100644 index 0000000..fcfb66a Binary files /dev/null and b/libelfmaster_talk_hushcon.pdf differ diff --git a/src/internal.c b/src/internal.c index a93df92..7640e83 100644 --- a/src/internal.c +++ b/src/internal.c @@ -189,6 +189,19 @@ build_dynsym_data(struct elfobj *obj) return true; } +static bool +sanity_check_st_name(struct elfobj *obj, size_t offset) +{ + + (void)obj; + (void)offset; + + /* + * XXX TODO + */ + return true; +} + bool build_symtab_data(struct elfobj *obj) { @@ -207,7 +220,7 @@ build_symtab_data(struct elfobj *obj) * that correspond to each FDE within .eh_frame. */ if ((obj->load_flags & ELF_LOAD_F_FORENSICS) && - insane_headers(obj) == true) { + insane_section_headers(obj) == true) { struct elf_symbol_node *symbol; struct elf_eh_frame fde; elf_eh_frame_iterator_t eh_iter; @@ -255,8 +268,27 @@ build_symtab_data(struct elfobj *obj) switch(obj->e_class) { case elfclass32: + /* + * NOTE: + * libelfmaster takes the position of assigning symbol names + * to symbols with out of bounds st_name, that will denote that + * there is an issue with the symbol->st_name string table index. + */ symtab32 = obj->symtab32; - symbol->name = &obj->strtab[symtab32[i].st_name]; + if (elf_type(obj) == ET_REL) { + if (symtab32[i].st_name < elf_size(obj)) { + symbol->name = &obj->strtab[symtab32[i].st_name]; + } else { + symbol->name = "invalid_name_index"; + } + } else if (elf_type(obj) == ET_DYN || elf_type(obj) == ET_EXEC) { + if (symtab32[i].st_name < elf_data_offset(obj) + + elf_data_filesz(obj)) { + symbol->name = &obj->strtab[symtab32[i].st_name]; + } else { + symbol->name = "invalid_name_index"; + } + } symbol->value = symtab32[i].st_value; symbol->shndx = symtab32[i].st_shndx; symbol->size = symtab32[i].st_size; @@ -266,7 +298,18 @@ build_symtab_data(struct elfobj *obj) break; case elfclass64: symtab64 = obj->symtab64; - symbol->name = &obj->strtab[symtab64[i].st_name]; + if (elf_type(obj) == ET_REL) { + if (symtab64[i].st_name < elf_size(obj)) { + symbol->name = &obj->strtab[symtab64[i].st_name]; + } else { + symbol->name = "invalid_name_index"; + } + } else if (elf_type(obj) == ET_DYN || elf_type(obj) == ET_EXEC) { + if (sanity_check_st_name(obj, symtab64[i].st_name) == true) + symbol->name = &obj->strtab[symtab64[i].st_name]; + else + symbol->name = "invalid_name_index"; + } symbol->value = symtab64[i].st_value; symbol->shndx = symtab64[i].st_shndx; symbol->size = symtab64[i].st_size; @@ -583,40 +626,55 @@ load_dynamic_segment_data(struct elfobj *obj) uint32_t dt_pltgot = 0, dt_pltrelsz = 0, dt_symtab = 0, dt_strtab = 0, dt_strsz = 0, dt_hash = 0, dt_pltrel = 0, dt_jmprel = 0, dt_rela = 0, dt_relasz = 0, dt_rel = 0, dt_relsz = 0, - dt_fini = 0, dt_init = 0, dt_relent = 0, dt_init_array = 0, dt_init_arraysz = 0, + dt_fini = 0, dt_init = 0, dt_relent = 0, dt_relaent = 0, + dt_init_array = 0, dt_init_arraysz = 0, dt_fini_array = 0, dt_fini_arraysz = 0, dt_debug = 0; - + uint32_t ptr_width = elf_class(obj) == elfclass32 ? 4 : 8; /* * If the ELF object has no section headers, then .dynstr won't be set * yet, and elf_dynamic_string() will fail. So before we use the * dynamic iterator to set all dynamic segment values, we must first * manually find the location of dynstr and set it. Its somewhat - * redundant, but its a quick and simple fix. + * redundant, but its a quick and simple fix. After that we can + * call elf_dynamic_string() as necessary. */ elf_dynamic_iterator_init(obj, &iter); for (;;) { res = elf_dynamic_iterator_next(&iter, &entry); if (res == ELF_ITER_DONE) break; - if (res == ELF_ITER_ERROR) + if (res == ELF_ITER_ERROR) { + fprintf(stderr, "Initial iteration over dynamic segment failed\n"); return false; + } if (entry.tag != DT_STRTAB) continue; /* - * TODO: - * In later versions we should handle anomalies where .dynstr + * we must handle anomalies where .dynstr * is not stored in the text segment. I've seen this before * with strange linker script configs where .dynstr is writable * and in the data segment. For now return false if .dynstr is * not in the text segment and we are performing forensics - * reconstruction. + * reconstruction. We must also adjust elf_data_base and elf_text_base + * to account for SCOP binaries. */ if (entry.value >= - elf_text_base(obj) + obj->text_segment_filesz) - return false; + elf_text_base(obj) + elf_text_filesz(obj)) { + if (entry.value >= elf_data_base(obj) && + entry.value < elf_data_base(obj) + elf_data_filesz(obj)) { + obj->dynstr = (char *)&obj->mem[entry.value - + elf_data_base(obj)]; + if (obj->dynstr == NULL) + return false; + } else { + fprintf(stderr, + ".dynstr points outside of text and data segment\n"); + return false; + } + } obj->dynstr = (char *)&obj->mem[entry.value - elf_text_base(obj)]; if (obj->dynstr == NULL) - return NULL; + return false; } LIST_INIT(&obj->list.shared_objects); elf_dynamic_iterator_init(obj, &iter); @@ -624,93 +682,213 @@ load_dynamic_segment_data(struct elfobj *obj) res = elf_dynamic_iterator_next(&iter, &entry); if (res == ELF_ITER_DONE) return true; - if (res == ELF_ITER_ERROR) + if (res == ELF_ITER_ERROR) { + fprintf(stderr, "Second iteration over dynamic segment failed\n"); return false; + } obj->dynseg.exists = true; /* * SECURITY: Some of these tags are expected more - * than once + * than once: * like DT_NEEDED. But an attacker who wants to * circumvent our reconstruction could put two * DT_PLTGOT tags for instance and we would save * the second one as the PLT/GOT address, and it * could be bunk. So lets make sure there's only - * one of each unless it expected otherwise. + * one of each unless it expected otherwise (such as NEEDED) * Eventually lets make sure to do further validation - * i.e. does the pltgot.addr even point to a valid - * location? (i.e. is it in the data segment) + * + * SECURITY TODO: Currently we do boundary checks on each value + * and make sure that certain vital values are sane. This + * is imperative for forensics reconstruction. There is a + * fundamental problem with our approach that needs to be + * addressed later on. We are assuming that these tags point + * to values either in the traditional text segment or the + * traditional data segment. Consider a scenario where the + * DT_PLTGOT is in a loadable segment that is not determined + * to be the data segment, yet we are using elf_data_base(obj) + * to calculate sanity checks. This is important since we + * need to be able to reconstruct the data segment, however + * we may advance our technique in the future to support + * reconstruction, even if a given tag value points to a + * non-traditional memory range, as long as that segment + * permissions are in alignment with the dynamic tag value + * then we could respect it. This enhancement will ultimately + * be spec'd out and designed properly and documented based + * on more analysis and samples. */ switch(entry.tag) { case DT_PLTGOT: if (dt_pltgot++ > 0) break; + if (obj->dynseg.pltgot.addr < elf_data_base(obj) || + obj->dynseg.pltgot.addr > elf_data_base(obj) + + elf_data_filesz(obj) - ptr_width - 1) { + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + } obj->dynseg.pltgot.addr = entry.value; break; case DT_PLTRELSZ: if (dt_pltrelsz++ > 0) break; + if (entry.value > obj->size - 1) + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; obj->dynseg.pltrel.size = entry.value; break; case DT_SYMTAB: if (dt_symtab++ > 0) break; + if (entry.value < elf_text_base(obj) || + entry.value > elf_text_base(obj) + + elf_text_filesz(obj) - ptr_width - 1) { + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + } obj->dynseg.dynsym.addr = entry.value; break; case DT_STRTAB: if (dt_strtab++ > 0) break; + if (entry.value < elf_text_base(obj) || + entry.value > elf_text_base(obj) + + elf_text_filesz(obj) - 1) { + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + } obj->dynseg.dynstr.addr = entry.value; break; case DT_STRSZ: if (dt_strsz++ > 0) break; + if (entry.value >= obj->size) + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; obj->dynseg.dynstr.size = entry.value; break; case DT_HASH: case DT_GNU_HASH: if (dt_hash++ > 0) break; + if (entry.value < elf_text_base(obj) || + entry.value > elf_text_base(obj) + + elf_text_filesz(obj) - ptr_width - 1) { + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + } obj->dynseg.hash.addr = entry.value; break; case DT_PLTREL: if (dt_pltrel++ > 0) break; + if (entry.value != ELF_DT_PLTREL_RELA && + entry.value != ELF_DT_PLTREL_RELA) { + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + } obj->flags |= ELF_PLT_RELOCS_F; obj->dynseg.pltrel.type = entry.value; break; case DT_JMPREL: if (dt_jmprel++ > 0) break; + if (entry.value < elf_text_base(obj) || + entry.value > elf_text_base(obj) + + elf_text_filesz(obj) - ptr_width - 1) { + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + } obj->dynseg.pltrel.addr = entry.value; break; case DT_RELA: if (dt_rela++ > 0) break; + if (entry.value < elf_text_base(obj) || + entry.value > elf_text_base(obj) + + elf_text_filesz(obj) - ptr_width - 1) { + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + } obj->dynseg.rela.addr = entry.value; break; case DT_RELASZ: if (dt_relasz++ > 0) break; + /* + * If we haven't hit DT_RELA yet, then we + * cannot properly calculate an invalid size + * since we won't have the exact location + * of the relocation section yet. In that + * case we do an approximation of whether the + * size is 'likely' or 'approximately' sane + */ + if (obj->dynseg.rela.addr == 0) { + /* + * Approximate check + */ + if (entry.value > elf_text_offset(obj) + + elf_text_filesz(obj) - 1) { + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + } + } else { + if (obj->dynseg.rela.addr + entry.value > + elf_text_base(obj) + elf_text_filesz(obj) - 1) { + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + } + } obj->dynseg.rela.size = entry.value; break; case DT_REL: if (dt_rel++ > 0) break; + if (entry.value < elf_text_base(obj) || + entry.value > elf_text_base(obj) + + elf_text_filesz(obj) - ptr_width - 1) { + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + } obj->dynseg.rel.addr = entry.value; break; case DT_RELSZ: if (dt_relsz++ > 0) break; + /* + * Same logic as how we handle DT_RELASZ, read + * comments in case DT_RELASZ + */ + if (obj->dynseg.rela.addr == 0) { + /* + * Approximate check + */ + if (entry.value > elf_text_offset(obj) + + elf_text_filesz(obj) - 1) { + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + } + } else { + if (obj->dynseg.rel.addr + entry.value > + elf_text_base(obj) + elf_text_filesz(obj) - 1) { + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + } + } obj->dynseg.rel.size = entry.value; break; case DT_INIT: if (dt_init++ > 0) break; + /* + * Approximate guess since we don't yet know the + * size of .init + */ + if (entry.value < elf_text_base(obj) || + entry.value > elf_text_base(obj) + + elf_text_filesz(obj) - 1) { + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + } obj->dynseg.init.addr = entry.value; break; case DT_FINI: if (dt_fini++ > 0) break; + /* + * Approximate guess since we don't yet know the + * size of .fini + */ + if (entry.value < elf_text_base(obj) || + entry.value > elf_text_base(obj) + + elf_text_filesz(obj) - 1) { + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + } obj->dynseg.fini.addr = entry.value; break; case DT_NEEDED: @@ -722,25 +900,71 @@ load_dynamic_segment_data(struct elfobj *obj) return false; so->index++; so->basename = elf_dynamic_string(obj, entry.value); + if (so->basename == NULL) { + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + free(so); + break; + } LIST_INSERT_HEAD(&obj->list.shared_objects, so, _linkage); break; case DT_RELAENT: + if (dt_relaent++ > 0) + break; + if (elf_class(obj) == elfclass32) { + if (entry.value != sizeof(Elf32_Rela)) + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + } else if (elf_class(obj) == elfclass64) { + if (entry.value != sizeof(Elf64_Rela)) + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + } + obj->dynseg.relaent.size = entry.value; + break; case DT_RELENT: + /* + * At this point DT_RELENT and DT_RELAENT are not + * necessarily vital for forensics reconstruction we may want + * to take the anomaly checks out for these. + */ if (dt_relent++ > 0) break; + if (elf_class(obj) == elfclass32) { + if (entry.value != sizeof(Elf32_Rel)) + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + } else if (elf_class(obj) == elfclass64) { + if (entry.value != sizeof(Elf64_Rel)) + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + } obj->dynseg.relent.size = entry.value; break; case DT_INIT_ARRAY: if (dt_init_array++ > 0) break; + if (entry.value < elf_data_base(obj) || + entry.value > elf_data_base(obj) + + elf_data_filesz(obj) - ptr_width - 1) { + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + } obj->dynseg.init_array.addr = entry.value; break; case DT_FINI_ARRAY: if (dt_fini_array++ > 0) break; + /* + * note to self: approximate guess here as well + * since usually DT_FINI_ARRAY comes before DT_INIT_ARRAY + */ + if (entry.value < elf_data_base(obj) || + entry.value > elf_data_base(obj) + + elf_data_filesz(obj) - ptr_width - 1) { + obj->anomalies |= INVALID_F_VITAL_DTAG_VALUE; + } obj->dynseg.fini_array.addr = entry.value; break; + /* + * TODO put in anomaly checks for these to make sure + * they are valid for reconstruction. + */ case DT_INIT_ARRAYSZ: if (dt_init_arraysz++ > 0) break; @@ -750,13 +974,22 @@ load_dynamic_segment_data(struct elfobj *obj) if (dt_fini_arraysz++ > 0) break; obj->dynseg.fini_array.size = entry.value; - break; + break; case DT_RPATH: + /* + * TODO we must get the runpath for + * supporting these types of .so path + * lookups. Also $ORIGIN expansion support + * is a must as it is actually used in + * a number of important ELF applications + * that I've seen. + */ case DT_RUNPATH: + break; case DT_DEBUG: if (dt_debug++ > 0) break; - obj->dynseg.debug.value = 0; + obj->dynseg.debug.value = entry.value; obj->flags |= ELF_DT_DEBUG_F; break; default: @@ -768,6 +1001,7 @@ load_dynamic_segment_data(struct elfobj *obj) void free_misc(elfobj_t *obj) { + if (elf_flags(obj, ELF_FORENSICS_F) == true) { free(obj->shstrtab); switch(obj->e_class) { @@ -859,10 +1093,33 @@ free_arrays(elfobj_t *obj) } bool -insane_headers(elfobj_t *obj) +insane_section_headers(elfobj_t *obj) +{ + + if (obj->anomalies & INVALID_F_SHOFF) + return true; + if (obj->anomalies & INVALID_F_SHSTRNDX) + return true; + if (obj->anomalies & INVALID_F_SHOFFSET) + return true; + if (obj->anomalies & INVALID_F_SHNUM) + return true; + if (obj->anomalies & INVALID_F_SHENTSIZE) + return true; + if (obj->anomalies & INVALID_F_SH_HEADERS) + return true; + if (obj->anomalies & INVALID_F_SHSTRTAB) + return true; + return false; +} + +bool +insane_dynamic_segment(elfobj_t *obj) { - return (obj->anomalies > 0); + if (obj->anomalies & INVALID_F_VITAL_DTAG_VALUE) + return true; + return false; } /* @@ -933,20 +1190,19 @@ resolve_plt_addr(elfobj_t *obj) * for the indirect GOT jump won't be using IP relative addressing. */ for (marker = inst = &obj->mem[init_offset]; inst; inst++, i++) { - if (*inst != 0x48 && *(inst + 1) != 0x83) - continue; if (inst - marker > INIT_SIZE_THRESHOLD) return 0; + if (*inst != 0x48 && *(inst + 1) != 0x83) + continue; for (;; inst++) { if (*inst == 0xc3) { for (;; inst++) { + if (inst - marker > INIT_SIZE_THRESHOLD) + return 0; if (*inst == 0xff && *(inst + 1) == 0x35) { return (uint64_t)((uint8_t *)inst - (uint8_t *)marker) + obj->dynseg.init.addr; } - if (inst - marker > INIT_SIZE_THRESHOLD) { - return 0; - } } } if (inst - marker > INIT_SIZE_THRESHOLD) @@ -956,14 +1212,14 @@ resolve_plt_addr(elfobj_t *obj) return 0; i386: for (marker = inst = &obj->mem[init_offset + start]; inst; inst++, i++) { + if (inst - marker > INIT_SIZE_THRESHOLD) + return 0; if (*inst != 0x5b) /* pop %ebx */ continue; if (*(inst + 1) == 0xc3) { /* ret */ return (uint64_t)((uint8_t *)inst - (uint8_t *)marker) + obj->dynseg.init.addr; } - if (inst - marker > INIT_SIZE_THRESHOLD) - return 0; } return 0; } @@ -973,6 +1229,11 @@ resolve_plt_addr(elfobj_t *obj) * so lets locate the beginning of the text segment and search * from there since we are looking for the _start glibc init code * and if we can't find it we create a section called .text_segment + * We return 0 on failure, since 0 will never be a valid entry point + * address due to the fact that there must always be an ELF file header + * first. Even in a heavily modified binary (i.e. a virus infected file) + * the smallest entry address would be 0x41, assuming the program header + * table was shifted forward, such as in a reverse text infection. */ #define GLIBC_START_CODE_64 "\x55\x48\x89\xe5\x48" /* enough to identify _start */ #define GLIBC_START_CODE_64_v2 "\x31\xed\x49\x89\xd1" /* enough to identify _start */ @@ -985,6 +1246,8 @@ original_ep(elfobj_t *obj) size_t i; for (i = 0, marker = inst = ptr; inst; inst++, i++) { + if (i >= (elf_text_offset(obj) + elf_text_filesz(obj) - 6)) + return 0; if (obj->arch == x64) { if (memcmp(&inst[i], GLIBC_START_CODE_64, sizeof(GLIBC_START_CODE_64) - 1) == 0) @@ -1500,8 +1763,8 @@ reconstruct_elf_sections(elfobj_t *obj, elf_error_t *e) return elf_error_set(e, ".plt", &soffset); } elf.shdr64.sh_addr = resolve_plt_addr(obj); - if (obj->dynseg.pltrel.size != 0 && obj->dynseg.relent.size != 0) - relaplt_count = obj->dynseg.pltrel.size / obj->dynseg.relent.size; + if (obj->dynseg.pltrel.size != 0 && obj->dynseg.relaent.size != 0) + relaplt_count = obj->dynseg.pltrel.size / obj->dynseg.relaent.size; relaplt_size = relaplt_count * 16; elf.shdr64.sh_size = relaplt_size; elf.shdr64.sh_size += 16; @@ -1519,7 +1782,7 @@ reconstruct_elf_sections(elfobj_t *obj, elf_error_t *e) /* * .rel[a].plt (Necessary for plt iterators) */ - sname = obj->dynseg.relent.size == RELA_ENT_SIZE ? ".rela.plt" : + sname = obj->dynseg.relaent.size == RELA_ENT_SIZE ? ".rela.plt" : "rel.plt"; if (add_shstrtab_entry(obj, sname, &soffset) == false) { return elf_error_set(e, "add_shstrtab_entry failed"); @@ -1529,9 +1792,9 @@ reconstruct_elf_sections(elfobj_t *obj, elf_error_t *e) elf.shdr64.sh_link = dynsym_index; elf.shdr64.sh_offset = obj->dynseg.pltrel.addr - elf_text_base(obj); elf.shdr64.sh_info = gotplt_index; - elf.shdr64.sh_entsize = obj->dynseg.relent.size; + elf.shdr64.sh_entsize = obj->dynseg.relaent.size; elf.shdr64.sh_name = soffset; - elf.shdr64.sh_type = obj->dynseg.relent.size == RELA_ENT_SIZE + elf.shdr64.sh_type = obj->dynseg.relaent.size == RELA_ENT_SIZE ? SHT_RELA : SHT_REL; total_sh_offset_len += elf.shdr64.sh_size; @@ -1831,28 +2094,15 @@ dw_read_location(elfobj_t *obj, uint64_t vaddr, size_t len, { uint8_t *ptr = NULL; - if (vaddr >= obj->text_address + obj->size) { + ptr = elf_address_pointer(obj, vaddr); + if (ptr == NULL) { *res = false; return 0; } - if (vaddr >= obj->text_address + obj->text_segment_filesz) { - ptr = &obj->mem[vaddr - obj->data_address]; - } else { - ptr = &obj->mem[vaddr - obj->text_address]; - } *res = true; if (ev != NULL) { - if (vaddr >= obj->text_address + obj->text_segment_filesz) { - ev->initial_loc = - *(uint32_t *)&obj->mem[vaddr - obj->data_address]; - ev->fde_entry_offset = - *(uint32_t *)&obj->mem[vaddr - obj->data_address + 4]; - } else { - ev->initial_loc = - *(uint32_t *)&obj->mem[vaddr - obj->text_address]; - ev->fde_entry_offset = - *(uint32_t *)&obj->mem[vaddr - obj->text_address + 4]; - } + ev->initial_loc = *(uint32_t *)ptr; + ev->fde_entry_offset = *(uint32_t *)&ptr[4]; return 0; } switch(len) { @@ -1901,7 +2151,7 @@ dw_decode_pointer(elfobj_t *obj, uint8_t encoding_byte, } encoding; int value_size; - bool res; + bool res = false; uint64_t text_section_vaddr; struct elf_section shdr; @@ -2079,3 +2329,69 @@ phdr_sanity(elfobj_t *obj, void *phdr) } return true; } +/* + * Returns the RVA of a given address + */ +uint64_t +internal_address_to_rva(struct elfobj *obj, uint64_t address) +{ + return address - obj->text_address; +} + +/* + * Returns segment virtual address delta to its disk offset. Implemented to handle segment + * alignment properlly. + */ +uint64_t +internal_segment_offset_delta(struct elfobj *obj, struct elf_segment *segment) +{ + return segment->offset - internal_address_to_rva(obj, segment->vaddr); +} + +/* + * Translates a given offset to its equivalent address for a given elfobj_t instance. + */ +bool +internal_offset_to_address(struct elfobj *obj, uint64_t offset, uint64_t *address, elf_error_t *error) +{ + elf_segment_iterator_t p_iter; + struct elf_segment segment; + + elf_segment_iterator_init(obj, &p_iter); + while (elf_segment_iterator_next(&p_iter, &segment) == ELF_ITER_OK) { + if(segment.type == PT_LOAD) { + if(offset >= segment.offset && + offset < segment.offset + segment.filesz) { + *address = (offset + (segment.vaddr - segment.offset)); + return true; + } + } + } + elf_error_set(error, "Offset 0x%x not found in any segment for the provided elfobj_t instance", offset); + return false; +} + +/* + * Translates a given address to its equivalent offset for a given elfobj_t instance. + */ +bool +internal_address_to_offset(struct elfobj *obj, uint64_t address, uint64_t *offset, elf_error_t *error) +{ + elf_segment_iterator_t p_iter; + struct elf_segment segment; + + elf_segment_iterator_init(obj, &p_iter); + while (elf_segment_iterator_next(&p_iter, &segment) == ELF_ITER_OK) { + if (segment.type == PT_LOAD) { + if (segment.vaddr <= address && + address < segment.vaddr + segment.memsz) { + *offset = (internal_address_to_rva(obj, address) + + internal_segment_offset_delta(obj, &segment)); + return true; + } + } + } + elf_error_set(error, "Address 0x%x not found in any segment for the provided elfobj_t instance", address); + return false; +} + diff --git a/src/libelfmaster.c b/src/libelfmaster.c index e12f6cb..05e9a48 100644 --- a/src/libelfmaster.c +++ b/src/libelfmaster.c @@ -271,8 +271,10 @@ elf_reloc_type_string(struct elfobj *obj, uint32_t r_type) return "R_386_GOTOFF"; case R_386_GOTPC: return "R_386_GOTPC"; +#ifdef __linux__ case R_386_32PLT: return "R_386_32PLT"; +#endif case R_386_TLS_TPOFF: return "R_386_TLS_TPOFF"; case R_386_TLS_LE: @@ -281,6 +283,7 @@ elf_reloc_type_string(struct elfobj *obj, uint32_t r_type) return "R_386_TLS_GD"; case R_386_TLS_LDM: return "R_386_TLS_LDM"; +#ifdef __linux__ case R_386_16: return "R_386_16"; case R_386_PC16: @@ -289,6 +292,7 @@ elf_reloc_type_string(struct elfobj *obj, uint32_t r_type) return "R_386_8"; case R_386_PC8: return "R_386_PC8"; +#endif case R_386_TLS_GD_32: return "R_386_TLS_GD_32"; case R_386_TLS_GD_PUSH: @@ -317,6 +321,7 @@ elf_reloc_type_string(struct elfobj *obj, uint32_t r_type) return "R_386_TLS_DTOFF32"; case R_386_TLS_TPOFF32: return "R_386_TLS_TPOFF32"; +#ifdef __linux__ case R_386_SIZE32: return "R_386_TLS_SIZE32"; case R_386_TLS_GOTDESC: @@ -325,6 +330,7 @@ elf_reloc_type_string(struct elfobj *obj, uint32_t r_type) return "R_386_TLS_DESC_CALL"; case R_386_TLS_DESC: return "R_386_TLS_DESC"; +#endif case R_386_IRELATIVE: return "R_386_IRELATIVE"; default: @@ -346,8 +352,10 @@ elf_reloc_type_string(struct elfobj *obj, uint32_t r_type) return "R_X86_64_COPY"; case R_X86_64_GLOB_DAT: return "R_X86_64_GLOB_DAT"; +#ifdef __linux__ case R_X86_64_JUMP_SLOT: return "R_X86_64_JUMP_SLOT"; +#endif case R_X86_64_RELATIVE: return "R_X86_64_RELATIVE"; case R_X86_64_GOTPCREL: @@ -408,8 +416,10 @@ elf_reloc_type_string(struct elfobj *obj, uint32_t r_type) return "R_X86_64_TLSDESC"; case R_X86_64_IRELATIVE: return "R_X86_64_IRELATIVE"; +#ifdef __linux__ case R_X86_64_RELATIVE64: return "R_X86_64_RELATIVE64"; +#endif default: return "R_UNKNOWN"; } @@ -492,9 +502,21 @@ elf_data_offset(struct elfobj *obj) void * elf_address_pointer(struct elfobj *obj, uint64_t address) { - uint64_t offset = elf_data_offset(obj) + address - elf_data_base(obj); + elf_segment_iterator_t iter; + struct elf_segment segment; + long long offset = -1; - if (offset > obj->size - 1) + elf_segment_iterator_init(obj, &iter); + while (elf_segment_iterator_next(&iter, &segment) == ELF_ITER_OK) { + if (address < segment.vaddr || + address >= segment.vaddr + segment.filesz) + continue; + offset = segment.offset + (address - segment.vaddr); + break; + } + if (offset == -1) + return NULL; + if ((size_t)offset > obj->size - 1) return NULL; return (void *)((uint8_t *)&obj->mem[offset]); } @@ -512,7 +534,7 @@ const char * elf_dynamic_string(struct elfobj *obj, uint64_t offset) { - if (offset >= obj->size) + if (offset >= obj->size - 1) return NULL; return &obj->dynstr[offset]; } @@ -552,8 +574,8 @@ elf_section_by_index(struct elfobj *obj, uint32_t index, struct elf_section *out) { - switch(obj->e_class) { - case elfclass32: + switch(obj->e_class) { + case elfclass32: if (index >= obj->ehdr32->e_shnum) return false; out->name = &obj->shstrtab[obj->shdr32[index].sh_name]; @@ -565,7 +587,7 @@ elf_section_by_index(struct elfobj *obj, uint32_t index, out->offset = obj->shdr32[index].sh_offset; out->address = obj->shdr32[index].sh_addr; break; - case elfclass64: + case elfclass64: if (index >= obj->ehdr64->e_shnum) return false; out->name = &obj->shstrtab[obj->shdr64[index].sh_name]; @@ -579,7 +601,7 @@ elf_section_by_index(struct elfobj *obj, uint32_t index, break; default: return false; - } + } return true; } @@ -593,6 +615,46 @@ elf_section_name_by_index(struct elfobj *obj, uint32_t index) return section.name; } +bool +elf_section_by_address(struct elfobj *obj, uint64_t addr, struct elf_section *out) +{ + struct elf_section section; + elf_section_iterator_t iter; + + elf_section_iterator_init(obj, &iter); + while (elf_section_iterator_next(&iter, §ion) == ELF_ITER_OK) { + if (addr >= section.address && addr < section.address + section.size) { + memcpy(out, §ion, sizeof(section)); + return true; + } + } + return false; +} + +bool +elf_symbol_by_value(struct elfobj *obj, uint64_t addr, struct elf_symbol *out) +{ + struct elf_symbol symbol; + elf_symtab_iterator_t symtab_iter; + elf_dynsym_iterator_t dynsym_iter; + + elf_dynsym_iterator_init(obj, &dynsym_iter); + while (elf_dynsym_iterator_next(&dynsym_iter, &symbol) == ELF_ITER_OK) { + if (addr >= symbol.value && addr < symbol.value + symbol.size) { + memcpy(out, &symbol, sizeof(symbol)); + return true; + } + } + elf_symtab_iterator_init(obj, &symtab_iter); + while (elf_symtab_iterator_next(&symtab_iter, &symbol) == ELF_ITER_OK) { + if (addr >= symbol.value && addr < symbol.value + symbol.size) { + memcpy(out, &symbol, sizeof(symbol)); + return true; + } + } + return false; +} + bool elf_symbol_by_index(struct elfobj *obj, unsigned int index, struct elf_symbol *out, const int which) @@ -697,6 +759,13 @@ elf_type(struct elfobj *obj) return obj->type; } +size_t +elf_size(struct elfobj *obj) +{ + + return obj->size; +} + void * elf_offset_pointer(elfobj_t *obj, uint64_t off) { @@ -1369,7 +1438,7 @@ elf_note_iterator_next(struct elf_note_iterator *iter, ELFNOTE_NAMESZ(iter->note32); max_note_offset = iter->obj->note_offset + iter->obj->note_size; if (entry_size >= max_note_offset) { - elf_error_set(e, "Invalid note entry size\n"); + elf_error_set(e, "Invalid PT_NOTE entry size\n"); return ELF_ITER_ERROR; } entry->mem = ELFNOTE_DESC(iter->note32); @@ -1605,8 +1674,8 @@ elf_open_object(const char *path, struct elfobj *obj, uint64_t load_flags, { int fd; uint32_t i, phdr_count = 0; - unsigned int open_flags = O_RDONLY; - unsigned int mmap_perms = PROT_READ|PROT_WRITE; + unsigned int open_flags = (load_flags & ELF_LOAD_F_MODIFY) ? O_RDWR : O_RDONLY; + unsigned int mmap_perms = PROT_READ|PROT_WRITE; // always need +write even with MAP_PRIVATE unsigned int mmap_flags = MAP_PRIVATE; uint8_t *mem; uint8_t e_class; @@ -1646,7 +1715,7 @@ elf_open_object(const char *path, struct elfobj *obj, uint64_t load_flags, mem = mmap(NULL, st.st_size, mmap_perms, mmap_flags, fd, 0); if (mem == MAP_FAILED) { - elf_error_set(error, "mmap: %s", strerror(errno)); + elf_error_set(error, "mmap(1): %s", strerror(errno)); close(fd); return false; } @@ -1786,7 +1855,7 @@ elf_open_object(const char *path, struct elfobj *obj, uint64_t load_flags, * segment's we pick the first one and use that. If there are two * PT_GNU_EH_FRAME segment's we pick the first one. We also must perform * rigirous sanity checks since we will be internally referencing several - * of these program header types for a variety of reasons. + * of these program header types for a variety of reasons */ obj->pt_load = calloc(INITIAL_LOAD_COUNT, sizeof(struct pt_load)); if (obj->pt_load == NULL) { @@ -1868,7 +1937,72 @@ elf_open_object(const char *path, struct elfobj *obj, uint64_t load_flags, obj->eh_frame_hdr_offset = obj->phdr32[i].p_offset; } } + /* + * When observing the text segment (Traditionally a single PT_LOAD segment) + * we must also consider SCOP (Secure code partitioning): + * http://www.bitlackeys.org/papers/secure_code_partitioning_2018.txt + */ } else if (obj->phdr32[i].p_type == PT_LOAD && obj->phdr32[i].p_offset == 0) { + if (text_found == false && obj->phdr32[i].p_flags == PF_R) { + if (obj->phdr32[i + 1].p_flags == PF_R|PF_X && + obj->phdr32[i + 2].p_flags == PF_R) { + obj->flags |= ELF_SCOP_F; + text_found = true; + obj->pt_load[obj->load_count].flag |= ELF_PT_LOAD_TEXT_F; + obj->pt_load[obj->load_count + 1].flag |= ELF_PT_LOAD_TEXT_F; + obj->pt_load[obj->load_count + 1].flag |= ELF_PT_LOAD_TEXT_RDONLY_F; + obj->pt_load[obj->load_count + 2].flag |= ELF_PT_LOAD_TEXT_F; + obj->pt_load[obj->load_count + 2].flag |= ELF_PT_LOAD_TEXT_RDONLY_F; + /* + * Consider a SCOP (Secure code partitioning) scenario + * where all of the read-only sections are prepended before + * the executable sections, and therefore there are only + * two segments that make up the text segment instead of + * three. This is a hypothetical but conceievable linking + * configuration. SCOP is very new, and currently is in + * the order of 3 PT_LOAD segments; the first being PF_R + * the second being PF_R|PF_X and the 3rd being PF_R, this + * supports the conventional order of the ELF sections from + * a historic standpoint and will probably stay this way + * for quite a while, but we must atleast be prepared for + * other variations of this, and even more than what we are + * currently doing here: + */ + obj->text_address = obj->phdr32[i].p_vaddr; + obj->text_segment_filesz = obj->phdr32[i].p_filesz; + + memcpy(&obj->pt_load[obj->load_count].phdr32, + &obj->phdr32[i], sizeof(Elf32_Phdr)); + memcpy(&obj->pt_load[obj->load_count + 1].phdr32, + &obj->phdr32[i + 1], sizeof(Elf32_Phdr)); + memcpy(&obj->pt_load[obj->load_count + 2].phdr32, + &obj->phdr32[i + 2], sizeof(Elf32_Phdr)); + i += 2; + obj->load_count += 3; + continue; + } else if (obj->phdr32[i + 1].p_flags == PF_R|PF_X && + /* + * Assuming the next segment would be the + * data segment, hence PF_R|PF_W, and the + * two segments before it SCOP text segments. + */ + obj->phdr32[i + 2].p_flags == PF_R|PF_W) { + text_found = true; + obj->flags |= ELF_SCOP_F; + obj->pt_load[obj->load_count].flag |= ELF_PT_LOAD_TEXT_F; + obj->pt_load[obj->load_count + 1].flag |= ELF_PT_LOAD_TEXT_F; + obj->pt_load[obj->load_count + 1].flag |= ELF_PT_LOAD_TEXT_RDONLY_F; + obj->text_address = obj->phdr32[i].p_vaddr; + obj->text_segment_filesz = obj->phdr32[i].p_filesz; + memcpy(&obj->pt_load[obj->load_count].phdr32, + &obj->phdr32[i], sizeof(Elf32_Phdr)); + memcpy(&obj->pt_load[obj->load_count].phdr32, + &obj->phdr32[i], sizeof(Elf32_Phdr)); + i += 1; + obj->load_count += 2; + continue; + } + } obj->pt_load[obj->load_count].flag |= ELF_PT_LOAD_TEXT_F; text_found = true; memcpy(&obj->pt_load[obj->load_count++].phdr32, &obj->phdr32[i], @@ -1899,6 +2033,7 @@ elf_open_object(const char *path, struct elfobj *obj, uint64_t load_flags, &obj->phdr32[i], sizeof(Elf32_Phdr)); obj->data_segment_filesz = obj->phdr32[i].p_filesz; } + } } break; @@ -1977,9 +2112,6 @@ elf_open_object(const char *path, struct elfobj *obj, uint64_t load_flags, obj->shstrtab = (char *)&mem[obj->shdr64[obj->ehdr64->e_shstrndx].sh_offset]; } - if ((obj->anomalies & INVALID_F_SH_HEADERS) == 0) - obj->section_count = section_count = obj->ehdr64->e_shnum; - if (obj->ehdr64->e_shentsize != sizeof(Elf64_Shdr)) { if (__strict) { elf_error_set(error, "invalid_e_shentsize: %u", @@ -1988,6 +2120,20 @@ elf_open_object(const char *path, struct elfobj *obj, uint64_t load_flags, } obj->anomalies |= INVALID_F_SHENTSIZE; } + /* + * NOTE: + * It is the position of libelfmaster to not parse existing section + * headers under the following conditions: + * 1. If the section header table is malformed, i.e. offset of the table + * points somewhere out of the file range. + * 2. If e_shentsize != sizeof(ElfW(Shdr)) -- and this decision should be + * re-addressed in the future so that we can parse custom section headers + * that crafty hackers don't want us to parse + */ + if ((obj->anomalies & INVALID_F_SH_HEADERS) == 0 && + (obj->anomalies & INVALID_F_SHENTSIZE) == 0) + obj->section_count = section_count = obj->ehdr64->e_shnum; + if (obj->ehdr64->e_type != ET_REL) { if (obj->ehdr64->e_phentsize != sizeof(Elf64_Phdr)) { elf_error_set(error, "invalid e_phentsize: %u", @@ -2002,6 +2148,7 @@ elf_open_object(const char *path, struct elfobj *obj, uint64_t load_flags, elf_error_set(error, "calloc: %s", strerror(errno)); goto err; } + phdr_count = INITIAL_LOAD_COUNT; for (i = 0; i < obj->ehdr64->e_phnum; i++) { if (obj->load_count >= phdr_count) { @@ -2075,6 +2222,49 @@ elf_open_object(const char *path, struct elfobj *obj, uint64_t load_flags, } } } else if (obj->phdr64[i].p_type == PT_LOAD && obj->phdr64[i].p_offset == 0) { + /* + * NOTE: Read coments in the i386 PT_LOAD parsing above + * as it applies to this next chunk of code here as well for x64. + */ + if (text_found == false && obj->phdr64[i].p_flags == PF_R) { + if (obj->phdr64[i + 1].p_flags == PF_R|PF_X && + obj->phdr64[i + 2].p_flags == PF_R) { + obj->flags |= ELF_SCOP_F; + text_found = true; + obj->pt_load[obj->load_count].flag |= ELF_PT_LOAD_TEXT_F; + obj->pt_load[obj->load_count + 1].flag |= ELF_PT_LOAD_TEXT_F; + obj->pt_load[obj->load_count + 1].flag |= ELF_PT_LOAD_TEXT_RDONLY_F; + obj->pt_load[obj->load_count + 2].flag |= ELF_PT_LOAD_TEXT_F; + obj->pt_load[obj->load_count + 2].flag |= ELF_PT_LOAD_TEXT_RDONLY_F; + obj->text_address = obj->phdr64[i].p_vaddr; + obj->text_segment_filesz = obj->phdr64[i].p_filesz; + memcpy(&obj->pt_load[obj->load_count++].phdr64, &obj->phdr64[i], + sizeof(Elf64_Phdr)); + memcpy(&obj->pt_load[obj->load_count + 1].phdr64, + &obj->phdr64[i + 1], sizeof(Elf64_Phdr)); + memcpy(&obj->pt_load[obj->load_count + 2].phdr64, + &obj->phdr64[i + 2], sizeof(Elf64_Phdr)); + i += 2; + obj->load_count += 3; + continue; + } else if (obj->phdr64[i + 1].p_flags == PF_R|PF_X && + obj->phdr64[i + 2].p_flags == PF_R|PF_W) { + text_found = true; + obj->flags |= ELF_SCOP_F; + obj->pt_load[obj->load_count].flag |= ELF_PT_LOAD_TEXT_F; + obj->pt_load[obj->load_count + 1].flag |= ELF_PT_LOAD_TEXT_F; + obj->pt_load[obj->load_count + 1].flag |= ELF_PT_LOAD_TEXT_RDONLY_F; + obj->text_address = obj->phdr64[i].p_vaddr; + obj->text_segment_filesz = obj->phdr64[i].p_filesz; + memcpy(&obj->pt_load[obj->load_count].phdr64, + &obj->phdr64[i], sizeof(Elf64_Phdr)); + memcpy(&obj->pt_load[obj->load_count].phdr64, + &obj->phdr64[i], sizeof(Elf64_Phdr)); + i += 1; + obj->load_count += 2; + continue; + } + } obj->pt_load[obj->load_count].flag |= ELF_PT_LOAD_TEXT_F; text_found = true; memcpy(&obj->pt_load[obj->load_count++].phdr64, &obj->phdr64[i], @@ -2120,7 +2310,7 @@ elf_open_object(const char *path, struct elfobj *obj, uint64_t load_flags, * we just skip section parsing/loading, after which we can sort them but * but not now. */ - if (insane_headers(obj) == true) { + if (insane_section_headers(obj) == true) { goto final_load_stages; } @@ -2193,7 +2383,8 @@ elf_open_object(const char *path, struct elfobj *obj, uint64_t load_flags, final_load_stages: if (elf_flags(obj, ELF_DYNAMIC_F) == true) { if (load_dynamic_segment_data(obj) == false) { - elf_error_set(error, "failed to build dynamic segment data"); + elf_error_set(error, "failed to build dynamic segment data: %s", + path); goto err; } } @@ -2207,7 +2398,8 @@ elf_open_object(const char *path, struct elfobj *obj, uint64_t load_flags, * of dynamically linked executables. We need to fix this ASAP. */ if (elf_flags(obj, ELF_DYNAMIC_F) == true && - insane_headers(obj) == true && (load_flags & ELF_LOAD_F_FORENSICS)) { + insane_section_headers(obj) == true && + (load_flags & ELF_LOAD_F_FORENSICS)) { elf_error_t suberror; if (reconstruct_elf_sections(obj, &suberror) == false) { @@ -2221,14 +2413,13 @@ elf_open_object(const char *path, struct elfobj *obj, uint64_t load_flags, * FORENSICS flag in elf_open_object, then skip the * reconstruction of necessary data. */ - if (insane_headers(obj) == true) + if (insane_section_headers(obj) == true) goto finalize; } - /* * Build a cache for symtab and dynsym as needed. */ - if (insane_headers(obj) == true && + if (insane_section_headers(obj) == true && (load_flags & ELF_LOAD_F_FORENSICS)) { /* * Make room to reconstruct up to SYMTAB_RECONSTRUCT_COUNT functions @@ -2292,8 +2483,359 @@ elf_close_object(elfobj_t *obj) free_caches(obj); free_arrays(obj); free_misc(obj); + free(obj->pt_load); /* * Unmap memory */ + if (obj->load_flags & ELF_LOAD_F_MODIFY) { + msync(obj->mem, obj->size, MS_SYNC); + } munmap(obj->mem, obj->size); } + +bool +elf_has_header(const char *path, bool *has_header, elf_error_t *error) +{ + int fd; + int magic; + + if((fd = open(path, O_RDONLY)) < 0) { + elf_error_set(error, "open: %s", strerror(errno)); + return false; + } + + if(pread(fd, &magic, sizeof(int), 0) != sizeof(int)) { + elf_error_set(error, "pread: %s", strerror(errno)); + return false; + } + *has_header = (magic == 0x464c457f) ? true : false; + close(fd); + return true; +} + +/* + * Handles opening binary stubs that reside in disk. Saves instance as a elfobj_t. + */ +bool +elf_open_stub(const char *path, struct elfobj *obj, elf_error_t *error) +{ + int fd; + struct stat st; + unsigned int open_flags = O_RDWR; + unsigned int mmap_perms = PROT_READ|PROT_WRITE; + unsigned int mmap_flags = MAP_PRIVATE; + uint8_t *mem; + + memset(obj, 0, sizeof(*obj)); + if((fd = open(path, open_flags, S_IRUSR|S_IRGRP|S_IROTH)) < 0) { + elf_error_set(error, "open: %s", strerror(errno)); + return false; + } + obj->fd = fd; + obj->path = path; + + if (fstat(fd, &st) < 0) { + elf_error_set(error, "fstat: %s", strerror(errno)); + close(fd); + return false; + } + obj->size = st.st_size; + + if((mem = mmap(NULL, st.st_size, mmap_perms, mmap_flags, fd, 0)) == MAP_FAILED) { + elf_error_set(error, "mmap: %s", strerror(errno)); + close(fd); + return false; + } + obj->mem = mem; + obj->type = ELF_ET_STUB; + return true; +} + +/* + * Handles initialization of a elfobj_t for a given stub supplied as a binary array. + */ +bool +elf_init_stub(struct elfobj *obj, uint8_t *mem, size_t size, elf_error_t *error) +{ + if (obj == NULL) { + elf_error_set(error, "Invalid elfobj_t address"); + return false; + } + if (mem == NULL) { + elf_error_set(error, "Invalid stub buffer address"); + return false; + } + obj->type = ELF_ET_STUB; + obj->mem = mem; + obj->size = size; + return true; +} + +/* + * Creates an elf object. initial content can be specified to contain a given ELF file. + */ +bool +elf_create_object(const char *path, struct elfobj *obj, struct elfobj *copy, size_t size, uint64_t load_flags, elf_error_t *error) +{ + int fd; + unsigned int open_flags = O_RDWR|O_CREAT|O_APPEND; + unsigned int mmap_perms = PROT_READ|PROT_WRITE; + unsigned int mmap_flags = MAP_PRIVATE; + uint8_t *mem; + + /* + * we count on this being initialized for various sanity checks. + */ + memset(obj, 0, sizeof(*obj)); + + /* + * we check if the file wants to be created containing a particular elf object + */ + if (copy != NULL) { + memcpy(obj, copy, sizeof(struct elfobj)); + memcpy(obj->mem, copy->mem, copy->size); + } + obj->load_flags = load_flags; + obj->path = path; + + if (load_flags & ELF_LOAD_F_MODIFY) { + mmap_flags = MAP_SHARED; + } + fd = open(path, open_flags, S_IRUSR | S_IRGRP | S_IROTH); + if (fd < 0) { + elf_error_set(error, "open: %s", strerror(errno)); + return false; + } + obj->fd = fd; + + if (size != 0 && copy == NULL) { + obj->size = size; + mem = mmap(NULL, obj->size, mmap_perms, mmap_flags, fd, 0); + if (mem == MAP_FAILED) { + elf_error_set(error, "mmap: %s", strerror(errno)); + close(fd); + return false; + } + obj->mem = mem; + } else if (size == 0 && copy == NULL) { + fprintf(stderr, "Invalid argument: size\n"); + return false; + } + return true; +} + +/* + * Writes a given elfobj_t instance to disk + */ +bool +elf_commit_object(struct elfobj *obj, size_t size, int offset, elf_error_t *error) +{ + if (pwrite(obj->fd, obj->mem, size, offset) != size) { + elf_error_set(error, "pwrite: %s", strerror(errno)); + return false; + } + return true; +} + +/* + * Handles several injection techniques. + */ +bool +elf_inject_code(struct elfobj *host, struct elfobj *target, uint64_t *payload_offset, + uint64_t injection_flags, elf_error_t *error) +{ + bool injection_end; + uint8_t *dest_mem; + size_t ehdr_size; + size_t payload_size; + elf_segment_iterator_t p_iter; + elf_section_iterator_t s_iter; + struct elf_segment segment; + struct elf_section section; + + injection_end = false; + payload_size = PAGE_ALIGN_UP(target->size); + ehdr_size = (host->e_class == ELFCLASS32) ? sizeof(Elf32_Ehdr) : sizeof(Elf64_Ehdr); + + if((dest_mem = (uint8_t *)calloc(1, host->size + payload_size)) == NULL) { + elf_error_set(error, "calloc: %s", strerror(errno)); + return false; + } + host->data_offset = elf_data_offset(host); + host->text_offset = elf_text_offset(host); + + switch(injection_flags) { + case ELF_INJECT_F_POSTPEND: { + uint32_t poffset; + + elf_segment_iterator_init(host, &p_iter); + while (elf_segment_iterator_next(&p_iter, &segment) == ELF_ITER_OK) { + if(segment.type == PT_LOAD && segment.offset == host->data_offset) { + if (host->e_class == ELFCLASS32) { + Elf32_Phdr *phdr = &host->phdr32[p_iter.index-1]; + poffset = phdr->p_offset + phdr->p_filesz; + phdr->p_memsz += payload_size; + phdr->p_filesz += payload_size; + phdr->p_flags |= PF_X; + + } else { + Elf64_Phdr *phdr = &host->phdr64[p_iter.index-1]; + poffset = phdr->p_offset + phdr->p_filesz; + phdr->p_memsz += payload_size; + phdr->p_filesz += payload_size; + phdr->p_flags |= PF_X; + } + memcpy(dest_mem, host->mem, host->size); + memcpy(dest_mem + poffset, target->mem, target->size); + *payload_offset = poffset; + host->mem = dest_mem; + host->size += payload_size; + injection_end = true; + break; + } + } + break; + } + case ELF_INJECT_F_PREPEND: { + elf_segment_iterator_init(host, &p_iter); + while (elf_segment_iterator_next(&p_iter, &segment) == ELF_ITER_OK) { + if(segment.offset != host->text_offset) { + if (host->e_class == ELFCLASS32) { + Elf32_Phdr *phdr = &host->phdr32[p_iter.index-1]; + phdr->p_offset += payload_size; + } else { + Elf64_Phdr *phdr = &host->phdr64[p_iter.index-1]; + phdr->p_offset += payload_size; + } + } else if(segment.offset == host->text_offset && segment.type == PT_LOAD){ + if (host->e_class == ELFCLASS32) { + Elf32_Phdr *phdr = &host->phdr32[p_iter.index-1]; + phdr->p_vaddr -= payload_size; + phdr->p_paddr -= payload_size; + phdr->p_filesz += payload_size; + phdr->p_memsz += payload_size; + } else { + Elf64_Phdr *phdr = &host->phdr64[p_iter.index-1]; + phdr->p_vaddr -= payload_size; + phdr->p_paddr -= payload_size; + phdr->p_filesz += payload_size; + phdr->p_memsz += payload_size; + } + } + } + elf_section_iterator_init(host, &s_iter); + while (elf_section_iterator_next(&s_iter, §ion) == ELF_ITER_OK) { + if (host->e_class == ELFCLASS32) { + Elf32_Shdr *shdr = &host->shdr32[s_iter.index-1]; + shdr->sh_offset += payload_size; + } else { + Elf64_Shdr *shdr = &host->shdr64[s_iter.index-1]; + shdr->sh_offset += payload_size; + } + } + memcpy(dest_mem, host->mem, ehdr_size); + memcpy(dest_mem + ehdr_size, target->mem, target->size); + memcpy(dest_mem + ehdr_size + payload_size, host->mem + ehdr_size, host->size - ehdr_size); + + *payload_offset = ehdr_size; + host->mem = dest_mem; + host->size += payload_size; + if (host->e_class == ELFCLASS32) { + Elf32_Ehdr *ehdr = (Elf32_Ehdr*)host->mem; + ehdr->e_phoff += payload_size; + ehdr->e_shoff += payload_size; + } else { + Elf64_Ehdr *ehdr = (Elf64_Ehdr*)host->mem; + ehdr->e_phoff += payload_size; + ehdr->e_shoff += payload_size; + } + injection_end = true; + break; + } + case ELF_INJECT_F_INTERPEND: { + size_t code_size; + size_t data_size; + + elf_segment_iterator_init(host, &p_iter); + while (elf_segment_iterator_next(&p_iter, &segment) == ELF_ITER_OK) { + if (segment.offset == host->text_offset && segment.type == PT_LOAD) { + if (host->e_class == ELFCLASS32) { + Elf32_Phdr *phdr = &host->phdr32[p_iter.index-1]; + code_size = phdr->p_filesz; + phdr->p_filesz += payload_size; + phdr->p_memsz += payload_size; + } else { + Elf64_Phdr *phdr = &host->phdr64[p_iter.index-1]; + code_size = phdr->p_filesz; + phdr->p_filesz += payload_size; + phdr->p_memsz += payload_size; + } + } else if (segment.offset != host->text_offset && segment.type == PT_LOAD) { + if (host->e_class == ELFCLASS32) { + Elf32_Phdr *phdr = &host->phdr32[p_iter.index-1]; + phdr->p_offset += payload_size; + data_size = phdr->p_filesz; + host->data_offset = phdr->p_offset; + + } else { + Elf64_Phdr *phdr = &host->phdr64[p_iter.index-1]; + phdr->p_offset += payload_size; + data_size = phdr->p_filesz; + host->data_offset = phdr->p_offset; + } + } else if (segment.type == PT_DYNAMIC) { + if (host->e_class == ELFCLASS32) { + Elf32_Phdr *phdr = &host->phdr32[p_iter.index-1]; + phdr->p_offset += payload_size; + + } else { + Elf64_Phdr *phdr = &host->phdr64[p_iter.index-1]; + phdr->p_offset += payload_size; + } + } + } + elf_section_iterator_init(host, &s_iter); + while (elf_section_iterator_next(&s_iter, §ion) == ELF_ITER_OK) { + if (host->e_class == ELFCLASS32) { + Elf32_Shdr *shdr = &host->shdr32[s_iter.index-1]; + if (shdr->sh_offset > host->text_offset) { + shdr->sh_offset += payload_size; + } else if (shdr->sh_type == SHT_DYNAMIC) { + shdr->sh_offset += payload_size; + } + } else { + Elf64_Shdr *shdr = &host->shdr64[s_iter.index-1]; + if (shdr->sh_offset > host->data_offset) { + shdr->sh_offset += payload_size; + } else if (shdr->sh_type == SHT_DYNAMIC) { + shdr->sh_offset += payload_size; + } + } + } + memcpy(dest_mem, host->mem, code_size); + memcpy(dest_mem + code_size, target->mem, target->size > payload_size ? + payload_size : target->size); + memcpy(dest_mem + host->data_offset, host->mem + host->data_offset - payload_size, host->size - code_size); + + *payload_offset = code_size; + host->mem = dest_mem; + host->size += payload_size; + if (host->e_class == ELFCLASS32) { + Elf32_Ehdr *ehdr = (Elf32_Ehdr*)host->mem; + ehdr->e_shoff += payload_size; + } else { + Elf64_Ehdr *ehdr = (Elf64_Ehdr*)host->mem; + ehdr->e_shoff += payload_size; + + } + injection_end = true; + break; + } + } + if (injection_end == false) { + elf_error_set(error, "Target segment was not found for injection"); + return false; + } + return true; +} + diff --git a/tags b/tags new file mode 100644 index 0000000..0ce34a6 --- /dev/null +++ b/tags @@ -0,0 +1,640 @@ +!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ +!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ +!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/ +!_TAG_PROGRAM_NAME Exuberant Ctags // +!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ +!_TAG_PROGRAM_VERSION 5.9~svn20110310 // +ALIGN_CACHE src/libelfmaster.c 53;" d file: +BUILD_DIR Makefile /^BUILD_DIR=\/home\/ulexec\/Documents\/ELF-REsearch\/PrivateProjects\/libelfmaster$/;" m +CACHEMAGIC include/internal.h 46;" d +CACHEMAGIC_NEW include/internal.h 59;" d +CACHEMAGIC_VERSION_NEW src/libelfmaster.c 51;" d file: +CACHE_FILE src/libelfmaster.c 49;" d file: +CACHE_VERSION include/internal.h 60;" d +CFLAGS Makefile /^CFLAGS=-D_DEFAULT_SOURCE -D_GNU_SOURCE -D_BSD_SOURCE -std=gnu99 -Wall -W -Wundef -Wendif-labels -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline -Wdisabled-optimization -fstrict-aliasing -O2 -pipe -Wno-parentheses -g -rdynamic -fno-omit-frame-pointer -I\/home\/ulexec\/Documents\/ELF-REsearch\/PrivateProjects\/libelfmaster\/include -I\/home\/ulexec\/Documents\/ELF-REsearch\/PrivateProjects\/libelfmaster\/include -I\/opt\/elfmaster\/include -D__x86_64__ -D_GNU_SOURCE -I\/opt\/elfmaster\/include -m64 -fPIC$/;" m +CFLAGS regressions/Makefile /^CFLAGS := -L$(LIB_DIR) $(CFLAGS)$/;" m +DEBUG_LOG include/internal.h 32;" d +DEBUG_LOG include/internal.h 34;" d +DW_EH_PE_APPL_MASK include/dwarf.h 5;" d +DW_EH_PE_FORMAT_MASK include/dwarf.h 35;" d +DW_EH_PE_FORMAT_MASK include/dwarf.h 4;" d +DW_EH_PE_absptr include/dwarf.h 7;" d +DW_EH_PE_aligned include/dwarf.h 23;" d +DW_EH_PE_datarel include/dwarf.h 21;" d +DW_EH_PE_funcrel include/dwarf.h 22;" d +DW_EH_PE_indirect include/dwarf.h 19;" d +DW_EH_PE_omit include/dwarf.h 8;" d +DW_EH_PE_pcrel include/dwarf.h 18;" d +DW_EH_PE_sdata2 include/dwarf.h 14;" d +DW_EH_PE_sdata4 include/dwarf.h 15;" d +DW_EH_PE_sdata8 include/dwarf.h 16;" d +DW_EH_PE_signed include/dwarf.h 17;" d +DW_EH_PE_sleb128 include/dwarf.h 13;" d +DW_EH_PE_textrel include/dwarf.h 20;" d +DW_EH_PE_udata2 include/dwarf.h 10;" d +DW_EH_PE_udata4 include/dwarf.h 11;" d +DW_EH_PE_udata8 include/dwarf.h 12;" d +DW_EH_PE_uleb128 include/dwarf.h 9;" d +ELFNOTE32_NEXT include/libelfmaster.h 58;" d +ELFNOTE64_NEXT include/libelfmaster.h 59;" d +ELFNOTE_ALIGN include/libelfmaster.h 55;" d +ELFNOTE_DESC include/libelfmaster.h 57;" d +ELFNOTE_DESCSZ include/libelfmaster.h 60;" d +ELFNOTE_NAME include/libelfmaster.h 54;" d +ELFNOTE_NAME include/libelfmaster.h 56;" d +ELFNOTE_NAMESZ include/libelfmaster.h 61;" d +ELF_BYTE include/libelfmaster.h /^ ELF_BYTE$/;" e enum:typewidth +ELF_DT_DEBUG_F include/libelfmaster.h /^ ELF_DT_DEBUG_F = (1 << 17)$/;" e enum:elf_obj_flags +ELF_DT_PLTREL_REL include/libelfmaster.h 47;" d +ELF_DT_PLTREL_RELA include/libelfmaster.h 46;" d +ELF_DWORD include/libelfmaster.h /^ ELF_DWORD,$/;" e enum:typewidth +ELF_DYNAMIC_F include/libelfmaster.h /^ ELF_DYNAMIC_F = (1 << 9),$/;" e enum:elf_obj_flags +ELF_DYNSTR_F include/libelfmaster.h /^ ELF_DYNSTR_F = (1 << 12),$/;" e enum:elf_obj_flags +ELF_DYNSYM_F include/libelfmaster.h /^ ELF_DYNSYM_F = (1 << 1),$/;" e enum:elf_obj_flags +ELF_DYN_RELOCS_F include/libelfmaster.h /^ ELF_DYN_RELOCS_F = (1 << 6),$/;" e enum:elf_obj_flags +ELF_EH_FRAME_F include/libelfmaster.h /^ ELF_EH_FRAME_F = (1 << 13),$/;" e enum:elf_obj_flags +ELF_FORENSICS_F include/libelfmaster.h /^ ELF_FORENSICS_F = (1 << 16), \/* elf sections at the least are reconstructed *\/$/;" e enum:elf_obj_flags +ELF_FULL_PIE_F include/libelfmaster.h /^ ELF_FULL_PIE_F = (1 << 14), \/* fully relocatable ET_DYN *\/$/;" e enum:elf_obj_flags +ELF_ITER_DONE include/libelfmaster.h /^ ELF_ITER_DONE,$/;" e enum:elf_iterator_res +ELF_ITER_ERROR include/libelfmaster.h /^ ELF_ITER_ERROR,$/;" e enum:elf_iterator_res +ELF_ITER_NOTFOUND include/libelfmaster.h /^ ELF_ITER_NOTFOUND$/;" e enum:elf_iterator_res +ELF_ITER_OK include/libelfmaster.h /^ ELF_ITER_OK,$/;" e enum:elf_iterator_res +ELF_LDSO_CACHE_NEW include/internal.h 63;" d +ELF_LDSO_CACHE_OLD include/internal.h 62;" d +ELF_LINKING_DYNAMIC include/libelfmaster.h /^ ELF_LINKING_DYNAMIC,$/;" e enum:elf_linking_type +ELF_LINKING_STATIC include/libelfmaster.h /^ ELF_LINKING_STATIC,$/;" e enum:elf_linking_type +ELF_LINKING_UNDEF include/libelfmaster.h /^ ELF_LINKING_UNDEF \/* Means its neither, such as an ET_REL or ET_CORE *\/$/;" e enum:elf_linking_type +ELF_LOAD_F_FORENSICS include/libelfmaster.h 517;" d +ELF_LOAD_F_MODIFY include/libelfmaster.h 519;" d +ELF_LOAD_F_SMART include/libelfmaster.h 515;" d +ELF_LOAD_F_STRICT include/libelfmaster.h 514;" d +ELF_LOAD_F_ULEXEC include/libelfmaster.h 520;" d +ELF_NOTE_F include/libelfmaster.h /^ ELF_NOTE_F = (1 << 4),$/;" e enum:elf_obj_flags +ELF_PHDRS_F include/libelfmaster.h /^ ELF_PHDRS_F = (1 << 2),$/;" e enum:elf_obj_flags +ELF_PIE_F include/libelfmaster.h /^ ELF_PIE_F = (1 << 8), \/* ET_DYN not necessarily fully relocatable though *\/$/;" e enum:elf_obj_flags +ELF_PLTGOT_F include/libelfmaster.h /^ ELF_PLTGOT_F = (1 << 11),$/;" e enum:elf_obj_flags +ELF_PLTGOT_PLT_STUB_F include/libelfmaster.h 459;" d +ELF_PLTGOT_RESERVED_DL_RESOLVE_F include/libelfmaster.h 458;" d +ELF_PLTGOT_RESERVED_DYNAMIC_F include/libelfmaster.h 456;" d +ELF_PLTGOT_RESERVED_LINKMAP_F include/libelfmaster.h 457;" d +ELF_PLTGOT_RESOLVED_F include/libelfmaster.h 460;" d +ELF_PLT_F include/libelfmaster.h /^ ELF_PLT_F = (1 << 10),$/;" e enum:elf_obj_flags +ELF_PLT_RELOCS_F include/libelfmaster.h /^ ELF_PLT_RELOCS_F = (1 << 5),$/;" e enum:elf_obj_flags +ELF_PT_LOAD_DATA_F include/libelfmaster.h 274;" d +ELF_PT_LOAD_MISC_F include/libelfmaster.h 275;" d +ELF_PT_LOAD_TEXT_F include/libelfmaster.h 273;" d +ELF_QWORD include/libelfmaster.h /^ ELF_QWORD,$/;" e enum:typewidth +ELF_RELOC_JUMP_SLOT src/internal.c 73;" d file: +ELF_SHDRS_F include/libelfmaster.h /^ ELF_SHDRS_F = (1 << 3),$/;" e enum:elf_obj_flags +ELF_SO_RESOLVE_ALL_F include/libelfmaster.h 489;" d +ELF_SO_RESOLVE_F include/libelfmaster.h 485;" d +ELF_SYMTAB_F include/libelfmaster.h /^ ELF_SYMTAB_F = (1 << 0),$/;" e enum:elf_obj_flags +ELF_SYMTAB_RECONSTRUCTION_F include/libelfmaster.h /^ ELF_SYMTAB_RECONSTRUCTION_F = (1 << 15), \/* .symtab is being reconstructed *\/$/;" e enum:elf_obj_flags +ELF_TEXT_RELOCS_F include/libelfmaster.h /^ ELF_TEXT_RELOCS_F = (1 << 7),$/;" e enum:elf_obj_flags +ELF_WORD include/libelfmaster.h /^ ELF_WORD,$/;" e enum:typewidth +GLIBC_START_CODE_32 src/internal.c 1118;" d file: +GLIBC_START_CODE_64 src/internal.c 1116;" d file: +GLIBC_START_CODE_64_v2 src/internal.c 1117;" d file: +HEADERS Makefile /^HEADERS=\/opt\/elfmaster\/include$/;" m +HEADERS src/Makefile /^HEADERS=$(INCLUDE_DIR)\/*.h$/;" m +INCLUDE_DIR regressions/Makefile /^INCLUDE_DIR=$(BUILD_DIR)\/include $(BUILD_DIR)\/regressions$/;" m +INCLUDE_DIR src/Makefile /^INCLUDE_DIR=$(SRC_DIR)\/include$/;" m +INITIAL_LOAD_COUNT src/libelfmaster.c 1609;" d file: +INIT_SIZE_THRESHOLD src/internal.c 1051;" d file: +INTERNAL_SECTION_COUNT include/internal.h 106;" d +INTERNAL_SHSTRTAB_SIZE include/internal.h 105;" d +INVALID_F_SHENTSIZE include/libelfmaster.h 213;" d +INVALID_F_SHNUM include/libelfmaster.h 212;" d +INVALID_F_SHOFF include/libelfmaster.h 209;" d +INVALID_F_SHOFFSET include/libelfmaster.h 211;" d +INVALID_F_SHSTRNDX include/libelfmaster.h 210;" d +INVALID_F_SHSTRTAB include/libelfmaster.h 215;" d +INVALID_F_SH_HEADERS include/libelfmaster.h 214;" d +INVALID_F_VITAL_DTAG_VALUE include/libelfmaster.h 220;" d +LDFLAGS regressions/Makefile /^LDFLAGS=-Wl,-rpath,\/opt\/elfmaster\/lib -Wl,-rpath-link,\/opt\/elfmaster\/lib -fPIC $(LIB_DIR)\/libelfmaster.a \/usr\/lib\/x86_64-linux-gnu\/libdl.so$/;" m +LDNAME Makefile /^LDNAME=@LDNAME@$/;" m +LDNAME_MAJOR Makefile /^LDNAME_MAJOR=@LDNAME_MAJOR@$/;" m +LDNAME_VERSION Makefile /^LDNAME_VERSION=@LDNAME_VERSION@$/;" m +LIBRARY Makefile /^LIBRARY=\/opt\/elfmaster\/lib$/;" m +LIB_DIR regressions/Makefile /^LIB_DIR=$(BUILD_DIR)\/src$/;" m +LIST_FOREACH_SAFE include/misc.h 5;" d +MAX_ERROR_STR_LEN include/libelfmaster.h 40;" d +MAX_LOADABLE_MAPPINGS include/libelfmaster.h 52;" d +MAX_PT_LOAD include/libelfmaster.h 272;" d +MAX_SO_COUNT src/libelfmaster.c 791;" d file: +MAX_VALID_SHNUM include/libelfmaster.h 78;" d +OBJECTS regressions/Makefile /^OBJECTS= \\$/;" m +OBJECTS src/Makefile /^OBJECTS=libelfmaster.o internal.o$/;" m +PF_EMUTRAMP examples/checksec.c 17;" d file: +PF_MPROTECT examples/checksec.c 15;" d file: +PF_PAGEEXEC examples/checksec.c 13;" d file: +PF_RANDEXEC examples/checksec.c 16;" d file: +PF_RANDMMAP examples/checksec.c 18;" d file: +PF_SEGMEXEC examples/checksec.c 14;" d file: +PKGCONFIG_DATA Makefile /^PKGCONFIG_DATA=\/opt\/elfmaster\/lib\/pkgconfig$/;" m +PREFIX Makefile /^PREFIX=\/opt\/elfmaster$/;" m +PT_GNU_EH_FRAME include/libelfmaster.h 67;" d +PT_GNU_RELRO include/libelfmaster.h 75;" d +PT_GNU_STACK include/libelfmaster.h 71;" d +PT_PAX_FLAGS examples/checksec.c 20;" d file: +PT_PAX_FLAGS include/libelfmaster.h 63;" d +RELA_ENT_SIZE src/internal.c 1159;" d file: +REL_ENT_SIZE src/internal.c 1160;" d file: +ROUNDUP src/libelfmaster.c 43;" d file: +SDIR regressions/Makefile /^SDIR=$(SRC_DIR)\/regressions$/;" m +SDIR src/Makefile /^SDIR=$(SRC_DIR)\/src$/;" m +SRC_DIR Makefile /^SRC_DIR=\/home\/ulexec\/Documents\/ELF-REsearch\/PrivateProjects\/libelfmaster$/;" m +SYMTAB_RECONSTRUCT_COUNT include/libelfmaster.h 80;" d +TARGET_DIR regressions/Makefile /^TARGET_DIR=$(BUILD_DIR)\/regressions$/;" m +TARGET_DIR src/Makefile /^TARGET_DIR=$(BUILD_DIR)\/src$/;" m +VERSION Makefile /^VERSION=0.1.0$/;" m +VERSION_MAJOR Makefile /^VERSION_MAJOR=0$/;" m +_GNU_SOURCE examples/checksec.c 1;" d file: +_GNU_SOURCE examples/eh_frame.c 4;" d file: +_GNU_SOURCE examples/elfparse.c 1;" d file: +_GNU_SOURCE examples/ldd.c 1;" d file: +_GNU_SOURCE examples/plt_dump.c 6;" d file: +_GNU_SOURCE examples/plt_dump2.c 7;" d file: +_GNU_SOURCE examples/pltgot.c 6;" d file: +_GNU_SOURCE examples/read_mem.c 7;" d file: +_GNU_SOURCE examples/sections.c 4;" d file: +_GNU_SOURCE examples/symbols.c 4;" d file: +_LIBELFMASTER_H_ include/libelfmaster.h 28;" d +_LIBELFMASTER_INTERNAL_H_ include/internal.h 27;" d +_MISC_H_ include/misc.h 2;" d +__LIBELFMASTER_DWARF__ include/dwarf.h 2;" d +_errno include/libelfmaster.h /^ int _errno;$/;" m struct:elf_error +_linkage include/internal.h /^ LIST_ENTRY(elf_fde_node) _linkage;$/;" m struct:elf_fde_node +_linkage include/internal.h /^ LIST_ENTRY(elf_malloc_node) _linkage;$/;" m struct:elf_malloc_node +_linkage include/internal.h /^ LIST_ENTRY(elf_plt_node) _linkage;$/;" m struct:elf_plt_node +_linkage include/internal.h /^ LIST_ENTRY(elf_rel_helper_node) _linkage;$/;" m struct:elf_rel_helper_node +_linkage include/internal.h /^ LIST_ENTRY(elf_section_node) _linkage;$/;" m struct:elf_section_node +_linkage include/internal.h /^ LIST_ENTRY(elf_shared_object_node) _linkage;$/;" m struct:elf_shared_object_node +_linkage include/internal.h /^ LIST_ENTRY(elf_symbol_node) _linkage;$/;" m struct:elf_symbol_node +_linkage include/internal.h /^ LIST_ENTRY(elf_eh_frame_node) _linkage;$/;" m struct:elf_eh_frame_node +_start examples/test2.c /^int _start() {$/;" f +add_section_entry src/internal.c /^add_section_entry(elfobj_t *obj, void *ptr)$/;" f file: +add_shstrtab_entry src/internal.c /^add_shstrtab_entry(elfobj_t *obj, const char *name, uint32_t *out)$/;" f file: +addend include/internal.h /^ bool addend;$/;" m struct:elf_rel_helper_node +addend include/libelfmaster.h /^ int64_t addend;$/;" m struct:elf_relocation +addr include/internal.h /^ uint64_t addr;$/;" m struct:elf_plt_node +addr include/libelfmaster.h /^ uint64_t addr;$/;" m struct:elfobj::__anon11::__anon12 +addr include/libelfmaster.h /^ uint64_t addr;$/;" m struct:elfobj::__anon11::__anon13 +addr include/libelfmaster.h /^ uint64_t addr;$/;" m struct:elfobj::__anon11::__anon14 +addr include/libelfmaster.h /^ uint64_t addr;$/;" m struct:elfobj::__anon11::__anon17 +addr include/libelfmaster.h /^ uint64_t addr;$/;" m struct:elfobj::__anon11::__anon18 +addr include/libelfmaster.h /^ uint64_t addr;$/;" m struct:elfobj::__anon11::__anon19 +addr include/libelfmaster.h /^ uint64_t addr;$/;" m struct:elfobj::__anon11::__anon20 +addr include/libelfmaster.h /^ uint64_t addr;$/;" m struct:elfobj::__anon11::__anon21 +addr include/libelfmaster.h /^ uint64_t addr;$/;" m struct:elfobj::__anon11::__anon22 +addr include/libelfmaster.h /^ uint64_t addr;$/;" m struct:elfobj::__anon11::__anon23 +addr include/libelfmaster.h /^ uint64_t addr;$/;" m struct:elfobj::__anon11::__anon24 +addr include/libelfmaster.h /^ uint64_t addr;$/;" m struct:elf_plt +address include/internal.h /^ uint64_t address;$/;" m struct:elf_section_node +address include/libelfmaster.h /^ uint64_t address;$/;" m struct:elf_section +align include/internal.h /^ uint64_t align;$/;" m struct:elf_section_node +align include/libelfmaster.h /^ uint64_t align;$/;" m struct:elf_section +align include/libelfmaster.h /^ uint64_t align;$/;" m struct:elf_segment +anomalies include/libelfmaster.h /^ unsigned long long int anomalies;$/;" m struct:elfobj +arch include/libelfmaster.h /^ elf_arch_t arch;$/;" m struct:elfobj +assert configure /^assert()$/;" f +basename include/internal.h /^ const char *basename;$/;" m struct:elf_shared_object_node +basename include/libelfmaster.h /^ const char *basename;$/;" m struct:elf_shared_object +bind include/internal.h /^ uint8_t bind;$/;" m struct:elf_symbol_node +bind include/libelfmaster.h /^ uint8_t bind;$/;" m struct:elf_symbol +build_dynsym_data src/internal.c /^build_dynsym_data(struct elfobj *obj)$/;" f +build_plt_data src/internal.c /^build_plt_data(struct elfobj *obj)$/;" f +build_symtab_data src/internal.c /^build_symtab_data(struct elfobj *obj)$/;" f +cache include/libelfmaster.h /^ struct cache_file *cache;$/;" m struct:elf_shared_object_iterator typeref:struct:elf_shared_object_iterator::cache_file +cache include/libelfmaster.h /^ } cache;$/;" m struct:elfobj typeref:struct:elfobj::__anon9 +cache_data include/libelfmaster.h /^ char *cache_data;$/;" m struct:elf_shared_object_iterator +cache_file include/internal.h /^struct cache_file {$/;" s +cache_file_new include/internal.h /^struct cache_file_new {$/;" s +cache_flags include/libelfmaster.h /^ uint32_t cache_flags;$/;" m struct:elf_shared_object_iterator +cache_new include/libelfmaster.h /^ struct cache_file_new *cache_new;$/;" m struct:elf_shared_object_iterator typeref:struct:elf_shared_object_iterator::cache_file_new +cache_size include/libelfmaster.h /^ size_t cache_size;$/;" m struct:elf_shared_object_iterator +check_lib configure /^check_lib()$/;" f +current include/libelfmaster.h /^ struct elf_eh_frame_node *current;$/;" m struct:elf_eh_frame_iterator typeref:struct:elf_eh_frame_iterator::elf_eh_frame_node +current include/libelfmaster.h /^ struct elf_plt_node *current;$/;" m struct:elf_plt_iterator typeref:struct:elf_plt_iterator::elf_plt_node +current include/libelfmaster.h /^ struct elf_rel_helper_node *current, *head;$/;" m struct:elf_relocation_iterator typeref:struct:elf_relocation_iterator::elf_rel_helper_node +current include/libelfmaster.h /^ struct elf_shared_object_node *current;$/;" m struct:elf_shared_object_iterator typeref:struct:elf_shared_object_iterator::elf_shared_object_node +current include/libelfmaster.h /^ struct elf_symbol_node *current;$/;" m struct:elf_dynsym_iterator typeref:struct:elf_dynsym_iterator::elf_symbol_node +current include/libelfmaster.h /^ struct elf_symbol_node *current;$/;" m struct:elf_symtab_iterator typeref:struct:elf_symtab_iterator::elf_symbol_node +data_address include/libelfmaster.h /^ uint64_t data_address; \/* data segment address *\/$/;" m struct:elfobj +data_offset include/libelfmaster.h /^ uint64_t data_offset;$/;" m struct:elfobj +data_segment_filesz include/libelfmaster.h /^ size_t data_segment_filesz;$/;" m struct:elfobj +debug include/libelfmaster.h /^ } debug;$/;" m struct:elfobj::__anon11 typeref:struct:elfobj::__anon11::__anon26 +dw_byte_encoding src/internal.c /^dw_byte_encoding(uint8_t encoded_byte, uint8_t *encoding, uint8_t *value)$/;" f file: +dw_decode_pointer src/internal.c /^dw_decode_pointer(elfobj_t *obj, uint8_t encoding_byte,$/;" f file: +dw_get_eh_frame_ranges src/internal.c /^dw_get_eh_frame_ranges(struct elfobj *obj)$/;" f +dw_read include/dwarf.h 25;" d +dw_read_location src/internal.c /^dw_read_location(elfobj_t *obj, uint64_t vaddr, size_t len,$/;" f file: +dw_read_sleb128 src/internal.c /^dw_read_sleb128(uint8_t *ptr, size_t len)$/;" f file: +dw_read_uleb128 src/internal.c /^dw_read_uleb128(uint8_t *ptr, size_t len)$/;" f file: +dynamic32 include/libelfmaster.h /^ Elf32_Dyn *dynamic32;$/;" m union:elfobj::__anon7 +dynamic64 include/libelfmaster.h /^ Elf64_Dyn *dynamic64;$/;" m union:elfobj::__anon7 +dynamic_addr include/libelfmaster.h /^ uint64_t dynamic_addr;$/;" m struct:elfobj +dynamic_offset include/libelfmaster.h /^ uint64_t dynamic_offset;$/;" m struct:elfobj +dynamic_size include/libelfmaster.h /^ size_t dynamic_size;$/;" m struct:elfobj +dynseg include/libelfmaster.h /^ } dynseg;$/;" m struct:elfobj typeref:struct:elfobj::__anon11 +dynstr include/libelfmaster.h /^ } dynstr;$/;" m struct:elfobj::__anon11 typeref:struct:elfobj::__anon11::__anon21 +dynstr include/libelfmaster.h /^ char *dynstr;$/;" m struct:elfobj +dynsym include/libelfmaster.h /^ LIST_HEAD(elf_dynsym_list, elf_symbol_node) dynsym;$/;" m struct:elfobj::__anon10 +dynsym include/libelfmaster.h /^ struct hsearch_data dynsym;$/;" m struct:elfobj::__anon9 typeref:struct:elfobj::__anon9::hsearch_data +dynsym include/libelfmaster.h /^ } dynsym;$/;" m struct:elfobj::__anon11 typeref:struct:elfobj::__anon11::__anon20 +dynsym32 include/libelfmaster.h /^ Elf32_Sym *dynsym32;$/;" m union:elfobj::__anon6 +dynsym64 include/libelfmaster.h /^ Elf64_Sym *dynsym64;$/;" m union:elfobj::__anon6 +dynsym_count include/libelfmaster.h /^ size_t dynsym_count;$/;" m struct:elfobj +e_class include/libelfmaster.h /^ elf_class_t e_class;$/;" m struct:elfobj +eh_frame include/libelfmaster.h /^ void *eh_frame;$/;" m struct:elfobj +eh_frame_entries include/libelfmaster.h /^ LIST_HEAD(elf_eh_frame_list, elf_eh_frame_node) eh_frame_entries;$/;" m struct:elfobj::__anon10 +eh_frame_hdr include/dwarf.h /^typedef struct eh_frame_hdr {$/;" s +eh_frame_hdr include/libelfmaster.h /^ void *eh_frame_hdr;$/;" m struct:elfobj +eh_frame_hdr_addr include/libelfmaster.h /^ uint64_t eh_frame_hdr_addr;$/;" m struct:elfobj +eh_frame_hdr_offset include/libelfmaster.h /^ uint64_t eh_frame_hdr_offset;$/;" m struct:elfobj +eh_frame_hdr_size include/libelfmaster.h /^ size_t eh_frame_hdr_size;$/;" m struct:elfobj +eh_frame_hdr_t include/dwarf.h /^} __attribute__((packed)) eh_frame_hdr_t;$/;" t typeref:struct:eh_frame_hdr +eh_frame_ptr include/dwarf.h /^ uint32_t eh_frame_ptr;$/;" m struct:eh_frame_hdr +eh_frame_ptr_enc include/dwarf.h /^ uint8_t eh_frame_ptr_enc;$/;" m struct:eh_frame_hdr +eh_frame_vec include/dwarf.h /^typedef struct eh_frame_vec {$/;" s +eh_frame_vec_t include/dwarf.h /^} eh_frame_vec_t;$/;" t typeref:struct:eh_frame_vec +ehdr32 include/libelfmaster.h /^ Elf32_Ehdr *ehdr32;$/;" m union:elfobj::__anon2 +ehdr64 include/libelfmaster.h /^ Elf64_Ehdr *ehdr64;$/;" m union:elfobj::__anon2 +elf_address_pointer src/libelfmaster.c /^elf_address_pointer(struct elfobj *obj, uint64_t address)$/;" f +elf_arch include/libelfmaster.h /^typedef enum elf_arch {$/;" g +elf_arch_t include/libelfmaster.h /^} elf_arch_t;$/;" t typeref:enum:elf_arch +elf_basename src/libelfmaster.c /^elf_basename(elfobj_t *obj)$/;" f +elf_class include/libelfmaster.h /^typedef enum elf_class {$/;" g +elf_class src/libelfmaster.c /^elf_class(elfobj_t *obj)$/;" f +elf_class_t include/libelfmaster.h /^} elf_class_t;$/;" t typeref:enum:elf_class +elf_close_object src/libelfmaster.c /^elf_close_object(elfobj_t *obj)$/;" f +elf_data_base src/libelfmaster.c /^elf_data_base(struct elfobj *obj)$/;" f +elf_data_filesz src/libelfmaster.c /^elf_data_filesz(elfobj_t *obj)$/;" f +elf_data_offset src/libelfmaster.c /^elf_data_offset(struct elfobj *obj)$/;" f +elf_dynamic_entry include/libelfmaster.h /^typedef struct elf_dynamic_entry {$/;" s +elf_dynamic_entry_t include/libelfmaster.h /^} elf_dynamic_entry_t;$/;" t typeref:struct:elf_dynamic_entry +elf_dynamic_iterator include/libelfmaster.h /^typedef struct elf_dynamic_iterator {$/;" s +elf_dynamic_iterator_init src/libelfmaster.c /^elf_dynamic_iterator_init(struct elfobj *obj, struct elf_dynamic_iterator *iter)$/;" f +elf_dynamic_iterator_next src/libelfmaster.c /^elf_dynamic_iterator_next(struct elf_dynamic_iterator *iter,$/;" f +elf_dynamic_iterator_t include/libelfmaster.h /^} elf_dynamic_iterator_t;$/;" t typeref:struct:elf_dynamic_iterator +elf_dynamic_string src/libelfmaster.c /^elf_dynamic_string(struct elfobj *obj, uint64_t offset)$/;" f +elf_dynsym_iterator include/libelfmaster.h /^typedef struct elf_dynsym_iterator {$/;" s +elf_dynsym_iterator_init src/libelfmaster.c /^elf_dynsym_iterator_init(struct elfobj *obj, struct elf_dynsym_iterator *iter)$/;" f +elf_dynsym_iterator_next src/libelfmaster.c /^elf_dynsym_iterator_next(struct elf_dynsym_iterator *iter,$/;" f +elf_dynsym_iterator_t include/libelfmaster.h /^} elf_dynsym_iterator_t;$/;" t typeref:struct:elf_dynsym_iterator +elf_eh_frame include/libelfmaster.h /^typedef struct elf_eh_frame {$/;" s +elf_eh_frame_iterator include/libelfmaster.h /^typedef struct elf_eh_frame_iterator {$/;" s +elf_eh_frame_iterator_init src/libelfmaster.c /^elf_eh_frame_iterator_init(struct elfobj *obj, struct elf_eh_frame_iterator *iter)$/;" f +elf_eh_frame_iterator_next src/libelfmaster.c /^elf_eh_frame_iterator_next(struct elf_eh_frame_iterator *iter,$/;" f +elf_eh_frame_iterator_t include/libelfmaster.h /^} elf_eh_frame_iterator_t;$/;" t typeref:struct:elf_eh_frame_iterator +elf_eh_frame_node include/internal.h /^struct elf_eh_frame_node {$/;" s +elf_eh_frame_t include/libelfmaster.h /^} elf_eh_frame_t;$/;" t typeref:struct:elf_eh_frame +elf_entry_point src/libelfmaster.c /^elf_entry_point(struct elfobj *obj)$/;" f +elf_error include/libelfmaster.h /^typedef struct elf_error {$/;" s +elf_error_msg src/libelfmaster.c /^elf_error_msg(elf_error_t *error)$/;" f +elf_error_set src/internal.c /^elf_error_set(elf_error_t *error, const char *fmt, ...)$/;" f +elf_error_t include/libelfmaster.h /^} elf_error_t;$/;" t typeref:struct:elf_error +elf_fde_node include/internal.h /^typedef struct elf_fde_node {$/;" s +elf_fde_node include/internal.h /^} elf_fde_node;$/;" t typeref:struct:elf_fde_node +elf_flags src/libelfmaster.c /^elf_flags(elfobj_t *obj, elf_obj_flags_t flag)$/;" f +elf_iterator_res include/libelfmaster.h /^typedef enum elf_iterator_res {$/;" g +elf_iterator_res_t include/libelfmaster.h /^} elf_iterator_res_t;$/;" t typeref:enum:elf_iterator_res +elf_linking_type include/libelfmaster.h /^typedef enum elf_linking_type {$/;" g +elf_linking_type src/libelfmaster.c /^elf_linking_type(elfobj_t *obj)$/;" f +elf_linking_type_t include/libelfmaster.h /^} elf_linking_type_t;$/;" t typeref:enum:elf_linking_type +elf_machine src/libelfmaster.c /^elf_machine(struct elfobj *obj)$/;" f +elf_malloc_node include/internal.h /^typedef struct elf_malloc_node {$/;" s +elf_malloc_node_t include/internal.h /^} elf_malloc_node_t;$/;" t typeref:struct:elf_malloc_node +elf_map_loadable_segments src/libelfmaster.c /^elf_map_loadable_segments(struct elfobj *obj, struct elf_mapping *mapping,$/;" f +elf_mapping include/libelfmaster.h /^typedef struct elf_mapping {$/;" s +elf_mapping_t include/libelfmaster.h /^} elf_mapping_t;$/;" t typeref:struct:elf_mapping +elf_note_entry include/libelfmaster.h /^typedef struct elf_note_entry {$/;" s +elf_note_entry_t include/libelfmaster.h /^} elf_note_entry_t;$/;" t typeref:struct:elf_note_entry +elf_note_iterator include/libelfmaster.h /^typedef struct elf_note_iterator {$/;" s +elf_note_iterator_init src/libelfmaster.c /^elf_note_iterator_init(struct elfobj *obj, struct elf_note_iterator *iter)$/;" f +elf_note_iterator_next src/libelfmaster.c /^elf_note_iterator_next(struct elf_note_iterator *iter,$/;" f +elf_note_iterator_t include/libelfmaster.h /^} elf_note_iterator_t;$/;" t typeref:struct:elf_note_iterator +elf_obj_flags include/libelfmaster.h /^typedef enum elf_obj_flags {$/;" g +elf_obj_flags_t include/libelfmaster.h /^} elf_obj_flags_t;$/;" t typeref:enum:elf_obj_flags +elf_offset_pointer src/libelfmaster.c /^elf_offset_pointer(elfobj_t *obj, uint64_t off)$/;" f +elf_open_object src/libelfmaster.c /^elf_open_object(const char *path, struct elfobj *obj, uint64_t load_flags,$/;" f +elf_pathname src/libelfmaster.c /^elf_pathname(elfobj_t *obj)$/;" f +elf_plt include/libelfmaster.h /^typedef struct elf_plt {$/;" s +elf_plt_by_name src/libelfmaster.c /^elf_plt_by_name(struct elfobj *obj, const char *name, struct elf_plt *entry)$/;" f +elf_plt_iterator include/libelfmaster.h /^typedef struct elf_plt_iterator {$/;" s +elf_plt_iterator_init src/libelfmaster.c /^elf_plt_iterator_init(struct elfobj *obj, struct elf_plt_iterator *iter)$/;" f +elf_plt_iterator_next src/libelfmaster.c /^elf_plt_iterator_next(struct elf_plt_iterator *iter, struct elf_plt *entry)$/;" f +elf_plt_iterator_t include/libelfmaster.h /^} elf_plt_iterator_t;$/;" t typeref:struct:elf_plt_iterator +elf_plt_node include/internal.h /^typedef struct elf_plt_node {$/;" s +elf_plt_node_t include/internal.h /^} elf_plt_node_t;$/;" t typeref:struct:elf_plt_node +elf_plt_t include/libelfmaster.h /^} elf_plt_t;$/;" t typeref:struct:elf_plt +elf_pltgot_entry include/libelfmaster.h /^typedef struct elf_pltgot_entry {$/;" s +elf_pltgot_entry_t include/libelfmaster.h /^} elf_pltgot_entry_t;$/;" t typeref:struct:elf_pltgot_entry +elf_pltgot_flag_string src/libelfmaster.c /^elf_pltgot_flag_string(uint32_t flags)$/;" f +elf_pltgot_iterator include/libelfmaster.h /^typedef struct elf_pltgot_iterator {$/;" s +elf_pltgot_iterator_init src/libelfmaster.c /^elf_pltgot_iterator_init(struct elfobj *obj, struct elf_pltgot_iterator *iter)$/;" f +elf_pltgot_iterator_next src/libelfmaster.c /^elf_pltgot_iterator_next(struct elf_pltgot_iterator *iter, struct elf_pltgot_entry *entry)$/;" f +elf_pltgot_iterator_t include/libelfmaster.h /^} elf_pltgot_iterator_t;$/;" t typeref:struct:elf_pltgot_iterator +elf_read_address src/libelfmaster.c /^elf_read_address(elfobj_t *obj, uint64_t addr, uint64_t *out, typewidth_t width)$/;" f +elf_read_offset src/libelfmaster.c /^elf_read_offset(elfobj_t *obj, uint64_t offset, uint64_t *out, typewidth_t width)$/;" f +elf_rel_helper_node include/internal.h /^struct elf_rel_helper_node {$/;" s +elf_reloc_type_string src/libelfmaster.c /^elf_reloc_type_string(struct elfobj *obj, uint32_t r_type)$/;" f +elf_relocation include/libelfmaster.h /^struct elf_relocation {$/;" s +elf_relocation_iterator include/libelfmaster.h /^typedef struct elf_relocation_iterator {$/;" s +elf_relocation_iterator_init src/libelfmaster.c /^elf_relocation_iterator_init(struct elfobj *obj,$/;" f +elf_relocation_iterator_next src/libelfmaster.c /^elf_relocation_iterator_next(struct elf_relocation_iterator *iter,$/;" f +elf_relocation_iterator_t include/libelfmaster.h /^} elf_relocation_iterator_t;$/;" t typeref:struct:elf_relocation_iterator +elf_section include/libelfmaster.h /^struct elf_section {$/;" s +elf_section_by_index src/libelfmaster.c /^elf_section_by_index(struct elfobj *obj, uint32_t index,$/;" f +elf_section_by_name src/libelfmaster.c /^elf_section_by_name(struct elfobj *obj, const char *name,$/;" f +elf_section_iterator include/libelfmaster.h /^typedef struct elf_section_iterator {$/;" s +elf_section_iterator_init src/libelfmaster.c /^elf_section_iterator_init(struct elfobj *obj, struct elf_section_iterator *iter)$/;" f +elf_section_iterator_next src/libelfmaster.c /^elf_section_iterator_next(struct elf_section_iterator *iter,$/;" f +elf_section_iterator_t include/libelfmaster.h /^} elf_section_iterator_t;$/;" t typeref:struct:elf_section_iterator +elf_section_name_by_index src/libelfmaster.c /^elf_section_name_by_index(struct elfobj *obj, uint32_t index)$/;" f +elf_section_node include/internal.h /^struct elf_section_node {$/;" s +elf_section_pointer src/libelfmaster.c /^elf_section_pointer(elfobj_t *obj, void *shdr)$/;" f +elf_section_string src/libelfmaster.c /^elf_section_string(struct elfobj *obj, uint64_t offset)$/;" f +elf_segment include/libelfmaster.h /^struct elf_segment {$/;" s +elf_segment_iterator include/libelfmaster.h /^typedef struct elf_segment_iterator {$/;" s +elf_segment_iterator_init src/libelfmaster.c /^elf_segment_iterator_init(struct elfobj *obj, struct elf_segment_iterator *iter)$/;" f +elf_segment_iterator_next src/libelfmaster.c /^elf_segment_iterator_next(struct elf_segment_iterator *iter,$/;" f +elf_segment_iterator_t include/libelfmaster.h /^} elf_segment_iterator_t;$/;" t typeref:struct:elf_segment_iterator +elf_segment_type_string src/libelfmaster.c /^elf_segment_type_string(uint32_t type)$/;" f +elf_shared_object include/libelfmaster.h /^typedef struct elf_shared_object {$/;" s +elf_shared_object_iterator include/libelfmaster.h /^typedef struct elf_shared_object_iterator {$/;" s +elf_shared_object_iterator_init src/libelfmaster.c /^elf_shared_object_iterator_init(struct elfobj *obj,$/;" f +elf_shared_object_iterator_next src/libelfmaster.c /^elf_shared_object_iterator_next(struct elf_shared_object_iterator *iter,$/;" f +elf_shared_object_iterator_t include/libelfmaster.h /^} elf_shared_object_iterator_t;$/;" t typeref:struct:elf_shared_object_iterator +elf_shared_object_node include/internal.h /^typedef struct elf_shared_object_node {$/;" s +elf_shared_object_node_t include/internal.h /^} elf_shared_object_node_t;$/;" t typeref:struct:elf_shared_object_node +elf_shared_object_t include/libelfmaster.h /^} elf_shared_object_t;$/;" t typeref:struct:elf_shared_object +elf_symbol include/libelfmaster.h /^struct elf_symbol {$/;" s +elf_symbol_by_index src/libelfmaster.c /^elf_symbol_by_index(struct elfobj *obj, unsigned int index,$/;" f +elf_symbol_by_name src/libelfmaster.c /^elf_symbol_by_name(struct elfobj *obj, const char *name,$/;" f +elf_symbol_node include/internal.h /^struct elf_symbol_node {$/;" s +elf_symtab_iterator include/libelfmaster.h /^typedef struct elf_symtab_iterator {$/;" s +elf_symtab_iterator_init src/libelfmaster.c /^elf_symtab_iterator_init(struct elfobj *obj, struct elf_symtab_iterator *iter)$/;" f +elf_symtab_iterator_next src/libelfmaster.c /^elf_symtab_iterator_next(struct elf_symtab_iterator *iter,$/;" f +elf_symtab_iterator_t include/libelfmaster.h /^} elf_symtab_iterator_t;$/;" t typeref:struct:elf_symtab_iterator +elf_symtab_string src/libelfmaster.c /^elf_symtab_string(struct elfobj *obj, uint64_t offset)$/;" f +elf_text_base src/libelfmaster.c /^elf_text_base(struct elfobj *obj)$/;" f +elf_text_filesz src/libelfmaster.c /^elf_text_filesz(elfobj_t *obj)$/;" f +elf_text_offset src/libelfmaster.c /^elf_text_offset(struct elfobj *obj)$/;" f +elf_type src/libelfmaster.c /^elf_type(struct elfobj *obj)$/;" f +elfclass32 include/libelfmaster.h /^ elfclass32$/;" e enum:elf_class +elfclass64 include/libelfmaster.h /^ elfclass64,$/;" e enum:elf_class +elfobj include/libelfmaster.h /^typedef struct elfobj {$/;" s +elfobj_t include/libelfmaster.h /^} elfobj_t;$/;" t typeref:struct:elfobj +entry_point include/libelfmaster.h /^ uint64_t entry_point;$/;" m struct:elfobj +entsize include/internal.h /^ uint64_t entsize;$/;" m struct:elf_section_node +entsize include/libelfmaster.h /^ uint64_t entsize;$/;" m struct:elf_section +epilog configure /^epilog()$/;" f +exists include/libelfmaster.h /^ bool exists;$/;" m struct:elfobj::__anon11 +fd include/libelfmaster.h /^ int fd;$/;" m struct:elf_shared_object_iterator +fde_count include/dwarf.h /^ uint32_t fde_count;$/;" m struct:eh_frame_hdr +fde_count include/libelfmaster.h /^ size_t fde_count; \/* holds the number of fde's after they've been parsed *\/$/;" m struct:elfobj +fde_count_enc include/dwarf.h /^ uint8_t fde_count_enc;$/;" m struct:eh_frame_hdr +fde_entry_offset include/dwarf.h /^ uint64_t fde_entry_offset;$/;" m struct:eh_frame_vec +file_entry include/internal.h /^struct file_entry {$/;" s +file_entry_new include/internal.h /^struct file_entry_new {$/;" s +filesz include/libelfmaster.h /^ uint64_t filesz;$/;" m struct:elf_segment +fini include/libelfmaster.h /^ } fini;$/;" m struct:elfobj::__anon11 typeref:struct:elfobj::__anon11::__anon23 +fini_array include/libelfmaster.h /^ } fini_array;$/;" m struct:elfobj::__anon11 typeref:struct:elfobj::__anon11::__anon13 +fini_array_size include/libelfmaster.h /^ size_t fini_array_size;$/;" m struct:elfobj +fini_array_vaddr include/libelfmaster.h /^ uint64_t fini_array_vaddr;$/;" m struct:elfobj +flag include/libelfmaster.h /^ uint32_t flag;$/;" m struct:pt_load +flags include/internal.h /^ int flags;$/;" m struct:file_entry +flags include/internal.h /^ int32_t flags;$/;" m struct:file_entry_new +flags include/libelfmaster.h /^ elf_obj_flags_t flags;$/;" m struct:elfobj +flags include/libelfmaster.h /^ uint32_t flags; \/* can be set to ELF_PLTGOT_* flags *\/$/;" m struct:elf_pltgot_entry +flags include/libelfmaster.h /^ uint32_t flags;$/;" m struct:elf_segment +flags include/libelfmaster.h /^ uint32_t flags;$/;" m struct:elf_shared_object_iterator +flags include/libelfmaster.h /^ uint64_t flags;$/;" m struct:elf_section +flags include/libelfmaster.h /^ unsigned int flags;$/;" m struct:elf_mapping +free_arrays src/internal.c /^free_arrays(elfobj_t *obj)$/;" f +free_caches src/internal.c /^free_caches(elfobj_t *obj)$/;" f +free_lists src/internal.c /^free_lists(elfobj_t *obj)$/;" f +free_misc src/internal.c /^void free_misc(elfobj_t *obj)$/;" f +generate configure /^generate()$/;" f +generate_stdout configure /^generate_stdout()$/;" f +gotsize include/libelfmaster.h /^ size_t gotsize;$/;" m struct:elf_pltgot_iterator +hash include/libelfmaster.h /^ } hash;$/;" m struct:elfobj::__anon11 typeref:struct:elfobj::__anon11::__anon24 +head include/libelfmaster.h /^ struct elf_rel_helper_node *current, *head;$/;" m struct:elf_relocation_iterator typeref:struct:elf_relocation_iterator:: +hwcap include/internal.h /^ uint64_t hwcap;$/;" m struct:file_entry_new +i386 include/libelfmaster.h /^ i386,$/;" e enum:elf_arch +index include/internal.h /^ unsigned int index; \/\/ used by elf_shared_object iterator$/;" m struct:elf_shared_object_node +index include/libelfmaster.h /^ unsigned int index;$/;" m struct:elf_dynamic_iterator +index include/libelfmaster.h /^ unsigned int index;$/;" m struct:elf_mapping +index include/libelfmaster.h /^ unsigned int index;$/;" m struct:elf_note_iterator +index include/libelfmaster.h /^ unsigned int index;$/;" m struct:elf_pltgot_iterator +index include/libelfmaster.h /^ unsigned int index;$/;" m struct:elf_relocation_iterator +index include/libelfmaster.h /^ unsigned int index;$/;" m struct:elf_section_iterator +index include/libelfmaster.h /^ unsigned int index;$/;" m struct:elf_segment +index include/libelfmaster.h /^ unsigned int index;$/;" m struct:elf_segment_iterator +index include/libelfmaster.h /^ unsigned int index;$/;" m struct:elf_shared_object_iterator +info include/internal.h /^ uint32_t info;$/;" m struct:elf_section_node +info include/libelfmaster.h /^ uint32_t info;$/;" m struct:elf_section +init include/libelfmaster.h /^ } init;$/;" m struct:elfobj::__anon11 typeref:struct:elfobj::__anon11::__anon22 +init_array include/libelfmaster.h /^ } init_array;$/;" m struct:elfobj::__anon11 typeref:struct:elfobj::__anon11::__anon12 +init_array_size include/libelfmaster.h /^ size_t init_array_size;$/;" m struct:elfobj +init_array_vaddr include/libelfmaster.h /^ uint64_t init_array_vaddr;$/;" m struct:elfobj +initial_loc include/dwarf.h /^ uint64_t initial_loc;$/;" m struct:eh_frame_vec +insane_headers src/internal.c /^insane_headers(elfobj_t *obj)$/;" f +internal_section_count include/libelfmaster.h /^ size_t internal_section_count;$/;" m struct:elfobj +internal_shstrtab_size include/libelfmaster.h /^ size_t internal_shstrtab_size;$/;" m struct:elfobj +key include/internal.h /^ uint32_t key;$/;" m struct:file_entry +key include/internal.h /^ uint32_t key;$/;" m struct:file_entry_new +ldso_cache_bsearch src/internal.c /^ldso_cache_bsearch(struct elf_shared_object_iterator *iter,$/;" f +ldso_cache_check_flags src/internal.c /^ldso_cache_check_flags(struct elf_shared_object_iterator *iter,$/;" f file: +ldso_cache_cmp src/internal.c /^ldso_cache_cmp(const char *p1, const char *p2)$/;" f file: +ldso_cache_verify_offset src/internal.c 334;" d file: +ldso_cleanup src/internal.c /^ldso_cleanup(struct elf_shared_object_iterator *iter)$/;" f +ldso_free_malloc_list src/internal.c /^ldso_free_malloc_list(struct elf_shared_object_iterator *iter)$/;" f +ldso_insert_yield_cache src/internal.c /^ldso_insert_yield_cache(struct elf_shared_object_iterator *iter,$/;" f +ldso_insert_yield_entry src/internal.c /^ldso_insert_yield_entry(struct elf_shared_object_iterator *iter,$/;" f file: +ldso_malloc src/internal.c /^ldso_malloc(struct elf_shared_object_iterator *iter, size_t size)$/;" f file: +ldso_recursive_cache_resolve src/internal.c /^ldso_recursive_cache_resolve(struct elf_shared_object_iterator *iter,$/;" f +ldso_strdup src/internal.c /^ldso_strdup(struct elf_shared_object_iterator *iter, const char *s)$/;" f file: +len include/internal.h /^ size_t len;$/;" m struct:elf_fde_node +len include/internal.h /^ size_t len;$/;" m struct:elf_eh_frame_node +len include/libelfmaster.h /^ size_t len;$/;" m struct:elf_eh_frame +len include/libelfmaster.h /^ size_t len;$/;" m struct:elf_mapping +len_strings include/internal.h /^ uint32_t len_strings; \/* size of string table *\/$/;" m struct:cache_file_new +libs include/internal.h /^ struct file_entry libs[0];$/;" m struct:cache_file typeref:struct:cache_file::file_entry +libs include/internal.h /^ struct file_entry_new libs[0]; \/* Entries describing libraries *\/$/;" m struct:cache_file_new typeref:struct:cache_file_new::file_entry_new +likely include/internal.h 38;" d +likely include/internal.h 41;" d +link include/internal.h /^ uint32_t link;$/;" m struct:elf_section_node +link include/libelfmaster.h /^ uint32_t link;$/;" m struct:elf_section +list include/libelfmaster.h /^ LIST_HEAD(elf_rel_helper_list, elf_rel_helper_node) list;$/;" m struct:elf_relocation_iterator +list include/libelfmaster.h /^ } list;$/;" m struct:elfobj typeref:struct:elfobj::__anon10 +load_count include/libelfmaster.h /^ size_t load_count;$/;" m struct:elfobj +load_dynamic_segment_data src/internal.c /^load_dynamic_segment_data(struct elfobj *obj)$/;" f +load_flags include/libelfmaster.h /^ uint64_t load_flags;$/;" m struct:elfobj +magic include/internal.h /^ char magic[sizeof CACHEMAGIC - 1];$/;" m struct:cache_file +magic include/internal.h /^ char magic[sizeof CACHEMAGIC_NEW - 1];$/;" m struct:cache_file_new +main examples/checksec.c /^int main(int argc, char **argv)$/;" f +main examples/eh_frame.c /^int main(int argc, char **argv)$/;" f +main examples/elfparse.c /^int main(int argc, char **argv)$/;" f +main examples/ldd.c /^int main(int argc, char **argv)$/;" f +main examples/plt_dump.c /^int main(int argc, char **argv)$/;" f +main examples/plt_dump2.c /^int main(int argc, char **argv)$/;" f +main examples/pltgot.c /^int main(int argc, char **argv)$/;" f +main examples/pointers.c /^int main(void)$/;" f +main examples/pointers.s /^main:$/;" l +main examples/read_mem.c /^int main(int argc, char **argv)$/;" f +main examples/sections.c /^int main(int argc, char **argv)$/;" f +main examples/symbols.c /^int main(int argc, char **argv)$/;" f +main examples/test.c /^int main(void)$/;" f +main utils/stripx.c /^int main(int argc, char **argv)$/;" f +malloc_list include/libelfmaster.h /^ LIST_HEAD(ldso_malloc_list, elf_malloc_node) malloc_list;$/;" m struct:elf_shared_object_iterator +mem include/libelfmaster.h /^ uint8_t *mem;$/;" m struct:elfobj +mem include/libelfmaster.h /^ uint8_t *mem[MAX_LOADABLE_MAPPINGS];$/;" m struct:elf_mapping +mem include/libelfmaster.h /^ void *mem;$/;" m struct:elf_note_entry +mem include/libelfmaster.h /^ void *mem;$/;" m struct:elf_shared_object_iterator +memsz include/libelfmaster.h /^ uint64_t memsz;$/;" m struct:elf_segment +name include/internal.h /^ char *name;$/;" m struct:elf_section_node +name include/internal.h /^ const char *name;$/;" m struct:elf_symbol_node +name include/libelfmaster.h /^ char *name;$/;" m struct:elf_section +name include/libelfmaster.h /^ const char *name;$/;" m struct:elf_symbol +nlibs include/internal.h /^ uint32_t nlibs; \/* number of entries *\/$/;" m struct:cache_file_new +nlibs include/internal.h /^ uint32_t nlibs;$/;" m struct:cache_file +note32 include/libelfmaster.h /^ Elf32_Nhdr *note32;$/;" m union:elf_note_iterator::__anon27 +note32 include/libelfmaster.h /^ Elf32_Nhdr *note32;$/;" m union:elfobj::__anon8 +note64 include/libelfmaster.h /^ Elf64_Nhdr *note64;$/;" m union:elf_note_iterator::__anon27 +note64 include/libelfmaster.h /^ Elf64_Nhdr *note64;$/;" m union:elfobj::__anon8 +note_offset include/libelfmaster.h /^ uint64_t note_offset; \/* Offset of first note section found *\/$/;" m struct:elfobj +note_size include/libelfmaster.h /^ size_t note_size;$/;" m struct:elfobj +obj include/libelfmaster.h /^ elfobj_t *obj;$/;" m struct:elf_dynamic_iterator +obj include/libelfmaster.h /^ elfobj_t *obj;$/;" m struct:elf_note_iterator +obj include/libelfmaster.h /^ elfobj_t *obj;$/;" m struct:elf_pltgot_iterator +obj include/libelfmaster.h /^ elfobj_t *obj;$/;" m struct:elf_relocation_iterator +obj include/libelfmaster.h /^ elfobj_t *obj;$/;" m struct:elf_section_iterator +obj include/libelfmaster.h /^ elfobj_t *obj;$/;" m struct:elf_segment_iterator +obj include/libelfmaster.h /^ elfobj_t *obj;$/;" m struct:elf_shared_object_iterator +offset include/internal.h /^ uint64_t offset;$/;" m struct:elf_section_node +offset include/libelfmaster.h /^ uint64_t offset;$/;" m struct:elfobj::__anon11::__anon25 +offset include/libelfmaster.h /^ uint64_t offset;$/;" m struct:elf_pltgot_entry +offset include/libelfmaster.h /^ uint64_t offset;$/;" m struct:elf_relocation +offset include/libelfmaster.h /^ uint64_t offset;$/;" m struct:elf_section +offset include/libelfmaster.h /^ uint64_t offset;$/;" m struct:elf_segment +original_ep src/internal.c /^original_ep(elfobj_t *obj)$/;" f file: +osversion include/internal.h /^ uint32_t osversion;$/;" m struct:file_entry_new +paddr include/libelfmaster.h /^ uint64_t paddr;$/;" m struct:elf_segment +path include/internal.h /^ char *path;$/;" m struct:elf_shared_object_node +path include/libelfmaster.h /^ char *path;$/;" m struct:elf_shared_object +path include/libelfmaster.h /^ const char *path;$/;" m struct:elfobj +pathsearch configure /^pathsearch()$/;" f +pc_begin include/internal.h /^ unsigned long long pc_begin;$/;" m struct:elf_eh_frame_node +pc_begin include/libelfmaster.h /^ unsigned long long pc_begin;$/;" m struct:elf_eh_frame +pc_end include/internal.h /^ unsigned long pc_end;$/;" m struct:elf_fde_node +pc_end include/internal.h /^ unsigned long long pc_end;$/;" m struct:elf_eh_frame_node +pc_end include/libelfmaster.h /^ unsigned long long pc_end;$/;" m struct:elf_eh_frame +pc_start include/internal.h /^ unsigned long pc_start;$/;" m struct:elf_fde_node +phdr32 include/libelfmaster.h /^ Elf32_Phdr *phdr32;$/;" m union:elfobj::__anon3 +phdr32 include/libelfmaster.h /^ Elf32_Phdr phdr32;$/;" m union:pt_load::__anon1 +phdr64 include/libelfmaster.h /^ Elf64_Phdr *phdr64;$/;" m union:elfobj::__anon3 +phdr64 include/libelfmaster.h /^ Elf64_Phdr phdr64;$/;" m union:pt_load::__anon1 +phdr_sanity src/internal.c /^phdr_sanity(elfobj_t *obj, void *phdr)$/;" f +plt include/libelfmaster.h /^ LIST_HEAD(elf_plt_list, elf_plt_node) plt;$/;" m struct:elfobj::__anon10 +plt include/libelfmaster.h /^ struct hsearch_data plt;$/;" m struct:elfobj::__anon9 typeref:struct:elfobj::__anon9::hsearch_data +pltgot include/libelfmaster.h /^ } pltgot;$/;" m struct:elfobj::__anon11 typeref:struct:elfobj::__anon11::__anon14 +pltgot include/libelfmaster.h /^ void *pltgot;$/;" m struct:elf_pltgot_iterator +pltrel include/libelfmaster.h /^ } pltrel;$/;" m struct:elfobj::__anon11 typeref:struct:elfobj::__anon11::__anon17 +pt_load include/libelfmaster.h /^ struct pt_load *pt_load;$/;" m struct:elfobj typeref:struct:elfobj::pt_load +pt_load include/libelfmaster.h /^struct pt_load {$/;" s +ptr include/internal.h /^ void *ptr;$/;" m struct:elf_malloc_node +reconstruct_elf_sections src/internal.c /^reconstruct_elf_sections(elfobj_t *obj, elf_error_t *e)$/;" f +rel include/libelfmaster.h /^ } rel;$/;" m struct:elfobj::__anon11 typeref:struct:elfobj::__anon11::__anon19 +rel32 include/internal.h /^ Elf32_Rel *rel32;$/;" m union:elf_rel_helper_node::__anon28 +rel64 include/internal.h /^ Elf64_Rel *rel64;$/;" m union:elf_rel_helper_node::__anon28 +rela include/libelfmaster.h /^ } rela;$/;" m struct:elfobj::__anon11 typeref:struct:elfobj::__anon11::__anon18 +rela32 include/internal.h /^ Elf32_Rela *rela32;$/;" m union:elf_rel_helper_node::__anon29 +rela64 include/internal.h /^ Elf64_Rela *rela64;$/;" m union:elf_rel_helper_node::__anon29 +relaent include/libelfmaster.h /^ } relaent;$/;" m struct:elfobj::__anon11 typeref:struct:elfobj::__anon11::__anon16 +relent include/libelfmaster.h /^ } relent;$/;" m struct:elfobj::__anon11 typeref:struct:elfobj::__anon11::__anon15 +resolve include/libelfmaster.h /^ bool resolve;$/;" m struct:elf_shared_object_iterator +resolve_plt_addr src/internal.c /^resolve_plt_addr(elfobj_t *obj)$/;" f +runpath include/libelfmaster.h /^ } runpath;$/;" m struct:elfobj::__anon11 typeref:struct:elfobj::__anon11::__anon25 +sanity_check src/internal.c /^sanity_check(uint64_t offset, uint64_t limit)$/;" f +section_count include/libelfmaster.h /^ size_t section_count;$/;" m struct:elfobj +section_name include/internal.h /^ char *section_name;$/;" m struct:elf_rel_helper_node +section_name_cmp src/internal.c /^section_name_cmp(const void *p0, const void *p1)$/;" f +sections include/libelfmaster.h /^ LIST_HEAD(elf_section_list, elf_section_node) sections;$/;" m struct:elfobj::__anon10 +sections include/libelfmaster.h /^ struct elf_section **sections;$/;" m struct:elfobj typeref:struct:elfobj::elf_section +segment_count include/libelfmaster.h /^ size_t segment_count;$/;" m struct:elfobj +shared_objects include/libelfmaster.h /^ LIST_HEAD(elf_shared_object_list, elf_shared_object_node) shared_objects;$/;" m struct:elfobj::__anon10 +shdr32 include/libelfmaster.h /^ Elf32_Shdr *shdr32;$/;" m union:elfobj::__anon4 +shdr64 include/libelfmaster.h /^ Elf64_Shdr *shdr64;$/;" m union:elfobj::__anon4 +shdrindex include/libelfmaster.h /^ size_t shdrindex; \/\/ used only when reconstructing sections$/;" m struct:elfobj +shdrname include/libelfmaster.h /^ char *shdrname;$/;" m struct:elf_relocation +shndx include/internal.h /^ uint16_t shndx;$/;" m struct:elf_symbol_node +shndx include/libelfmaster.h /^ uint16_t shndx;$/;" m struct:elf_symbol +shstrtab include/libelfmaster.h /^ char *shstrtab;$/;" m struct:elfobj +size include/internal.h /^ size_t size;$/;" m struct:elf_rel_helper_node +size include/internal.h /^ size_t size;$/;" m struct:elf_section_node +size include/internal.h /^ uint64_t size;$/;" m struct:elf_symbol_node +size include/libelfmaster.h /^ uint64_t size;$/;" m struct:elfobj::__anon11::__anon12 +size include/libelfmaster.h /^ uint64_t size;$/;" m struct:elfobj::__anon11::__anon13 +size include/libelfmaster.h /^ uint64_t size;$/;" m struct:elfobj::__anon11::__anon15 +size include/libelfmaster.h /^ uint64_t size;$/;" m struct:elfobj::__anon11::__anon16 +size include/libelfmaster.h /^ uint64_t size;$/;" m struct:elfobj::__anon11::__anon17 +size include/libelfmaster.h /^ uint64_t size;$/;" m struct:elfobj::__anon11::__anon18 +size include/libelfmaster.h /^ uint64_t size;$/;" m struct:elfobj::__anon11::__anon19 +size include/libelfmaster.h /^ uint64_t size;$/;" m struct:elfobj::__anon11::__anon21 +size include/libelfmaster.h /^ size_t size;$/;" m struct:elf_note_entry +size include/libelfmaster.h /^ size_t size;$/;" m struct:elf_section +size include/libelfmaster.h /^ size_t size;$/;" m struct:elfobj +size include/libelfmaster.h /^ uint64_t size;$/;" m struct:elf_symbol +sort_elf_sections src/internal.c /^sort_elf_sections(elfobj_t *obj, elf_error_t *error)$/;" f +st include/libelfmaster.h /^ struct stat st;$/;" m struct:elf_shared_object_iterator typeref:struct:elf_shared_object_iterator::stat +strindex include/libelfmaster.h /^ size_t strindex; \/\/ used only when creating custom strtabs$/;" m struct:elfobj +string include/libelfmaster.h /^ char string[MAX_ERROR_STR_LEN];$/;" m struct:elf_error +strtab include/libelfmaster.h /^ char *strtab;$/;" m struct:elfobj +symname include/internal.h /^ char *symname;$/;" m struct:elf_plt_node +symname include/libelfmaster.h /^ char *symname;$/;" m struct:elf_plt +symname include/libelfmaster.h /^ char *symname;$/;" m struct:elf_relocation +symtab include/libelfmaster.h /^ LIST_HEAD(elf_symtab_list, elf_symbol_node) symtab;$/;" m struct:elfobj::__anon10 +symtab include/libelfmaster.h /^ struct hsearch_data symtab;$/;" m struct:elfobj::__anon9 typeref:struct:elfobj::__anon9::hsearch_data +symtab32 include/libelfmaster.h /^ Elf32_Sym *symtab32;$/;" m union:elfobj::__anon5 +symtab64 include/libelfmaster.h /^ Elf64_Sym *symtab64;$/;" m union:elfobj::__anon5 +symtab_count include/libelfmaster.h /^ size_t symtab_count;$/;" m struct:elfobj +table_enc include/dwarf.h /^ uint8_t table_enc;$/;" m struct:eh_frame_hdr +tag include/libelfmaster.h /^ unsigned int tag;$/;" m struct:elf_dynamic_entry +test_dummy examples/test2.c /^static int test_dummy = 5;$/;" v file: +text_address include/libelfmaster.h /^ uint64_t text_address; \/* text base address *\/$/;" m struct:elfobj +text_offset include/libelfmaster.h /^ uint64_t text_offset;$/;" m struct:elfobj +text_segment_filesz include/libelfmaster.h /^ size_t text_segment_filesz;$/;" m struct:elfobj +type include/internal.h /^ uint32_t type;$/;" m struct:elf_section_node +type include/internal.h /^ uint8_t type;$/;" m struct:elf_symbol_node +type include/libelfmaster.h /^ uint32_t type;$/;" m struct:elfobj::__anon11::__anon17 +type include/libelfmaster.h /^ uint32_t type;$/;" m struct:elf_section +type include/libelfmaster.h /^ uint32_t type;$/;" m struct:elf_segment +type include/libelfmaster.h /^ uint64_t type;$/;" m struct:elf_relocation +type include/libelfmaster.h /^ uint8_t type;$/;" m struct:elf_symbol +type include/libelfmaster.h /^ unsigned int type;$/;" m struct:elf_note_entry +type include/libelfmaster.h /^ unsigned int type;$/;" m struct:elfobj +typewidth include/libelfmaster.h /^typedef enum typewidth {$/;" g +typewidth_t include/libelfmaster.h /^} typewidth_t;$/;" t typeref:enum:typewidth +unlikely include/internal.h 39;" d +unlikely include/internal.h 42;" d +unsupported include/libelfmaster.h /^ unsupported$/;" e enum:elf_arch +unused include/internal.h /^ uint32_t unused[5]; \/* space for future extension *\/$/;" m struct:cache_file_new +vaddr include/libelfmaster.h /^ uint64_t vaddr;$/;" m struct:elf_segment +value include/internal.h /^ uint32_t value;$/;" m struct:file_entry +value include/internal.h /^ uint32_t value;$/;" m struct:file_entry_new +value include/internal.h /^ uint64_t value;$/;" m struct:elf_symbol_node +value include/libelfmaster.h /^ uint64_t value;$/;" m struct:elfobj::__anon11::__anon26 +value include/libelfmaster.h /^ uint64_t value;$/;" m struct:elf_dynamic_entry +value include/libelfmaster.h /^ uint64_t value;$/;" m struct:elf_pltgot_entry +value include/libelfmaster.h /^ uint64_t value;$/;" m struct:elf_symbol +version include/dwarf.h /^ uint8_t version;$/;" m struct:eh_frame_hdr +version include/internal.h /^ char version[sizeof CACHE_VERSION - 1];$/;" m struct:cache_file_new +visibility include/internal.h /^ uint8_t visibility;$/;" m struct:elf_symbol_node +visibility include/libelfmaster.h /^ uint8_t visibility;$/;" m struct:elf_symbol +wordsize include/libelfmaster.h /^ size_t wordsize;$/;" m struct:elf_pltgot_iterator +x64 include/libelfmaster.h /^ x64,$/;" e enum:elf_arch +yield include/libelfmaster.h /^ struct elf_shared_object_node *yield;$/;" m struct:elf_shared_object_iterator typeref:struct:elf_shared_object_iterator::elf_shared_object_node +yield_cache include/libelfmaster.h /^ struct hsearch_data yield_cache;$/;" m struct:elf_shared_object_iterator typeref:struct:elf_shared_object_iterator::hsearch_data +yield_list include/libelfmaster.h /^ LIST_HEAD(ldso_cache_yield_list, elf_shared_object_node) yield_list;$/;" m struct:elf_shared_object_iterator