元始天尊 发表于 2016-5-6 00:06:26

如何在init_array中植入代码

没搜到网上有相应的帖子,自己研究了下
源码是这样滴:
crtbegin_dynamic/static.c

typedef struct
{
    void (**preinit_array)(void);
    void (**init_array)(void);
    void (**fini_array)(void);
    void (**ctor_list)(void);
} structors_array_t;

extern int main(int argc, char **argv, char **env);

extern void __libc_init(
unsigned int *elfdata,
void (*onexit)(void),
int (*slingshot)(int, char**, char**),
structors_array_t const * const structors
);

__attribute__ ((section (".preinit_array")))
void (*__PREINIT_ARRAY__)(void) = (void (*)(void)) -1;

__attribute__ ((section (".init_array")))
void (*__INIT_ARRAY__)(void) = (void (*)(void)) -1;

__attribute__ ((section (".fini_array")))
void (*__FINI_ARRAY__)(void) = (void (*)(void)) -1;

__attribute__ ((section (".ctors")))
void (*__CTOR_LIST__)(void) = (void (*)(void)) -1;

__attribute__((visibility("hidden")))
void _start() {
structors_array_t array;
void *elfdata;

array.preinit_array = &__PREINIT_ARRAY__;
array.init_array =    &__INIT_ARRAY__;
array.fini_array =    &__FINI_ARRAY__;
array.ctor_list =    &__CTOR_LIST__;

elfdata = __builtin_frame_address(0) + sizeof(void *);
__libc_init(elfdata, (void *) 0, &main, &array);
}


拿init_array来说:执行main之前,先进行init_array初始化,而数组第一个元素被编译器置为-1,本来是个函数指针数组,再看__libc_init实现,
发现对init_array处理是判断是否为0

libc_init_static/dynamic.cpp


static void call_array(void(**list)()) {
// First element is -1, list is null-terminated
while (*++list) {
    (*list)();
}
}
__noreturn void __libc_init(void* raw_args,
                            void (*onexit)(void) __unused,
                            int (*slingshot)(int, char**, char**),
                            structors_array_t const * const structors) {
KernelArgumentBlock args(raw_args);
__libc_init_tls(args);
__libc_init_AT_SECURE(args);
__libc_init_common(args);

apply_gnu_relro();

call_array(structors->preinit_array);
call_array(structors->init_array);

if (structors->fini_array != NULL) {
    __cxa_atexit(__libc_fini,structors->fini_array,NULL);
}

exit(slingshot(args.argc, args.argv, args.envp));
}

可见,判断init_array是否执行的依据是该项是否为0,因此只要想办法吧函数指针加到init_array段已经有的-1的后面就好了!
下面提供这种方法,无需改源码:

#include <stdio.h>

volatile inttestnum=0;

void func1(void){testnum=1;};
void func2(void){testnum=2;};
void func3(void){testnum=3;};
void func4(void){testnum=4;};

//__attribute__ ((section (".preinit_array")))
//__attribute__ ((section (".fini_array")))
//__attribute__ ((section (".ctors")))
__attribute__ ((section (".init_array"))) void(*initfunc[])(void)={&func1,&func2,&func3,&func4};//放入多个函数
__attribute__ ((section (".init_array"))) void(*initfunc1)(void)=&func1;//放入单个函数

int main(int argc, char *argv[])
{
        printf("testnum=%d\n",testnum);
}

__star__ 发表于 2016-5-6 09:36:05

居然没人顶超神
页: [1]
查看完整版本: 如何在init_array中植入代码