Exemple #1
0
/*
 * Locate a symbol in an ELF image.
 */
int
elf32FindSymbolByName(struct ElfObject *o, const char *name,
                    const Elf32_Sym **symp, const char **namep)
{
    struct Section *shdrs, *hash, *syms;
    const char *symStrings;
    const Elf32_Sym *sym;
    Elf32_Word nbucket;
    Elf32_Word nchain;
    Elf32_Word i;

    const Elf32_Word *buckets;
    const Elf32_Word *chains;
    const Elf32_Word *hashData;
    unsigned long hashv;

    shdrs = o->sectionHeaders;

    /* First, search the hashed symbols in .dynsym.  */
    if (elf32FindSectionByName(o, ".hash", &hash) != -1) {
        syms = &shdrs[hash->shdr.sh_link];

        hashData = elf32MapSection(o, hash);
        sym = elf32MapSection(o, syms);
        symStrings = elf32MapSection(o, &shdrs[syms->shdr.sh_link]);

        nbucket = hashData[0];
        nchain = hashData[1];
        buckets = hashData + 2;
        chains = buckets + nbucket;
        hashv = elfhash(name) % nbucket;
        for (i = buckets[hashv]; i != STN_UNDEF; i = chains[i])
            if (strcmp(symStrings + sym[i].st_name, name) == 0) {
                *symp = sym + i;
                if (namep)
                    *namep = symStrings + sym[i].st_name;
                return (0);
            }
    } else if (elf32FindSectionByName(o, ".dynsym", &syms) != -1) {
        /* No ".hash", but have ".dynsym": do linear search */
        if (elf32LinearSymSearch(o, syms, name, symp, namep) != -1) {
            return (0);
        }
    }

    /* Do a linear search of ".symtab" if present */
    if (elf32FindSectionByName(o, ".symtab", &syms) != -1 &&
        elf32LinearSymSearch(o, syms, name, symp, namep) != -1) {
            return (0);
    }

    return -1;
}
Exemple #2
0
void
elfdynhash(void)
{
	Sym *s, *sy, *dynstr;
	int i, j, nbucket, b, nfile;
	uint32 hc, *chain, *buckets;
	int nsym;
	char *name;
	Elfaux **need;
	Elflib *needlib;
	Elflib *l;
	Elfaux *x;
	
	if(!iself)
		return;

	nsym = nelfsym;
	s = lookup(".hash", 0);
	s->type = SELFROSECT;
	s->reachable = 1;

	i = nsym;
	nbucket = 1;
	while(i > 0) {
		++nbucket;
		i >>= 1;
	}

	needlib = nil;
	need = malloc(nsym * sizeof need[0]);
	chain = malloc(nsym * sizeof chain[0]);
	buckets = malloc(nbucket * sizeof buckets[0]);
	if(need == nil || chain == nil || buckets == nil) {
		cursym = nil;
		diag("out of memory");
		errorexit();
	}
	memset(need, 0, nsym * sizeof need[0]);
	memset(chain, 0, nsym * sizeof chain[0]);
	memset(buckets, 0, nbucket * sizeof buckets[0]);
	for(sy=allsym; sy!=S; sy=sy->allsym) {
		if (sy->dynid <= 0)
			continue;

		if(sy->dynimpvers)
			need[sy->dynid] = addelflib(&needlib, sy->dynimplib, sy->dynimpvers);

		name = sy->dynimpname;
		if(name == nil)
			name = sy->name;
		hc = elfhash((uchar*)name);

		b = hc % nbucket;
		chain[sy->dynid] = buckets[b];
		buckets[b] = sy->dynid;
	}

	adduint32(s, nbucket);
	adduint32(s, nsym);
	for(i = 0; i<nbucket; i++)
		adduint32(s, buckets[i]);
	for(i = 0; i<nsym; i++)
		adduint32(s, chain[i]);

	free(chain);
	free(buckets);
	
	// version symbols
	dynstr = lookup(".dynstr", 0);
	s = lookup(".gnu.version_r", 0);
	i = 2;
	nfile = 0;
	for(l=needlib; l; l=l->next) {
		nfile++;
		// header
		adduint16(s, 1);  // table version
		j = 0;
		for(x=l->aux; x; x=x->next)
			j++;
		adduint16(s, j);	// aux count
		adduint32(s, addstring(dynstr, l->file));  // file string offset
		adduint32(s, 16);  // offset from header to first aux
		if(l->next)
			adduint32(s, 16+j*16);  // offset from this header to next
		else
			adduint32(s, 0);
		
		for(x=l->aux; x; x=x->next) {
			x->num = i++;
			// aux struct
			adduint32(s, elfhash((uchar*)x->vers));  // hash
			adduint16(s, 0);  // flags
			adduint16(s, x->num);  // other - index we refer to this by
			adduint32(s, addstring(dynstr, x->vers));  // version string offset
			if(x->next)
				adduint32(s, 16);  // offset from this aux to next
			else
				adduint32(s, 0);
		}
	}

	// version references
	s = lookup(".gnu.version", 0);
	for(i=0; i<nsym; i++) {
		if(i == 0)
			adduint16(s, 0); // first entry - no symbol
		else if(need[i] == nil)
			adduint16(s, 1); // global
		else
			adduint16(s, need[i]->num);
	}

	free(need);

	s = lookup(".dynamic", 0);
	elfverneed = nfile;
	if(elfverneed) {
		elfwritedynentsym(s, DT_VERNEED, lookup(".gnu.version_r", 0));
		elfwritedynent(s, DT_VERNEEDNUM, nfile);
		elfwritedynentsym(s, DT_VERSYM, lookup(".gnu.version", 0));
	}
	elfwritedynent(s, DT_NULL, 0);
}
Exemple #3
0
int main(int argc ,char** argv)
{
    Elf32_Ehdr ehdr;
    Elf32_Phdr phdr;
    Elf32_Word dyn_size,dyn_strsz;
    Elf32_Off  dyn_off;
    Elf32_Dyn   dyn;
    Elf32_Addr  dyn_sym,dyn_str,dyn_hash;
    unsigned   func_hash,nbucket,nchain,func_index;
    char * ptr_dynstr = NULL;
    char * ptr_func_content = NULL;
    Elf32_Sym   func_sym;

    int   flag = 0;
    int i = 0;

    char func_name[] = "getString";
    if(argc < 2)
    {
        printf("input the so file\n");
        return 0;
    }
    int fd = open(argv[1],O_RDWR);
    if(fd < 0)
    {

        printf("open file failed\n");
        goto _error;
    }
    lseek(fd,0,SEEK_SET);
    if(read(fd,&ehdr,sizeof(Elf32_Ehdr)) != sizeof(Elf32_Ehdr))
    {
        printf("read elf header failed\n");
        goto _error;

    }

    lseek(fd,ehdr.e_phoff,SEEK_SET);
    for(i=0; i<ehdr.e_phnum;i++)
    {
        memset(&phdr,0,sizeof(phdr));
        if(read(fd,&phdr,sizeof(Elf32_Phdr)) != sizeof(Elf32_Phdr))
        {
            printf("read segment failed\n");
            goto _error;
        }
        if(phdr.p_type == PT_DYNAMIC)
        {
            dyn_off = phdr.p_offset;
            dyn_size = phdr.p_filesz;
            printf("find .dynamic section\n");
            break;
        }
    }
    lseek(fd,dyn_off,SEEK_SET);
    //for(i = 0;i<dyn_size/sizeof(Elf32_Dyn);i++)


    do{
        if(read(fd,&dyn,sizeof(Elf32_Dyn)) != sizeof(Elf32_Dyn))
        {
            printf("read .dynamic failed\n");
            goto _error;
        }
        if(dyn.d_tag == DT_SYMTAB)
        {
            flag |= SYMTAB;
            dyn_sym = dyn.d_un.d_ptr;
        }
        if(dyn.d_tag == DT_STRTAB)
        {
            flag |= STRTAB;
            dyn_str = dyn.d_un.d_ptr;
        }
        if(dyn.d_tag == DT_STRSZ)
        {
            flag |= STRSZ;
            dyn_strsz = dyn.d_un.d_val;
        }
        if(dyn.d_tag == DT_HASH)
        {
            flag |= HASH;
            dyn_hash = dyn.d_un.d_ptr;
        }
    } while(dyn.d_tag != DT_NULL);

    if((flag & 0x0f) != 0x0f)
    {
        printf("find the needed dynamic section failed\n");
        goto _error;
    }

    ptr_dynstr = (char*)malloc(dyn_strsz);
    if(ptr_dynstr == NULL)
    {
        printf("malloc .dynstr failed\n");
        goto _error;
    }
    lseek(fd,dyn_str,SEEK_SET);
    if(read(fd,ptr_dynstr,dyn_strsz) != dyn_strsz)
    {
        printf("read .dynstr failed\n");
        goto _error;
    }

    func_hash = elfhash(func_name);
    lseek(fd,dyn_hash,SEEK_SET);
    if(read(fd,&nbucket,4) != 4)
    {
        printf("read hash nbucket failed\n");
        goto _error;
    }
    if(read(fd,&nchain,4) != 4)
    {
        printf("read hash nchain failed\n");
        goto _error;
    }
    func_hash = func_hash%nbucket;

    lseek(fd,func_hash*4,SEEK_CUR);
    if(read(fd,&func_index,4) != 4)//索引是符号表或者chain
    {
        printf("read funck index failed\n");
        goto _error;
    }
    lseek(fd,dyn_sym+func_index*sizeof(Elf32_Sym),SEEK_SET);
    if(read(fd,&func_sym,sizeof(Elf32_Sym)) != sizeof(Elf32_Sym))
    {
        printf("read func sym entry failed\n'");
    }
    if(strcmp(ptr_dynstr+func_sym.st_name,func_name) != 0)
    {
        while(1)  //纯C语言是没有true的
        {
            lseek(fd,dyn_hash+4*(2+nbucket+func_index),SEEK_SET);
            if(read(fd,&func_index,4) != 4)
            {
                printf("read func index failed\n");
                goto _error;
            }

            lseek(fd,dyn_sym + func_index*sizeof(Elf32_Sym),SEEK_SET);
            memset(&func_sym,0,sizeof(Elf32_Sym));
            if(read(fd,&func_sym,sizeof(Elf32_Sym)) != sizeof(Elf32_Sym))
            {
                goto _error;
            }
            if(strcmp(func_name,dyn_str+func_sym.st_name) == 0)
            {
                break;
            }

        }
    }
    printf("find target func addr: %x,sizeo:%x\n",func_sym.st_value,func_sym.st_size);
    ptr_func_content = (char*)malloc(func_sym.st_size);
    if(ptr_func_content == NULL)
    {
        printf("alloc for func failed\n");
        goto _error;
    }

    lseek(fd,func_sym.st_value,SEEK_SET);

    if(read(fd,ptr_func_content,func_sym.st_size) != func_sym.st_size)
    {
        printf("read func content failed\n");
        goto _error;
    }


    for(i=0;i<func_sym.st_size;i++)
    {
        ptr_func_content[i] = ~ptr_func_content[i];
    }


    lseek(fd,func_sym.st_value,SEEK_SET);
    if(write(fd,ptr_func_content,func_sym.st_size) != func_sym.st_size)
    {
        printf("write to func failed\n");
        goto _error;
    }

    printf("Complete \n");

_error:
    if(ptr_dynstr != NULL)
    {
        free(ptr_dynstr);
    }
    if(ptr_func_content != NULL)
    {
        free(ptr_func_content);
    }

    return 0;
}
Exemple #4
0
unsigned libhook_addhook( const char *soname, const char *symbol, unsigned newval ) {
    struct soinfo *si = NULL;
    Elf32_Rel *rel = NULL;
    Elf32_Sym *s = NULL;
    unsigned int sym_offset = 0;
    size_t i;

//    HOOKLOG( "dlopen(%s)", soname );

    // since we know the module is already loaded and mostly
    // we DO NOT want its constructors to be called again,
    // ise RTLD_NOLOAD to just get its soinfo address.
    si = (struct soinfo *)dlopen( soname, 4 /* RTLD_NOLOAD */ );
//    si = (struct soinfo *)dlopen( soname, 0 /* RTLD_NOLOAD */ );
    if( !si ){
        HOOKLOG( "dlopen error: %s.", dlerror() );
        return 0;
    }

//    HOOKLOG( "libhook_addhook dlopen success [0x%X], soinfo_elf_lookup...",(unsigned int)si);

    s = soinfo_elf_lookup( si, elfhash(symbol), symbol );
    if( !s ){
        return 0;
    }

  //  HOOKLOG( "soinfo_elf_lookup = [0x%X]", (unsigned int)s);

    sym_offset = s - si->symtab;

//    HOOKLOG( "sym_offset = [0x%X]", sym_offset);

    // loop reloc table to find the symbol by index
    for( i = 0, rel = si->plt_rel; i < si->plt_rel_count; ++i, ++rel ) {
        unsigned type  = ELF32_R_TYPE(rel->r_info);
        unsigned sym   = ELF32_R_SYM(rel->r_info);
        unsigned reloc = (unsigned)(rel->r_offset + si->base);

//        HOOKLOG( "[%i] type/reloc/sym = [0x%X/0x%X/0x%X]", i, type, reloc, sym);

        if( sym_offset == sym ) {
            switch(type) {
                case R_ARM_JUMP_SLOT:

//                    HOOKLOG( "found R_ARM_JUMP_SLOT at [0x%X]", reloc);

                    return libhook_patch_address( reloc, newval );

                default:

                    HOOKLOG( "Expected R_ARM_JUMP_SLOT, found 0x%X", type );
            }
        }
    }

//    HOOKLOG( "find by index finished %i", 0);

    unsigned original = 0;

    // loop dyn reloc table
    for( i = 0, rel = si->rel; i < si->rel_count; ++i, ++rel ) {
        unsigned type  = ELF32_R_TYPE(rel->r_info);
        unsigned sym   = ELF32_R_SYM(rel->r_info);
        unsigned reloc = (unsigned)(rel->r_offset + si->base);

        if( sym_offset == sym ) {
            switch(type) {
                case R_ARM_ABS32:
                case R_ARM_GLOB_DAT:

                    original = libhook_patch_address( reloc, newval );

                default:

                    HOOKLOG( "Expected R_ARM_ABS32 or R_ARM_GLOB_DAT, found 0x%X", type );
            }
        }
    }

    if( original == 0 ){
        HOOKLOG( "Unable to find symbol in the reloc tables ( plt_rel_count=%u - rel_count=%u ).", si->plt_rel_count, si->rel_count );
    }

    return original;
}