首页 > 其他分享 >利用LD_PRELOAD给glibc库函数加钩子

利用LD_PRELOAD给glibc库函数加钩子

时间:2023-06-15 16:38:59浏览次数:44  
标签:PRELOAD fork LD void include strlen hello 库函数


网上已经有不少相关文章,具体可参考:

 

通过getuid、printf等函数讲解了基本的加钩子的方法:

http://blog.chinaunix.net/u/9577/showart_1195703.html

 

如果你希望的不仅仅是替换掉原有库函数,而且还希望最终将函数逻辑传递到原有系统函数,那么你可能需要用到RTLD_NEXT。系统可能提示RTLD_NEXT未定义,这里给出了解决方案:

http://xueruini.spaces.live.com/blog/cns!DF086AB717BC7F6F!517.entry

 

使用dlsym时候可能遇到链接错误,提示找不到dlsym。解决方法是编译的时候加上-ldl编译选项:

http://blog.tianya.cn/blogger/post_show.asp?BlogID=78856&PostID=13635493

 

 

 

我的过程记录

 

fork.c,最后编译成fork.so

 

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dlfcn.h>
/* 即使按照参考文献中的方法,定义__USE_GNU
 * 还是被提示RTLD_NEXT未定义
 * 只能用这种猥琐的,不可移植的方法了
 * 实验目的,无伤大雅。
 */
# define RTLD_NEXT      ((void *) -1l)
static pid_t (*real_fork)(void);
pid_t fork(void)
{
        printf("Fork is called/n");
        if (real_fork == NULL)
        {
                real_fork = (pid_t (*)(void))dlsym( RTLD_NEXT, "fork" );
        }
        return real_fork();
}

 

strlen.c,最后编译成strlen.so 。 需要说明的是,最后这个so没有用到,因为我遇到了一个诡异的事情,详细见后文。

 

#include <stdio.h>
size_t strlen(const char *s)
{
        size_t i = 0;
        printf("strlen is called, return x/n");
        while(*s)
        {
                i++;
                s++;
        }
        return i;
}

 

测试代码。测试了strlen和fork。

但是,我并没有为strlen加钩子,因为,我发现,无论是否挂钩strlen,这个测试函数总是没有反应,根本没有进入到strlen.c的代码中。不过呢,当我用export LD_PRELOAD="./strlen.so"后,vi、ls等应用程序都能够进入到strlen.c中,唯独我的./hello不能进入strlen.c。诡异!

 

fork函数测试有效。

 

#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc,char** argv)
{
        pid_t m;
        if(argc < 2)
                exit(0);
        const char* hello = argv[1];
        printf("%s length is %d/n",hello, strlen(hello));
        m = fork();
        printf("pid=%d/n", (pid_t)m);
        return 0;
}

 

 

编译过程(只涉及到 fork.c 和 hello.c )

 

gcc -fPIC -shared -ldl -o fork.so fork.c
; note: 如果没有家ldl,则提示找不到符号dlsym,没有家-fPIC,则编译器会提示添加此选项。跟网上的一些资料有点出入。
 
gcc -o hello hello.c
 
export LD_PRELOAD="./fork.so"
 
./hello  abcd
abcd length is 4
 Fork is called
 pid=0
 pid=12828
export LD_PRELOAD=""
; clear preload path

 

上面使用LD_PRELOAD的方法有个问题,它是一个持久的全局设置,可能会影响到./hello之外的程序的正常行为。一个更好的使用方法是直接执行:

LD_PRELOAD="./fork.so"   ./hello  abcd




 

 

后记:

 

关于dlsym

#include <dlfcn.h>
       void *dlopen(const char *filename, int flag);
       char *dlerror(void);
       void *dlsym(void *handle, const char *symbol);
       int dlclose(void *handle);

 

LD_PRELOAD能够很方便地实现应用层的二进制兼容,值得推广。同时谨记LD_PRELOAD不可滥用,否则会干扰正常系统的功能。一般,用完后需要将LD_PRELOAD的内容清空。

 

