//-------------------------------------------------------------------------------------------------- static int symbol_by_name(int d, Elf_Shdr *section, char const *name, Elf_Sym **symbol, size_t *index) { Elf_Shdr *strings_section = NULL; char const *strings = NULL; Elf_Sym *symbols = NULL; size_t i, amount; *symbol = NULL; *index = 0; if ( section_by_index(d, section->sh_link, &strings_section) || read_string_table(d, strings_section, &strings) || read_symbol_table(d, section, &symbols) ) return errno; amount = section->sh_size / sizeof(Elf_Sym); for (i = 0; i < amount; ++i) if (!strcmp(name, &strings[symbols[i].st_name])) { *symbol = (Elf_Sym *)malloc(sizeof(Elf_Sym)); if (NULL == *symbol) { free(strings_section); free((void *)strings); free(symbols); return errno; } memcpy(*symbol, symbols + i, sizeof(Elf_Sym)); *index = i; break; } free(strings_section); free((void *)strings); free(symbols); return 0; }
//-------------------------------------------------------------------------------------------------- int get_module_base_address(char const *module_filename, void *handle, void **base) { int descriptor; //file descriptor of shared module Elf_Shdr *dynsym = NULL, *strings_section = NULL; char const *strings = NULL; Elf_Sym *symbols = NULL; size_t i, amount; Elf_Sym *found = NULL; *base = NULL; descriptor = open(module_filename, O_RDONLY); if (descriptor < 0) return errno; if (section_by_type(descriptor, SHT_DYNSYM, &dynsym) || //get ".dynsym" section section_by_index(descriptor, dynsym->sh_link, &strings_section) || read_string_table(descriptor, strings_section, &strings) || read_symbol_table(descriptor, dynsym, &symbols)) { free(strings_section); free((void *)strings); free(symbols); free(dynsym); close(descriptor); return errno; } amount = dynsym->sh_size / sizeof(Elf_Sym); /* Trick to get the module base address in a portable way: * Find the first GLOBAL or WEAK symbol in the symbol table, * look this up with dlsym, then return the difference as the base address */ for (i = 0; i < amount; ++i) { switch(ELF32_ST_BIND(symbols[i].st_info)) { case STB_GLOBAL: case STB_WEAK: found = &symbols[i]; break; default: // Not interested in this symbol break; } } if(found != NULL) { const char *name = &strings[found->st_name]; void *sym = dlsym(handle, name); if(sym != NULL) *base = (void*)((size_t)sym - found->st_value); } free(strings_section); free((void *)strings); free(symbols); free(dynsym); close(descriptor); return *base == NULL; }
int main(int argc, char* argv[]){ ParseArguments(argc, argv); if(InputFile == NULL) { fprintf(stderr, "Input file not specified\n"); exit(EXIT_FAILURE); } FILE* fpin = fopen(InputFile, "r+b"); if(fpin == NULL){ perror("fopen failed: "); exit(EXIT_FAILURE); } // seek to end of file fseek(fpin, 0L, SEEK_END); // get file size unsigned int size = ftell(fpin); // allocate memory uint8_t* InputBuffer = malloc(size); // seek reset fseek(fpin, 0L, SEEK_SET); // read all bytes unsigned int sizeread = fread(InputBuffer, sizeof(uint8_t), size, fpin); if(sizeread != size){ fprintf(stderr, "fread failed.\n"); perror("fread: "); exit(EXIT_FAILURE); } if(*((uint32_t*)&InputBuffer[0]) == EXEC_HEADER) { printf("Type: Executable\n"); r3x_header_t* myheader = (r3x_header_t*)&InputBuffer[0]; printf("Program header Index: 0x%X\n", myheader->program_header); printf("Version (Major).(Minor): %u.%u\n", myheader->major, myheader->minor); printf("Location of .text: %u\n", myheader->r3x_init); printf("Size of .text: %u\n", myheader->r3x_text_size); printf("Location of .symbols: %u\n", myheader->r3x_symbols); printf("Size of .symbols: %u\n", myheader->r3x_symbolsize); printf("Location of data: %u\n", myheader->r3x_data); printf("Size of .data: %u\n", myheader->r3x_data_size); printf("Location of .bss: %u\n", myheader->r3x_bss); printf("Size of .bss: %u\n", myheader->r3x_bss_size); printf("Location of .import: %u\n", myheader->import); printf("Size of .import: %u\n", myheader->import_size); if(myheader->nameaddr - PROG_EXEC_POINT > size || myheader->pulibsheraddr - PROG_EXEC_POINT > size) { printf("Invalid publisher/executable information\n"); } else { printf("Name: %s\n", (char*)&InputBuffer[myheader->nameaddr - PROG_EXEC_POINT]); printf("Publisher: %s\n", (char*)&InputBuffer[myheader->pulibsheraddr - PROG_EXEC_POINT]); } if(myheader->r3x_symbols - PROG_EXEC_POINT > size) { printf("Invalid symbol table\n"); } else { read_symbol_table(myheader, InputBuffer, size, 0); } if(myheader->import - PROG_EXEC_POINT > size) { printf("Invalid .import table\n"); } else { r3x_header_t* Header = myheader; if(Header->import_size == 0) { } else { uint32_t NumberOfImports = Header->import_size / sizeof(r3x_import_t); r3x_import_t* Imports = (r3x_import_t*)&InputBuffer[Header->import - PROG_EXEC_POINT]; printf(".import:\n"); for(unsigned int i = 0; i < NumberOfImports; i++) { if(Imports[i].SymbolName - PROG_EXEC_POINT > size || Imports[i].LibName - PROG_EXEC_POINT > size) { printf("Corrupted .import table!\n"); exit(0); } printf("%u: %s from %s\n", i, (char*)((uintptr_t)((uintptr_t)InputBuffer + Imports[i].SymbolName - PROG_EXEC_POINT)), (char*)((uintptr_t)((uintptr_t)InputBuffer + Imports[i].LibName - PROG_EXEC_POINT))); } } } } else if(*((uint32_t*)&InputBuffer[0]) == DLL_HEADER) { printf("Type: Dynamic Shared Library\n"); r3x_dynamic_header_t* myheader = (r3x_dynamic_header_t*)&InputBuffer[0]; printf("Program header Index: 0x%X\n", 0); printf("Version (Major).(Minor): %u.%u\n", myheader->major, myheader->minor); printf("Location of .text: %u\n", myheader->text_section); printf("Size of .text: %u\n", myheader->text_size); printf("Location of data: %u\n", myheader->data_section); printf("Size of .data: %u\n", myheader->data_size); printf("Location of .bss: %u\n", myheader->bss_section); printf("Size of .bss: %u\n", myheader->bss_size); if(myheader->nameaddr > size || myheader->publisheraddr > size) { printf("Invalid publisher/executable information\n"); } else { printf("Name: %s\n", (char*)&InputBuffer[myheader->nameaddr - 0]); printf("Publisher: %s\n", (char*)&InputBuffer[myheader->publisheraddr - 0]); } printf(".export section: \n"); if(myheader->export_section > size) { printf("Bad Export section\n"); } else { export_struct* myexports = (export_struct*)&InputBuffer[myheader->export_section]; for(unsigned int i = 0; i < myheader->export_size / sizeof(export_struct); i++){ if(myexports[i].function_id > size) { printf("bad export\n"); } else { printf("Export %s, to function at: %u\n", (char*)&InputBuffer[myexports[i].function_id], myexports[i].instruction_pointer); } } } } }
/* exe_commande Descr: Execute les différentes opérations demandés par l'utilisateur Param: - c: Commande (voir #define ci dessus) - nomfichier: Nom du fichier à lire - nm_index: Argument de l'option -x, NULL si l'option n'a pas été choisis Return: Etat de sortie de la fonction: - -1: Impossible d'ouvrir le fichier donné - 0: Ouverture du fichier réussi */ int exe_commande(unsigned char c, char *nomfichier,char* nm_index) { if (nomfichier==NULL) return NOMFICHIERNULL; FILE *f; Elf32_Ehdr header; Elf32_Shdr *section_header_table; Elf32_Sym *symbol_tab; sectioncontent section; int nbSym = 0; int valid = 0; f = fopen(nomfichier,"r"); // Ouverture du fichier nomfichier if(f == NULL) { // Echec d'ouverture return FICHIERINEXISTANT; } else { /* Lecture Header */ header = read_header(f,&valid); if(valid==1) { // Header valide /* Lecture Table de section header */ section_header_table = read_section_header_table(f,header); /* Lecture Table des symboles */ symbol_tab = read_symbol_table(f ,section_header_table, header, &nbSym); if(c&COMMANDE_HEAD) //COMMANDE_HEAD { printf("ELF Header:\n"); print_header(header); printf("\n"); } if(c&COMMANDE_SECTIONTAB)//COMMANDE_SECTIONTAB { printf("Section Headers:\n"); print_section_header_table(f,section_header_table,header); printf("\n"); } if(c&COMMANDE_CONTENT)//COMMANDE_CONTENT { printf("Section %s content:\n", nm_index); section = read_section_content(f,nm_index, section_header_table, header); if(section.content==NULL) { printf("Warning, section : %s,was not dumped because it does not exist \n",nm_index); } else { print_section_content(section); } } if(c&COMMANDE_RELOC)//COMMANDE_RELOC { print_all_reloc_table(f, header, section_header_table, symbol_tab); printf("\n"); } if(c&COMMANDE_SYM)//COMMANDE_SYM { printf("Symbol table\n"); print_symbol_table(symbol_tab, nbSym, f, section_header_table, header); freeSymbolTable(symbol_tab); } } else // Header non valide { if(valid ==-1) { // Fichier non valid (vide ou autre) return FILEEMPTY;fprintf(stderr, "%s : Error while reading the file (possibly empty)\n",nomfichier); } else if(valid==0) { //Fichier pas au format elf32 return NOTELF32; } else { // Cas normalement impossible fprintf(stderr, "Impossible error append\n"); } } fclose(f); // Fermeture du fichier } return 0; }
static int elf_read(struct mt_elf *mte, struct task *task, const char *filename) { unsigned long loadsize = 0; unsigned long loadbase = ~0; unsigned long align; unsigned long vstart; unsigned int loadsegs = 0; debug(DEBUG_FUNCTION, "filename=%s", filename); if (open_elf(mte, task, filename) < 0) return -1; GElf_Phdr phdr; int i; memset(&mte->txt_hdr, 0, sizeof(mte->txt_hdr)); memset(&mte->eh_hdr, 0, sizeof(mte->eh_hdr)); memset(&mte->exidx_hdr, 0, sizeof(mte->exidx_hdr)); for (i = 0; gelf_getphdr(mte->elf, i, &phdr) != NULL; ++i) { switch (phdr.p_type) { case PT_LOAD: loadsegs++; align = phdr.p_align; if (align) align -= 1; vstart = phdr.p_vaddr & ~align; if (mte->vstart > vstart) mte->vstart = vstart; if (loadbase > phdr.p_offset) loadbase = phdr.p_offset; if (loadsize < phdr.p_offset + phdr.p_filesz) loadsize = phdr.p_offset + phdr.p_filesz; if ((phdr.p_flags & (PF_X | PF_W)) == PF_X) mte->txt_hdr = phdr; break; case PT_GNU_EH_FRAME: mte->eh_hdr = phdr; break; #ifdef __arm__ case PT_ARM_EXIDX: mte->exidx_hdr = phdr; break; #endif case PT_INTERP: mte->interp = phdr.p_vaddr; break; case PT_DYNAMIC: mte->dyn = phdr.p_vaddr; break; default: break; } } if (!loadsegs) { fprintf(stderr, "No loadable segemnts in %s\n", filename); return -1; } mte->loadbase = loadbase & ~PAGEALIGN; mte->loadsize = (loadsize + (loadbase - mte->loadbase) + PAGEALIGN) & ~PAGEALIGN; debug(DEBUG_FUNCTION, "filename=`%s' text offset=%#llx addr=%#llx size=%#llx", filename, (unsigned long long)mte->txt_hdr.p_offset, (unsigned long long)mte->txt_hdr.p_vaddr, (unsigned long long)mte->txt_hdr.p_filesz); for (i = 1; i < mte->ehdr.e_shnum; ++i) { Elf_Scn *scn; GElf_Shdr shdr; const char *name; scn = elf_getscn(mte->elf, i); if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) { fprintf(stderr, "Couldn't get section #%d from" " \"%s\": %s\n", i, filename, elf_errmsg(-1)); return -1; } name = elf_strptr(mte->elf, mte->ehdr.e_shstrndx, shdr.sh_name); if (name == NULL) { fprintf(stderr, "Couldn't get name of section #%d from \"%s\": %s\n", i, filename, elf_errmsg(-1)); return -1; } if (shdr.sh_type == SHT_SYMTAB) { read_symbol_table(mte, filename, scn, &shdr, name, &mte->symtab, &mte->symtab_count, &mte->strtab); } else if (shdr.sh_type == SHT_DYNSYM) { read_symbol_table(mte, filename, scn, &shdr, name, &mte->dynsym, &mte->dynsym_count, &mte->dynstr); } else if (shdr.sh_type == SHT_DYNAMIC) { Elf_Data *data; GElf_Dyn dyn; int idx; data = elf_getdata(scn, NULL); if (data == NULL) { fprintf(stderr, "Couldn't get .dynamic data from \"%s\": %s\n", filename, strerror(errno)); return -1; } for(idx = 0; gelf_getdyn(data, idx, &dyn); ++idx) { if (dyn.d_tag == DT_PLTGOT) { mte->pltgot = dyn.d_un.d_ptr; break; } } } } if (!mte->dynsym || !mte->dynstr) { fprintf(stderr, "Couldn't find .dynsym or .dynstr in \"%s\"\n", filename); return -1; } return 0; }