利用 预加载(PRELOAD)机制实现 Hook

 

elf程序在进行动态链接的时候,会将有相同符号名的符号覆盖成LD_PRELOAD指定的so文件中的符号。也就是说,我们可以用自己的so库中的函数替换原来库里有的函数,从而达到hook的目的。

下面我们尝试通过这种hook方式来实现任意地址读/写

linux平台下的测试

测试文件:

test.c:

#include <stdio.h> char xxx[] = "tlsn_wheeler"; int main(){ puts("nihao"); puts(xxx); return 0; } // gcc ./test.c -g -no-pie -o ./test

 

 

hook代码:

hook.c:

#include <stdio.h> #include <string.h> #include <dlfcn.h> unsigned char hooking[] = "hook write xD!!!!"; typedef int (*PFN_puts)(const char * s); int puts(const char * s) { void *handle = dlopen("libc.so.6", RTLD_LAZY); PFN_puts old_puts = dlsym(handle, "puts"); // 以备调用 if (!strcmp(s,"nihao")){ unsigned long long int hook_addr = 0x000000000404030; // 任意位置读数据 unsigned char res[20] ={0}; for(int i=0;i<10;i++){ res[i] = *(unsigned char*)(hook_addr+i); } printf("hook read: %s\n",res); // 任意位置写数据 for(int i=0;i<13;i++){ *(unsigned char*)(hook_addr+i) = hooking[i]; } *(unsigned char*)(hook_addr+13) = 0; }else{ return old_puts(s); } // printf("hooked!!!"); return 0; } // gcc -fPIC -shared -o hook.so hook.c -ldl // LD_PRELOAD=./hook.so ./test

 

效果:

 

 

 

Android平台下的测试

需要注意的是,Android5.0 之后不支持未开启pie的程序,因此,测试文件的编译选项中不能有 -no-pie选项了,没关系,我们可以通过读 /proc/self/maps 来获取程序加载的基址。

另一个需要注意的点就是 dlopen的库从 libc.so.6变为了 libc.so ,不要填错了!!!

 

 

测试文件:

test.c

#include <stdio.h> #include <stdlib.h> #include <sys/auxv.h> char xxx[] = "tlsn_wheeler"; int main(){ puts("nihao"); puts(xxx); return 0; } // '/home/tlsn/Btools/NDKXX/NDK24/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang' ./test.c -g -o ./test

 

hook文件

hook.c

#include <stdio.h> #include <string.h> #include <dlfcn.h> unsigned char hooking[] = "hook write xD!!!!"; typedef int (*PFN_puts)(const char * s); unsigned long long get_baseaddr(){ FILE *fp = fopen("/proc/self/maps", "r"); if (fp == NULL) { perror("fopen"); return 1; } char line[256]; unsigned long long start_addr =0; while (fgets(line, sizeof(line), fp) != NULL) { unsigned long start, end; if (sscanf(line, "%lx-%lx", &start, &end) == 2) { // printf("Program loaded at address range: %lx - %lx\n", start, end); start_addr = start; fclose(fp); return start_addr; } } } int puts(const char * s) { void *handle = dlopen("libc.so", RTLD_LAZY); PFN_puts old_puts = dlsym(handle, "puts"); // 以备调用 unsigned long long baseaddr = get_baseaddr(); printf("[*]baseaddr is 0x%llx\n",baseaddr); printf("[*]old_puts is 0x%llx\n",old_puts); printf("[*]HOOKED_puts is 0x%llx\n",puts); if (!strcmp(s,"nihao")){ unsigned long long int hook_addr_offset = 0x3998; unsigned long long int hook_addr = baseaddr + hook_addr_offset; // 任意位置读数据 unsigned char res[20] ={0}; for(int i=0;i<10;i++){ res[i] = *(unsigned char*)(hook_addr+i); } printf("hook read: %s\n",res); // 任意位置写数据 for(int i=0;i<13;i++){ *(unsigned char*)(hook_addr+i) = hooking[i]; } *(unsigned char*)(hook_addr+13) = 0; }else{ return old_puts(s); } // printf("hooked!!!"); return 0; } // '/home/tlsn/Btools/NDKXX/NDK24/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang' -fPIC -shared -o hook.so hook.c -ldl // LD_PRELOAD=./hook.so ./test

 

hook效果:

 


__EOF__

本文作者_TLSN
本文链接https://www.cnblogs.com/lordtianqiyi/p/18706874.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   TLSN  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示