标签:PRELOAD,fork,LD,void,include,strlen,hello,库函数
From: https://blog.51cto.com/u_16162111/6493131

相关文章

  • 探秘C#中的yield关键字
    在"C#中,什么时候用yieldreturn"中,我们了解到:使用yieldreturn返回集合,不是一次性加载到内存中,而是客户端每调用一次就返回一个集合元素,是一种"按需供给"。本篇来重温yieldreturn的用法,探秘yield背后的故事并自定义一个能达到yieldreturn相同效果的类,最后体验yieldbreak的用法......
  • 海康SDK注册报错 Structure.getFieldOrder() on class com.xxx.sdk.HCNetSDK$NET_DVR_
    Structure.getFieldOrder()onclasscom.xxx.sdk.HCNetSDK$NET_DVR_DEVICEINFO_V30doesnotprovideenoughnames[0]海康依赖的版本较低,项目引用的较高,导致海康注册报错,所以降低jna版本 <dependency><groupId>net.java.dev.jna</groupId><artifactId>jna<......
  • npm install报错[email protected] postinstall: `node scripts/build.js`
    [email protected]: nodescripts/build.js解决方法:npmconfigsetsass_binary_site=https://npm.taobao.org/mirrors/node-sassnpminstall  ......
  • 使用 ProcessBuilder API 优化你的流程
    ProcessBuilder介绍Java的ProcessAPI为开发者提供了执行操作系统命令的强大功能,但是某些API方法可能让你有些疑惑,没关系,这篇文章将详细介绍如何使用ProcessBuilderAPI来方便的操作系统命令。ProcessBuilder入门示例我们通过演示如何调用java-version命令输出JD......
  • MySQL 备份还原 mysqldump
    1、参考MySQL数据备份与还原(mysqldump)mysql导入时出现“ERRORatline:Unknowncommand‘\‘‘.“的解决办法2、代码#mysqldump-h服务器-u用户名-p密码数据库名>备份文件.sqlmysqldump-uroot-ptest01>D:/test01.sql#恢复备份mysql-uroot-ptest02-......
  • ERROR: Failed building wheel for mysqlclient Running setup.py clean for mysqlc
    Itseemsthatthereisanerrorwhiletryingtoinstallthemysqlclientpackageandit'sfailingtobuildthewheel.Theerrormessageindicatesthatitcan'tfindthePython.hfile,whichisrequiredforbuildingCextensions.Toresolvethisi......
  • LocalDate中季度的使用
    季度字符串转LocalDate//方式一DateTimeFormatterBuilderbuilder=newDateTimeFormatterBuilder();DateTimeFormatterformatter=builder.appendValue(ChronoField.YEAR_OF_ERA,4,10,SignStyle.EXCEEDS_PAD).appendLiteral("-Q").appendValue(IsoFiel......
  • maven-compiler-plugin build-helper-maven-plugin Maven-assembly-plugin
    三个插件都是是用干啥的maven-compiler-plugin进行源代码的编译build-helper-maven-plugin项目中添加额外的资源、源代码、构建输出目录和依赖项等Maven-assembly-plugin生成可执行jar包<build><plugins><plugin><groupId......
  • C++ Builder 初学问与答(二)
     2.文本输入组件11)问:如果要实现文本输入,在C++Builder中应该怎么办? 答:C++Builder常用文本输入组件来实现,常用的文本输入组件有Edit、MaskEdit、Memo和RichEdit。他们的主要不同在于Edit和MaskEdit用于输入单行文本,而Memo和RichEdit可以输入多行文本。此外Label组件也可用来进行......
  • C++ Builder 初学问与答(一)
    一直以来都想写一点为BCB初学者快速入门的东西,前不久写了几篇《闲谈BCB》想把自己学习BCB中如何来解决难点的方法说给大家,没想到被骂得不成样子。本想不写了,但觉得这些东西留下来能做什么呢?还是用另一种方法来重新演译我的思维吧,最近有些忙,那几篇没有写完的文章,我也会尽快写完的,至......