linux LD_PRELOAD 预加载 so 简介

本文介绍了Linux系统中利用LD_PRELOAD环境变量预加载动态链接库的方法,包括修改/etc/ld.so.preload配置文件和启动进程前设置LD_PRELOAD。预加载库可以用于hook系统调用,例如捕获socket函数调用。然而,LD_PRELOAD也带来安全风险,如静态链接或设置SUID权限可避免其影响。文章探讨了使LD_PRELOAD失效的策略,并提醒注意其潜在的安全隐患。
摘要由CSDN通过智能技术生成

预加载so的两种方式:

  1. 修改/etc/ld.so.preload配置文件,这种方法对配置修改之后运行的进程生效,而无法影响已经在运行的进程;
  2. 启动进程前设置LD_PRELOAD变量(如shell中执行LD_PRELOAD=/lib64/inject.so ./myprocess),则只对当前进程生效。

默认情况下进程创建的子进程也会继承Preload环境变量,而父进程可以在子进程初始化前修改子进程的环境变量,从而避免往子代传播。

LD_PRELOAD可以影响程序的运行时的链接,它允许你定义在程序运行前优先加载的动态链接库,这个功能主要就是用来有选择性的载入不同动态链接库中的相同函数。

通过这个环境变量,我们可以在主程序和其动态链接库的中间加载别的动态链接库,甚至覆盖正常的函数。

进程在启动后,会按照一定顺序加载动态库:

  • 加载环境变量LD_PRELOAD指定的动态库
  • 加载文件/etc/ld.so.preload指定的动态库
  • 搜索环境变量LD_LIBRARY_PATH指定的动态库搜索路径
  • 搜索路径/lib64下的动态库文件

因此可以使用预加载实现hook功能,一个简单例子,捕获所有socket函数:

// inject.c
#include <stdio.h>
#include <sys/socket.h>

 __attribute__ ((visibility("default"))) int socket(int family, int type, int protocol) {

    printf("detect socket call\n");
    return -1;
}

__attribute__((constructor)) void main() {
    printf("module inject success\n");
}

然后在shell环境中执行以下命令:

gcc inject.c --shared -fPIC -o inject.so # 生成so库(*)
LD_PRELOAD=$PWD/inject.so ping 127.0.0.1 # 使用LD_PRELOAD预加载
# 输出内容如下
# module inject success 
# detect socket call 

不可否认,LD_PRELOAD是一个很难缠的问题。目前来说,要解决这个问题,只能想方设法让LD_PRELOAD失效。目前而言,有以下面两种方法可以让LD_PRELOAD失效。

  1. 通过静态链接。使用gcc的-static参数可以把libc.so.6静态链入执行程序中。但这也就意味着你的程序不再支持动态链接。
  2. 通过设置执行文件的setgid/setuid标志。在有SUID权限的执行文件,系统会忽略LD_PRELOAD环境变量。也就是说,如果你有以root方式运行的程序,最好设置上SUID权限。

在一些UNIX版本上,如果要使用LD_PRELOAD环境变量,需要有root权限。但不管怎么说,这些个方法目前来看并不是一个彻底的解决方案,为了安全,只能禁用LD_PRELOAD。

 

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值