欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]LINUX ELF HOOK DEMO源码

[原创]LINUX ELF HOOK DEMO源码

#define _GNU_SOURCE

#define __USE_GNU

#include <sys/stat.h>

#include <fcntl.h>

#include <sys/mman.h>

#include <signal.h>

#include <dlfcn.h>

#include <errno.h>

#include <elf.h>

#include <link.h>

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

extern int test_so_call(int a, int b);

#define ELFW(name, t) _ELFW (name, __WORDSIZE, t)

#define _ELFW(name, bits, t) __ELFW (name, bits, t)

#define __ELFW(name, bits, t) name##bits##t

#define SYMID_2_NAME(e_info, i) \

        (e_info)->e_strtab + (e_info)->e_syms[i].st_name

#define PROT_ADDR(addr, t) \

        mprotect((void*)((size_t)(addr) & (((size_t)-1) ^ 0xfff)), 0x1000, t)

typedef struct _elf_info {

        ElfW(Ehdr) *e_ehdr;

        ElfW(Shdr) *e_shdr;

        ElfW(Phdr) *e_phdr;

        ElfW(Shdr) *e_shdr_dyn;

        ElfW(Sym)  *e_syms;

        ElfW(Rela) *e_rela;

        ElfW(Rel) *e_rel;

        size_t e_relsz;

        /* jmp plt import */

        char* e_jmprel;

        size_t e_pltrel;

        size_t e_pltrelsz;

        uint32_t *e_hashtab;

        char* e_strtab;

        void** e_got;

        size_t e_dyn_size;

        size_t e_shnum;

        int e_class;            /* ELFCLASS32/ELFCLASS64 */

} elf_info, *pelf_info;

typedef struct _elf_hook_item {

        void* modbase;

        const char* lib_name;

        const char* fun_name;

        void* hook_func;

        void* org_func;

        void** porg_func;

} elf_hook_item, *pelf_hook_item;

elf_hook_item hook_test;

elf_hook_item hook_test2;

int hook_so_call(int a, int b)

{

        printf("!!!!!eat hook test_so_call\n");

        return ((int(*)(int,int))hook_test.org_func)(a, b) + 1;

}

#include <stdarg.h>

int hook_printf(__const char *__restrict __format, va_list ap)

{

        int ret = 0;

        printf("!!!!!iat hook printf\n");

        //printf(__format, ap);

        ret = ((int(*)(const char *,...))hook_test2.org_func)(__format, ap);

        printf("printf:GOT %p -> %p\n", hook_test2.porg_func, *hook_test2.porg_func);

        if (*hook_test2.porg_func != hook_printf)

                *hook_test2.porg_func = hook_printf;

        return ret;

}

unsigned long elf_Hash(const char *name)

{

        unsigned long h = 0, g;

        while (*name) {

                h = (h << 4) + *name++;

                if ((g = h & 0xf0000000))

                        h ^= g >> 24;

                h &= ~g;

        }

        return h;

}

static ElfW(Sym)* get_func_sym(pelf_info e_info, const char* fun_name)

{

        unsigned long hash;

        uint32_t *buf = e_info->e_hashtab;

        uint32_t nbucket, nchain;

        uint32_t *bucket, *chain;

        ElfW(Sym)* e_sym = e_info->e_syms;

        uint32_t symindx;

        hash = elf_Hash(fun_name);

        nbucket = buf[0];

        nchain = buf[1];

        bucket = buf + 2;

        chain = bucket + nbucket;

        for (symindx=bucket[hash % nbucket];

                        symindx != STN_UNDEF; symindx=chain[symindx]) {

                //printf("%s\n", e_info->e_strtab + e_sym[symindx].st_name);

                if (strcmp(e_info->e_strtab + e_sym[symindx].st_name, fun_name) == 0)

                        return e_sym + symindx;

        }

        return NULL;

}

static void __parse_dyn_info(void* dyntab, pelf_info e_info)

{

        ElfW(Dyn)* e_dyn;

        for (e_dyn = (ElfW(Dyn)*)dyntab; e_dyn->d_tag != DT_NULL; e_dyn++) {

                //printf("%d\n", e_dyn->d_tag);

                switch (e_dyn->d_tag) {

                case DT_PLTGOT:

                        e_info->e_got =  (void**)e_dyn->d_un.d_ptr;

                        break;

                case DT_STRTAB:

                        e_info->e_strtab = (char*)e_dyn->d_un.d_ptr;

                        break;

                case DT_HASH:

                        e_info->e_hashtab = (uint32_t *)e_dyn->d_un.d_ptr;

                        break;

                case DT_SYMTAB:

                        e_info->e_syms = (ElfW(Sym)*)e_dyn->d_un.d_ptr;

                        break;

                case DT_REL:

                        e_info->e_rel = (ElfW(Rel)*)e_dyn->d_un.d_ptr;

                        break;

                case DT_RELA:

                        e_info->e_rela = (ElfW(Rela)*)e_dyn->d_un.d_ptr;

                        break;

                case DT_JMPREL:

                        e_info->e_jmprel = (char*)e_dyn->d_un.d_ptr;

                        break;

                case DT_PLTREL:

                        e_info->e_pltrel = e_dyn->d_un.d_val;

                        break;

                case DT_PLTRELSZ:

                        e_info->e_pltrelsz = e_dyn->d_un.d_val;

                        break;

                case DT_RELSZ:

                case DT_RELASZ:

                        e_info->e_relsz = e_dyn->d_un.d_val;

                        break;

                default:

                        continue;

                }

        }

}

