Linux下入门级导出函数截获-使用LD_PRELOAD环境变量

本文介绍了一种利用LD_PRELOAD机制对libvirt提供的虚拟化操作进行事件审计的方法。通过分析libvirt的客户端工具virsh及其依赖的动态库libvirt.so,找到了审计libvirt事件的有效切入点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    博文篇首要感谢我的同事zxb,他曾经提示我有这种简便的截获方法。

    近期要做Linux下libvirt事件审计,原计划是分析libvirt的通信数据从而进一步分析libvirt事件。尼玛,这怎么看都觉得工作量浩大,第一反应就是能不能偷懒。对于一般的审计事件,首先想到的是函数截获:遍历ELF文件的导出函数,然后替换之。顺带一提,现在安卓上的进程注入就这么做的,哪天有空了我也放一篇Linux ELF文件注入的博文。不过这个工程也不小(相比原计划已经很小了),而且我也没十足的把握稳定代码。于是,退而求其次想到标题中这种方法,此法,也是首次尝试。

1)    先来整理下当时的处理思路:libvirt提供了一个命令行客户端工具--virsh,通过virsh可以使用libvirt提供的功能,如创建域。首先,可以肯定的是libvirt是个成功的项目,所以,客户端代码肯定和实际虚拟化操作是分开的,他们的唯一结合处一定是调用libvirt某个动态库导出的函数,来找一下他们的契合处:

root@ubuntu:~# which virsh
/usr/local/bin/virsh
root@ubuntu:~# ldd /usr/local/bin/virsh
	linux-gate.so.1 =>  (0xb770d000)
	libvirt.so.0 => /usr/lib/libvirt.so.0 (0xb743d000)
	libvirt-qemu.so.0 => /usr/lib/libvirt-qemu.so.0 (0xb7439000)
	libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xb741d000)
可以看到virsh依赖于libvirt.so这个动态库。再来看看这个动态库是否提供了virsh命令行所需要的接口:

virsh创建域会调用virDomainCreateXML这个API,来看下virDomainCreateXML在virsh中的符号形式:

root@ubuntu:~# nm /usr/local/bin/virsh|grep virDomainCreateXML
         U virDomainCreateXML@@LIBVIRT_0.5.0
nm显示virDomainCreateXML在virsh中是未解析的符号名,意味着,virsh中没有对应的实现,那必须在其他模块中实现否则都不会通过链接的步骤。可以猜测,virDomainCreateXML肯定在libvirt中实现(我看了源码,当然知道在这个so中实现。你不服,可在ldd virsh输出的所有动态库中搜索这个API)。

root@ubuntu:~# nm /usr/lib/libvirt.so.0 | grep virDomainCreateXML
000f7c40 T virDomainCreateXML
nm显示virDomainCreateXML的确在libvirt.so中实现。如此可以确定virsh以至于其他客户端工具,要使用libvirt提供的虚拟化操作,都依赖这个库的实现。咩哈哈哈哈哈,后面都用LD_PRELOAD来截获对该动态库的调用了,以此来实现对libvirt的审计。

2)    扯了这么久,还没怎么利用LD_PRELOAD。这不,思路很重要么,至少看到这知道了审计事件时,可以用这种方式去实现么。好,先放个链接:http://blog.youkuaiyun.com/haoel/article/details/1602108  这位博主详细介绍了什么是LD_PRELOAD以及如何利用。但是,这位博主只做了一半,还有一半没做:就是,你把水截流了,还得把水放到下游去啊,要不然下游人民怎么生活!光简单粗暴的截获了strcmp,然后return 0这不是改的strcmp他妈都不认识他了么?为了实现strcmp的原有功能,这里我用到了dlopen/dlsym,用来加载动态库和获得导出函数。类似于windows的LoadLibrary和GetProcAddr。值得一提的事,linux的进程加载器也是使用这两个函数加载所依赖的so库。

下面来看下我对那位博主代码的扩充:

hack.c
#define _GNU_SOURCE

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

typedef int (*detour_strcmp)(const char*,const char*);
detour_strcmp g_Strcmp;
int strcmp(const char *s1, const char *s2)
{
	int res=0;
    printf("hack function invoked. s1=<%s> s2=<%s>\n", s1, s2);

    g_Strcmp = dlsym(RTLD_NEXT, "strcmp");
    if(g_Strcmp==NULL)
    {
    	printf("load strcmp failed\n");
    	return 0;
    }
    res = (*g_Strcmp)(s1,s2);
    printf("compare result:%d\n",res);
    return res;
}
因为使用了dlopen和dlsym编译连接时,需要加上-ldl

