Results 1 to 2 of 2

Thread: [Linux] Redirecting parent functions from shared object

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2006
    Location
    Ubuntu Haters Club
    Posts
    405

    Thumbs up [Linux] Redirecting parent functions from shared object

    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
    Code:
    #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 = &sectionHeader[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;
    }
    elf.h
    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);
    Implementation example (.cpp for compilation into a shared object):
    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);
    }
    Last edited by RudiVisser; Feb 2nd, 2009 at 03:40 PM.
    » Twitter: @rudi_visser : Website: www.rudiv.se «

    If Apple fixes security flaws, they are heralded as proactive. If Microsoft fixes a security flaw, they finally got around to fixing their buggy OS.

  2. #2
    Banned
    Join Date
    Mar 2009
    Posts
    17

    Re: [Linux] Redirecting parent functions from shared object

    That is interesting one thanks for sharing it..

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width