Unix系统调用hook函数以及使用dl库实现

博客搬家,原地址:https://langzi989.github.io/2017/10/16/Unix系统hook函数以及使用dl库实现/

系统调用属于一种软中断机制(内中断陷阱),它有操作系统提供的功能入口(sys_call)以及CPU提供的硬件支持(int 3 trap)共同完成。
hook系统调用:为当用户代码调用系统调用的时候,我们通过某种手段入侵该系统调用,使得系统调用中除了执行原有的操作,还可以完成我们需要其完成的一些自定义特性,也可以理解为我们为这个函数做了一个钩子。这样我们就可以实现如当一个文件发生写操作的时候,通知所有关注此文件的进程或线程等等。

通过动态链接库挟持系统调用

在linux操作系统的动态链接库的世界中,LD_PRELOAD就是这样一个环境变量,它可以影响程序的运行时的链接(Runtime linker),它允许你定义在程序运行前优先加载的动态链接库。loader在进行动态链接的时候,会将有相同符号名的符号覆盖成LD_PRELOAD指定的so文件中的符号。换句话说,可以用我们自己的so库中的函数替换原来库里有的函数,从而达到hook的目的。

上述hook系统调用的方法可以使用dlfcn.h库中的一系列函数实现。
example,此函数hook了fcntl系统调用:

#include <stdarg.h>
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>

typedef int (*fcntl_pfn_t)(int fildes, int cmd, ...);


int fcntl(int fildes, int cmd, ...)
{
	fcntl_pfn_t g_sys_fcntl_func    = (fcntl_pfn_t)dlsym(RTLD_NEXT,"fcntl");

	va_list arg_list;
	va_start( arg_list,cmd );

	int ret = -1;
	switch( cmd )
	{
		case F_DUPFD:
		{
			int param = va_arg(arg_list,int);
			ret = g_sys_fcntl_func( fildes,cmd,param );
			break;
		}
		case F_GETFD:
		{
			ret = g_sys_fcntl_func( fildes,cmd );
			break;
		}
		case F_SETFD:
		{
			int param = va_arg(arg_list,int);
			ret = g_sys_fcntl_func( fildes,cmd,param );
			break;
		}
		case F_GETFL:
		{
			ret = g_sys_fcntl_func( fildes,cmd );
			break;
		}
		case F_SETFL:
		{
			int param = va_arg(arg_list,int);
			int flag = param;
			flag |= O_NONBLOCK;
			ret = g_sys_fcntl_func( fildes,cmd,flag );
			break;
		}
		case F_GETOWN:
		{
			ret = g_sys_fcntl_func( fildes,cmd );
			break;
		}
		case F_SETOWN:
		{
			int param = va_arg(arg_list,int);
			ret = g_sys_fcntl_func( fildes,cmd,param );
			break;
		}
		case F_GETLK:
		{
			struct flock *param = va_arg(arg_list,struct flock *);
			ret = g_sys_fcntl_func( fildes,cmd,param );
			break;
		}
		case F_SETLK:
		{
			struct flock *param = va_arg(arg_list,struct flock *);
			ret = g_sys_fcntl_func( fildes,cmd,param );
			break;
		}
		case F_SETLKW:
		{
			struct flock *param = va_arg(arg_list,struct flock *);
			ret = g_sys_fcntl_func( fildes,cmd,param );
			break;
		}
	}

	va_end( arg_list );

	return ret;
}

int main() {
	int old = fcntl(STDIN_FILENO, F_GETFL);
	printf ("old:%d\n", old);

	fcntl(STDIN_FILENO, F_SETFL, old);

	int _new = fcntl(STDIN_FILENO, F_GETFL);
	printf ("new:%d\n", _new);
}

参考链接:http://www.it165.net/os/html/201407/8847.html

发布了130 篇原创文章 · 获赞 40 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/u014630623/article/details/89058027