gcc -shared -o hack.so hack.c -ldl

最后,来看下新strcmp的输出:

root@ubuntu:~/Desktop# export LD_PRELOAD="./hack.so"
root@ubuntu:~/Desktop# ./verifypasswd 
usage: ./verifypasswd <password>/nroot@ubuntu:~/Desktop# ./verifypasswd 1
hack function invoked. s1=<password> s2=<1>/ncompare result:1
Invalid Password!/n
输出无效的密码!至少可以知道strcmp是被调用过了

<think>好的,我现在需要帮助用户找到在RedHat系统中删除环境变量LD_LIBRARY_PATH和LD_PRELOAD的方法。首先,我应该回忆一下环境变量Linux系统中的管理方式。用户提到的这两个变量都是动态链接库相关的,通常用于指定库的路径和预加载库。 根据引用[1]和[2],用户之前可能设置过这些环境变量,比如通过export命令或者修改shell的配置文件。删除环境变量通常可以通过几种方式:在当前会话中unset,或者从配置文件中移除相关设置,或者通过系统服务配置调整。 首先,考虑临时删除。用户可以使用unset命令在当前终端会话中立即移除变量,例如: unset LD_LIBRARY_PATH unset LD_PRELOAD 但这种方法只是临时的,关闭终端后会失效。 接下来是永久删除。用户需要检查shell的配置文件,比如.bashrc、.bash_profile或/etc/profile,找到export这些变量的行并删除。例如,引用[1]中提到用户添加了export LD_LIBRARY_PATH=...,所以应该去对应的配置文件里删除那一行,然后重新加载配置或者重启shell。 另外,引用[2]和[5]提到系统服务如mysqld可能通过systemd管理,这时候可能需要检查服务配置文件中的环境变量设置。用户可能需要编辑服务的unit文件(如mysql.service),移除或注释掉Environment指令中的相关变量,并重新加载systemd配置。 还有引用[3]提到的/etc/ld.so.preload文件,如果用户修改过这个文件,可能需要清理里面的内容,但这和LD_PRELOAD环境变量不同,需要分别处理。用户可能需要检查该文件并删除不需要的库路径。 需要提醒用户注意,不同的设置方式对应不同的删除方法。如果是通过脚本或临时命令设置的,重启后会失效;如果是配置文件中的,需要手动修改。此外,系统服务中的变量可能需要更高的权限来修改,比如使用sudo编辑系统级配置文件。 最后,确保用户了解操作的影响,比如删除这些变量后,依赖它们的程序可能无法运行,需要确认是否有必要删除,或者是否有替代的配置方式。</think>在RedHat系统中删除环境变量$LD\_LIBRARY\_PATH$和$LD\_PRELOAD$的方法如下: ### 一、临时删除(仅当前会话生效) ```bash unset LD_LIBRARY_PATH unset LD_PRELOAD ``` *此方法仅对当前终端会话有效,重启后恢复原设置[^1][^2]。* ### 二、永久删除(需修改配置文件) 1. **检查环境变量定义位置** - 用户级:检查`~/.bashrc`、`~/.bash_profile`、`~/.profile` - 系统级:检查`/etc/profile`、`/etc/environment` ```bash grep -rn "LD_LIBRARY_PATH\|LD_PRELOAD" ~/ /etc/ ``` 2. **注释或删除相关行** 例如原设置行可能为: ```bash export LD_LIBRARY_PATH=/your/path/lib:$LD_LIBRARY_PATH # 注释此行[^1] export LD_PRELOAD=/path/to/library.so # 删除此行[^2] ``` 3. **应用修改** ```bash source ~/.bashrc # 根据实际修改的配置文件选择 ``` ### 三、系统服务配置清理(针对服务调用) 若通过systemd服务设置(如MySQL服务[^5]): 1. 检查服务配置文件: ```bash systemctl show mysql.service | grep Environment ``` 2. 编辑服务unit文件: ```bash sudo systemctl edit mysql.service ``` 3. 移除包含`LD_PRELOAD`或`LD_LIBRARY_PATH`的`Environment`指令 ### 四、附加清理项 - 检查`/etc/ld.so.preload`文件(独立于环境变量)[^3] ```bash sudo vim /etc/ld.so.preload # 删除相关库路径 ``` ### 五、验证删除结果 ```bash echo $LD_LIBRARY_PATH # 应输出空行 echo $LD_PRELOAD # 应输出空行 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值