系统Hook实现网络重定向(主机无法连接到网络)
-
系统调用Hook简介
系统调用属于一种软中断机制(内中断陷阱),它有操作系统提供的功能入口
sys_call
以及CPU提供的硬件支持int 3 trap
共同完成。首先要知道,Hook技术是一个相对较宽的话题,由于操作系统从
ring3
到ring0
是分层次的结构,在每一个层次上都可以进行相应的Hook,在不同的层次使用所取得的效果也是不尽相同的.Ring3中Hook技术
0x1:
LD_PRELOAD
动态连接.so函数劫持在linux操作系统的动态链接库的世界中,
LD_PRELOAD
就是这样一个环境变量,它可以影响程序的运行时的链接(Runtime linker),它允许你定义在程序运行前优先加载的动态链接库。loader在进行动态链接的时候,会将有相同符号名的符号覆盖成LD_PRELOAD
指定的so文件中的符号。也就是说可以用我们自己的so库中的函数替换原来库里有的函数,从而达到hook的目的。Linux的用C库的都是glibc,有一个叫libc.so.6的文件,这是几乎所有Linux下命令的动态链接中,其中有标准C的各种函数,默认情况下,linux所编译的程序中对标准C函数的链接,都是通过动态链接方式来链接libc.so.6这个函数库的。这也意味着我们在通过我们注入的.so来实现函数覆盖劫持之后需要从libc.so.6中取得原本的正常函数,让程序继续正常执行
0x2:
LD_PRELOAD
动态连接.so生效如果要使自己编写的动态链接库生效有以下两种方法,如果要应用到生产环境中建议使用第二种
LD_PRELOAD=./hook.so ./test
命令中
./hook.so
为编译生成的动态链接库,./test
为可执行程序,使用此命令,仅当test
程序中出现了hook.so
中同名函数调用的时候才会生效,其他调用无效- 修改系统配置文件,在
/etc/ld.so.preload
,写入生成的动态链接库的路径.之后调用其中的同名函数时便会生效,文件没有可以新建
0x3: 代码实例
connect.c
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <stdbool.h> #include <fcntl.h> #include <dlfcn.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> #include <linux/ip.h> #include <linux/tcp.h> #define LOCAL_PORT 1080 #define LOCAL_IP "127.0.0.1" int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { bool status = false; int optval; int optlen = sizeof(int); struct sockaddr_in *sin = (struct sockaddr_in *)addr; static int (*func)(int, const struct sockaddr *, socklen_t); // save old function ptr FN(func,int,"connect", (int, const struct sockaddr *, socklen_t)); //redirect dst ip and port sin->sin_port = htons(LOCAL_PORT); sin->sin_addr.s_addr = inet_addr(LOCAL_IP); return (*func) (sockfd, addr, addrlen); }
将文件编译为动态链接库
gcc -shared -fPIC -o not_connect.so hook.c -ldl
并将文件路径写在
/etc/ld.so.preload
中之后进行网络连接将会重定向到本地.从而主机无法上网
-
在使用
hook
时需要注意动态库的标准化,否则容易出现Linux系统无法正常开机。@zhaoyonghui 难忘的经历呀.
-
是的,Hook要尽量减少资源开销比较大的操作,像读写文件这样的!