Hi deLusion`
Okay so an implementation of the following would be if you need to redirect a library to another one.
For example, application aaa.x86 loads bbb.so, and you would like to load your own shared library (via LD_PRELOAD), which would in turn stop xxx.x86 loading bbb.so, and make it load ccc.so.
elf.cpp
elf.hCode:#include "elf.h" bool HookGlobalFunc(const char *SymbolName, void *HookFunc) { int fileDescriptor = open("/proc/self/exe", O_RDONLY); // We'll only need to hook Global funcs from et.x86 elf_version(EV_CURRENT); Elf *elf = elf_begin(fileDescriptor, ELF_C_READ, NULL); Elf32_Ehdr *header = 0; // ELF Header Elf_Scn *section = 0; // ELF Section Elf_Data *sectionData = 0; // ELF Section Data Elf32_Shdr *sectionHeader = 0; // ELF Section Header int symbolNumber = -1; if(!elf) { goto end; /* close(fileDescriptor); return false;*/ } unsigned short ndx; if((header = elf32_getehdr(elf)) == 0) { goto error; //elf_end(elf); //close(fileDescriptor); //return false; } ndx = header->e_shstrndx; // Go through the sections // .dynsym = Dynamic Symbol Location (linked with .hash and .dynstr) while((section = elf_nextscn(elf, section)) != 0) { char *name = 0; if((sectionHeader = elf32_getshdr(section)) != 0) { name = elf_strptr(elf, ndx, (size_t)sectionHeader->sh_name); if(!strcmp(name, ".dynsym")) { Elf32_Shdr *strtabhdr; Elf32_Sym *symbol, *symbolp; // ELF Symbol Pointers char *string; strtabhdr = §ionHeader[sectionHeader->sh_link]; string = (char *)malloc(strtabhdr->sh_size); if(string == NULL) goto error; if((size_t)lseek(fileDescriptor, strtabhdr->sh_offset, SEEK_SET) != strtabhdr->sh_offset) goto error; if((size_t)read(fileDescriptor, string, strtabhdr->sh_size) != strtabhdr->sh_size) goto error; symbol = (Elf32_Sym *)malloc(sectionHeader->sh_size); if(symbol == NULL) goto error; if((size_t)lseek(fileDescriptor, sectionHeader->sh_offset, SEEK_SET) != sectionHeader->sh_offset) goto error; if((size_t)read(fileDescriptor, symbol, sectionHeader->sh_size) != sectionHeader->sh_size) goto error; symbolp = symbol; for(int i = 0; (size_t)i < sectionHeader->sh_size; i += sizeof(Elf32_Sym)) { if(!strcmp(elf_strptr(elf, sectionHeader->sh_link, symbolp->st_name), SymbolName)) { symbolNumber = symbolp - symbol; break; } ++symbolp; } free(string); } else continue; } else continue; } // .rel.plt = Relocation Procedure Linkage Table (Actual GOT) if(symbolNumber == -1) goto error; // Lookup the Hash from .dynsym in .rel.plt section = 0; sectionHeader = 0; while((section = elf_nextscn(elf, section)) != 0) { char *name = 0; if((sectionHeader = elf32_getshdr(section)) != 0) { name = elf_strptr(elf, ndx, (size_t)sectionHeader->sh_name); if(!strcmp(name, ".rel.plt")) { sectionData = elf_getdata(section, NULL); if(!sectionData) goto error; for(int i = 0; (size_t)i < (sectionHeader->sh_size / sectionHeader->sh_entsize); i++) { GElf_Rel relocation; gelf_getrel(sectionData, i, &relocation); if(ELF64_R_SYM(relocation.r_info) == (size_t)symbolNumber) { if(HookFunc == NULL) { // Debug printf("Symbol '%s' found at 0x%x\n", SymbolName, (unsigned int)relocation.r_offset); } else { #ifdef DEBUG // Only on absolute debug build in muppetTools/ printf("Found symbol (%i) at %x redirecting to %x\n", symbolNumber, relocation.r_offset, &HookFunc); #endif *(void **)(unsigned int)relocation.r_offset = HookFunc; } } } } else continue; } else continue; } end: close(fileDescriptor); elf_end(elf); return true; error: close(fileDescriptor); elf_end(elf); return false; }
Implementation example (.cpp for compilation into a shared object):Code:#pragma once #include <libelf.h> #include <gelf.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <fcntl.h> bool HookGlobalFunc(const char *SymbolName, void *HookFunc);
Code:void *_dlopen(const char *fileName, int flags) { if(strstr(fileName, "bbb.so")) return dlopen("ccc.so", flags); else return dlopen(fileName, flags); } void __atrribute__ ((constructor)) MyMain(void) { HookGlobalFunc("dlopen", (void *)&_dlopen); }


Reply With Quote