static int __do_eat_hook(char* modbase, pelf_hook_item hook_item)

{

        elf_info e_info = {0};

        ElfW(Sym)* e_sym;

        int i;

        e_info.e_class = modbase[EI_CLASS];

        e_info.e_ehdr = (ElfW(Ehdr)*)modbase;

        e_info.e_shdr = (ElfW(Shdr)*)(modbase + e_info.e_ehdr->e_shoff);

        e_info.e_phdr = (ElfW(Phdr)*)(modbase + e_info.e_ehdr->e_phoff);

        /* get dynamin info */

        for (i=0; i<e_info.e_ehdr->e_phnum; i++) {

                if (e_info.e_phdr[i].p_type == PT_DYNAMIC) {

                        e_info.e_shdr_dyn = (ElfW(Shdr) *)(modbase + e_info.e_phdr[i].p_vaddr);

                        e_info.e_dyn_size = e_info.e_phdr[i].p_memsz;

                        break;

                }

        }

        if (!e_info.e_shdr_dyn)

                return -1;

        __parse_dyn_info(e_info.e_shdr_dyn, &e_info);

        printf("base %p %p hash %p\n", modbase, e_info.e_syms, e_info.e_hashtab);

        e_sym = get_func_sym(&e_info, hook_item->fun_name);

        if (e_sym == NULL) {

                printf("get_func_sym:%s failed\n", hook_item->fun_name);

                return -1;

        }

        if (PROT_ADDR(e_sym, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) {

                printf("mprotect error! %d\n", errno);

                return -1;

        }

        hook_item->modbase = modbase;

        hook_item->org_func = e_sym->st_value + modbase;

        hook_item->porg_func = (void**)&e_sym->st_value;

        e_sym->st_value = (char*)hook_item->hook_func - modbase;

        printf("eat hook %s %p -> %p\n",

               hook_item->fun_name,

               hook_item->porg_func,

               hook_item->hook_func

               );

        return 0;

}

static int enum_mod_base(struct dl_phdr_info *info, size_t size, void *data)

{

        pelf_hook_item hook_item = (pelf_hook_item)data;

        int i;

        printf("name=%s (%d segments) address=%p\n",

               info->dlpi_name, info->dlpi_phnum, (void*)info->dlpi_addr);

        if (strstr(info->dlpi_name, hook_item->lib_name) == NULL)

                return 0;

        for (i = 0; i < info->dlpi_phnum; i++) {

                if (info->dlpi_phdr[i].p_type == PT_LOAD) {

                        char* lib_base = (char *)(info->dlpi_addr +

                                                  info->dlpi_phdr[i].p_vaddr);

                        __do_eat_hook(lib_base, hook_item);

                        break;

                }

        }

        return 0;

}

static int eat_hook(pelf_hook_item hook_item)

{

        dl_iterate_phdr(enum_mod_base, hook_item);

        return 0;

}

static int iat_hook(pelf_hook_item hook_item)

{

        struct link_map *link_map;

        char* rel_bf;

        int symid;

        void* symaddr;

        elf_info e_info = {0};

        link_map = (struct link_map *)dlopen(hook_item->lib_name, RTLD_LAZY);

        if (!link_map)

                return -1;

        hook_item->modbase = (void*)link_map->l_addr;

        printf("l_ld->%p\n", link_map->l_ld);

        __parse_dyn_info(link_map->l_ld, &e_info);

        dlclose(link_map);

        if (!e_info.e_jmprel)

                return -1;

        for (rel_bf = e_info.e_jmprel; rel_bf < e_info.e_jmprel + e_info.e_pltrelsz;) {

                if (DT_RELA == e_info.e_pltrel) {

                        symid = ELFW(ELF,_R_SYM)(((ElfW(Rela)*)rel_bf)->r_info);

                        symaddr = (void*)((ElfW(Rela)*)rel_bf)->r_offset;

                } else {

                        symid = ELFW(ELF,_R_SYM)(((ElfW(Rel)*)rel_bf)->r_info);

                        symaddr = (void*)((ElfW(Rel)*)rel_bf)->r_offset;

                }

                if (!strcmp(SYMID_2_NAME(&e_info, symid), hook_item->fun_name)) {

                        if (PROT_ADDR(symaddr, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) {

                                printf("mprotect error! %d\n", errno);

                                return 0;

                        }

                        hook_item->porg_func = (void**)symaddr;

                        hook_item->org_func = *(void**)symaddr;

                        *(void**)symaddr = hook_item->hook_func;

                        printf("iat hook %s %p -> %p\n",

                               hook_item->fun_name,

                               hook_item->porg_func,

                               hook_item->hook_func

                               );

                }

                rel_bf += (DT_RELA == e_info.e_pltrel) ? sizeof(ElfW(Rela)):sizeof(ElfW(Rel));

        }

        return -1;

}

__attribute ((constructor)) void so_lib_init(void)

{

        printf("hook so init\n");

        hook_test.lib_name = "so_test.so";

        hook_test.fun_name = "test_so_call";

        hook_test.hook_func = hook_so_call;

        eat_hook(&hook_test);

        hook_test2.lib_name = NULL;

        hook_test2.fun_name = "printf";

        hook_test2.hook_func = hook_printf;

        iat_hook(&hook_test2);

}

__attribute ((destructor)) void so_lib_free(void)

{

        printf("so_lib_freed\n");

}


运行结果如下

上传的附件 Screenshot-main.c (test_so) - Code::Blocks 10.05.png

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功