Linux hook技术之如何理解Ring3下动态链接库(linux,编程语言)

时间:2024-05-05 00:06:21 作者 : 石家庄SEO 分类 : 编程语言
  • TAG :

一、动态链接库函数劫持原理

Unix操作系统中,程序运行时会按照一定的规则顺序去查找依赖的动态链接库,当查找到指定的so文件时,动态链接器(/lib/ld-linux.so.X)会将程序所依赖的共享对象进行装载和初始化,而为什么可以使用so文件进行函数的劫持呢?

这与LINUX的特性有关,先加载的so中的全局符号会屏蔽掉后载入的符号,也就是说如果程序先后加载了两个so文件,两个so文件定义了同名函数,程序中调用该函数时,会调用先加载的so中的函数,后加载的将会屏蔽掉;所以要实现劫持,必须要抢得先机。

环境变量LD_PRELOAD以及配置文件/etc/ld.so.preload就可以让我们取得这种先机,它们可以影响程序的运行时的链接(Runtime linker),它允许你定义在程序运行前优先加载的动态链接库,我们只要在通过LD_PRELOAD加载的.so中编写我们需要hook的同名函数,即可实现劫持!从下图中我们使用strace可以看到,优先加载了LD_PRELOAD指明的.so

Linux hook技术之如何理解Ring3下动态链接库

劫持普通函数当然没有什么意思了!我们要劫持的是系统函数!我们知道,Unix操作系统中对于GCC而言,默认情况下,所编译的程序中对标准C函数(fopen、printf、execv家族等等函数)的链接,都是通过动态链接方式来链接libc.so.6这个函数库的,我们只要在加载libc.so.6之前加载我们自己的so文件就可以劫持这些函数了。

二、Demo

我们从一个简单的c程序(sample.c)开始

下面的代码标准调用fopen函数,并检查返回值

#include<stdio.h>intmain(void){printf("Callingthefopen()function...\n");FILE*fd=fopen("test.txt","r");if(!fd){printf("fopen()returnedNULL\n");return1;}printf("fopen()succeeded\n");return0;}

编译执行

$gcc-osamplesample.c$./sampleCallingthefopen()function...fopen()returnedNULL$touchtest.txt$./sampleCallingthefopen()function...fopen()succeeded

开始编写我们自己的so动态库

#include<stdio.h>FILE*fopen(constchar*path,constchar*mode){printf("Thisismyfopen!\n");returnNULL;}

编译成.so

gcc-Wall-fPIC-shared-omyfopen.somyfopen.c

设置环境变量后执行sample程序,我们可以看到成功劫持了fopen函数,并返回了NULL

$LD_PRELOAD=./myfopen.so./sampleCallingthefopen()function...Thisismyfopen!fopen()returnedNULL

当然 ,使fopen始终返回null是不明智的,我们应该在假的fopen函数中还原真正fopen的行为,看下面代码 这回轮到 dlfcn.h 出场,来对动态库进行显式调用,使用dlsym函数从c标准库中调用原始的fopen函数,并保存原始函数的地址以便最后返回 恢复现场

#define_GNU_SOURCE#include<stdio.h>#include<dlfcn.h>FILE*fopen(constchar*path,constchar*mode){printf("Inourownfopen,opening%s\n",path);FILE*(*original_fopen)(constchar*,constchar*);original_fopen=dlsym(RTLD_NEXT,"fopen");return(*original_fopen)(path,mode);}

Tips: 如果dlsym或dlvsym函数的第一个参数的值被设置为RTLD_NEXT,那么该函数返回下一个共享对象中名为NAME的符号(函数)的运行时地址。 下一个共享对象是哪个,依赖于共享库被加载的顺序。dlsym查找共享库顺序如下: ①环境变量LD_LIBRARY_PATH列出的用分号间隔的所有目录。 ②文件/etc/ld.so.cache中找到的库的列表,由ldconfig命令刷新。 ③目录usr/lib。 ④目录/lib。 ⑤当前目录。 编译:

gcc-Wall-fPIC-shared-omyfopen.somyfopen.c-ldl

执行:调用原始函数,劫持成功!

$LD_PRELOAD=./myfopen.so./sampleCallingthefopen()function...Inourownfopen,openingtest.txtfopen()succeeded

三、需要注意的问题以及LD_PRELOAD hook的应用

需要注意的问题

1.so文件加载及函数劫持的顺序。

在很多情况下,在你进行劫持之前,系统中已经有其他组件也对该函数进行了劫持,那么就要特别注意so加载的顺序,一定要在其他组件的so库加载前加载自己的so库,否则你的hook函数将会被忽略。

2.保持原本函数的完备性与业务的兼容性。被hook的函数一定要hook结束时进行返回,返回前自己的执行逻辑中不能过度延时,过度延时可能造成原有的业务逻辑失败。使用RTLD_NEXT 句柄,维持原有的共享库调用链。

应用一:HIDS入侵检测系统

劫持libc库

优点: 性能较好, 比较稳定, 相对于LKM更加简单, 适配性也很高, 通常对抗web层面的入侵.

缺点: 对于静态编译的程序束手无策, 存在一定被绕过的风险.

应用二:rootkit恶意软件

已经有多种恶意软件应用了此技术,常见的有cub3、vlany、bdvl等

 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:Linux hook技术之如何理解Ring3下动态链接库的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:Fireeye中如何部署勒索软件下一篇:

3 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18