C Preload 简介

2018-07-16 Monday     program , misc

Linux C 中有一个很不错的特性,可以在不改变程序的前提下,修改动态库所调用的函数,也就是 Preload 功能。

这里简单介绍其使用方法。

简介

最常见的使用场景是不修改程序,而直接修改动态库中函数的实现,例如重新实现 malloc()free() 函数。

示例

#include <stdio.h>

int main(void)
{
	FILE *fd;

	printf("Calling the fopen() function...\n");

	fd = fopen("test.txt","r");
	if (fd == NULL) {
		printf("fopen() returned NULL\n");
		return 1;
	}
	printf("fopen() succeeded\n");

	return 0;
}

然后可以通过如下方式编译、执行。

$ gcc foobar.c -o foobar

$ ./foobar
Calling the fopen() function...
fopen() succeeded

接着我们生成自己定义 fopen() 函数。

#include <stdio.h>

FILE *fopen(const char *path, const char *mode)
{
	printf("Always failing fopen\n");
	return NULL;
}

然后,编译生成动态库。

$ gcc -Wall -fPIC -shared -o libawrap.so awrap.c

$ LD_PRELOAD=./libawrap.so ./foobar
Calling the fopen() function...
Always failing fopen
fopen() returned NULL

也可以通过如下命令查看符号的查找过程。

LD_DEBUG=symbols ./foobar

以及其真正依赖的库。

$ ldd ./foobar
        linux-vdso.so.1 =>  (0x00007fffaffe7000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f0c22128000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f0c224f5000)
$ LD_PRELOAD=./libawrap.so ldd ./foobar
        linux-vdso.so.1 =>  (0x00007fff023fe000)
        ./libawrap.so (0x00007fbfa3e08000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fbfa3a3b000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fbfa400a000)

高级用法

假设我们仍然需要调用系统提供的函数,可以使用如下的方法。

#define _GNU_SOURCE

#include <dlfcn.h>
#include <stdio.h>

FILE *fopen(const char *path, const char *mode)
{
	FILE *(*oopen)(const char *, const char*);

	printf("A wrapped fopen\n");
	oopen = dlsym(RTLD_NEXT, "fopen");
	if (oopen == NULL) {
		fprintf(stderr, "Failed to find fopen\n");
		return NULL;
	}

	return oopen(path, mode);
}

也就是通过 dlsym() 查找下个 fopen() 符号。

参考

详细可以参考 Dynamic linker tricks: Using LD_PRELOAD to cheat, inject features and investigate programs 或者 本地文档



如果喜欢这里的文章,而且又不差钱的话,欢迎打赏个早餐 ^_^


About This Blog

Recent Posts

Categories

Related Links

  • RTEMS
    RTEMS
  • GNU
  • Linux Kernel
  • Arduino

Search


This Site was built by Rimond, generated with Jekyll, and hosted on GitHub Pages
©2013-2018 – Rimond