Hook库构造函数调用dlsym出现段错误,添加特定代码后异常消失的原因排查
动态库Hook初始化段错误排查
我编写了一个hook.so用于挂钩目标程序的read、write等系统调用,使用GNU的__attribute__((constructor))标记初始化函数get_origin_function,让它在hook.so加载时自动执行,代码如下:
void get_origin_function() { GLIBC_OPEN = (open_ptr)dlsym(RTLD_NEXT, "open"); GLIBC_OPENAT = (openat_ptr)dlsym(RTLD_NEXT, "openat"); LIBC_FOPEN = (fopen_ptr)dlsym(RTLD_NEXT, "fopen"); LIBC_FOPEN64 = (fopen64_ptr)dlsym(RTLD_NEXT, "fopen64"); GLIBC_READ = (read_ptr)dlsym(RTLD_NEXT, "read"); LIBC_FREAD = (fread_ptr)dlsym(RTLD_NEXT, "fread"); GLIBC_CLOSE = (close_ptr)dlsym(RTLD_NEXT, "close"); LIBC_FCLOSE = (fclose_ptr)dlsym(RTLD_NEXT, "fclose"); LIBC_FPRINTF = (fprintf_ptr)dlsym(RTLD_NEXT, "fprintf"); LIBC_PRINTF = (printf_ptr)dlsym(RTLD_NEXT, "printf"); GLIBC_WRITE = (write_ptr)dlsym(RTLD_NEXT, "write"); }
使用LD_PRELOAD=./hook.so my_program测试时出现段错误,推测是空指针引用。但奇怪的是,在函数末尾添加usleep(1)或打印函数指针的printf("%p %p %p...",GLIBC_OPEN)后,段错误消失,代码如下:
void get_origin_function() { GLIBC_OPEN = (open_ptr)dlsym(RTLD_NEXT, "open"); GLIBC_OPENAT = (openat_ptr)dlsym(RTLD_NEXT, "openat"); LIBC_FOPEN = (fopen_ptr)dlsym(RTLD_NEXT, "fopen"); LIBC_FOPEN64 = (fopen64_ptr)dlsym(RTLD_NEXT, "fopen64"); GLIBC_READ = (read_ptr)dlsym(RTLD_NEXT, "read"); LIBC_FREAD = (fread_ptr)dlsym(RTLD_NEXT, "fread"); GLIBC_CLOSE = (close_ptr)dlsym(RTLD_NEXT, "close"); LIBC_FCLOSE = (fclose_ptr)dlsym(RTLD_NEXT, "fclose"); LIBC_FPRINTF = (fprintf_ptr)dlsym(RTLD_NEXT, "fprintf"); LIBC_PRINTF = (printf_ptr)dlsym(RTLD_NEXT, "printf"); GLIBC_WRITE = (write_ptr)dlsym(RTLD_NEXT, "write"); usleep(1); // or printf() }
如果在函数开头添加printf(),仍会出现段错误,代码如下:
void get_origin_function() { printf(); GLIBC_OPEN = (open_ptr)dlsym(RTLD_NEXT, "open"); GLIBC_OPENAT = (openat_ptr)dlsym(RTLD_NEXT, "openat"); LIBC_FOPEN = (fopen_ptr)dlsym(RTLD_NEXT, "fopen"); LIBC_FOPEN64 = (fopen64_ptr)dlsym(RTLD_NEXT, "fopen64"); GLIBC_READ = (read_ptr)dlsym(RTLD_NEXT, "read"); LIBC_FREAD = (fread_ptr)dlsym(RTLD_NEXT, "fread"); GLIBC_CLOSE = (close_ptr)dlsym(RTLD_NEXT, "close"); LIBC_FCLOSE = (fclose_ptr)dlsym(RTLD_NEXT, "fclose"); LIBC_FPRINTF = (fprintf_ptr)dlsym(RTLD_NEXT, "fprintf"); LIBC_PRINTF = (printf_ptr)dlsym(RTLD_NEXT, "printf"); GLIBC_WRITE = (write_ptr)dlsym(RTLD_NEXT, "write"); }
最初怀疑是glibc等动态库未加载,尝试在函数开头调用dlopen也未解决问题,恳请排查该异常的原因。
内容的提问来源于stack exchange,提问作者wenju sun
相关产品推荐
相关产品推荐

