美文网首页
基于LD_PRELOAD的动态库函数hook

基于LD_PRELOAD的动态库函数hook

作者: DayDayUpppppp | 来源:发表于2021-10-13 21:31 被阅读0次
1. LD_PRELOAD 实现注入的原理

LD_PRELOAD是linux系统中的一个环境变量,它可以指定优先加载某个动态库。当主程序中有相同的符号出现在不同的动态库中,会使用优先加载的动态库中的符号。根据这个原理,如果要被hook的函数在动态库a中,那么可以重载一个相同定义的函数并把它编译成动态库b,并使用LD_PRELOAD执行优先加载动态库b。当启动主程序的时候,主程序会调用动态库b中的函数。通过这个环境变量,我们可以在主程序和其动态链接库的中间加载别的动态链接库,去覆盖正常的函数库。

默认情况下linux的动态库链接顺序:

LD_PRELOAD --> LD_LIBRARY_PATH --> /lib --> /usr/lib

使用LD_PRELOAD替换rand函数

// main.cpp
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
 
int main(int argc, char** argv)
{
    srand((unsigned)time(NULL));
    int value = rand();

    printf("value is %d \n", value);
    return 0;
}
// hook.cpp
#include <stdlib.h>
#include <stdio.h>

// hock 函数
int rand (void)
{
    printf("hock function \n");
    return 100;   // 返回一个固定值
}
[linux@ t0]~$tree -L 2
.
|-- a.out
|-- hook.cpp
|-- hook.o
|-- libhook.so
`-- main.cpp

// 编译
[linux@ t0]~$g++ main.cpp
[linux@ t0]~$g++ -Wall -fPIC -c hook.cpp -o hook.o
[linux@ t0]~$g++ -shared -o libhook.so hook.o

// 执行
[linux@ t0]~$LD_PRELOAD=./libhook.so ./a.out 
hock function 
value is 100 

通过ldd可以查看依赖关系

[linux@ t0]~$ldd ./a.out 
        linux-vdso.so.1 (0x00007ffff7ffb000)
        libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007ffff7a3f000)
        libm.so.6 => /lib64/libm.so.6 (0x00007ffff76bd000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007ffff74a5000)
        libc.so.6 => /lib64/libc.so.6 (0x00007ffff70e3000)
        /lib64/ld-linux-x86-64.so.2 (0x00007ffff7dd4000)

[linux@ t0]~$LD_PRELOAD=./libhook.so ldd ./a.out 
        linux-vdso.so.1 (0x00007ffff7ffb000)
        ./libhook.so (0x00007ffff7ff1000)     <----- 区别在这里
        libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007ffff7a3f000)
        libm.so.6 => /lib64/libm.so.6 (0x00007ffff76bd000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007ffff74a5000)
        libc.so.6 => /lib64/libc.so.6 (0x00007ffff70e3000)
        /lib64/ld-linux-x86-64.so.2 (0x00007ffff7dd4000)

关于LD_PRELOAD 命令的一些操作

1. 通过命令 export LD_PRELOAD="库文件路径",设置要优先替换动态链接库
2. 如果找不替换库,可以通过 export LD_LIBRARY_PATH=库文件所在目录路径,设置系统查找库的目录
3. 替换结束,要还原函数调用关系,用命令unset LD_PRELOAD 解除
4. 想查询依赖关系,可以用ldd 程序名称

2. attribute(construct)

在加载动态库的时候,可以利用attribute关键字定义加载动态库的init函数。这是一个非常有用的特性。很多基于preload动态库的程序都会用到这个机制。

#include <stdlib.h>
#include <stdio.h>

// 这里定义了一个my_init_so函数
// 并通过attrbute关键字让它在成员加载这个动态库之后,执行的一个函数
void __attribute__ ((constructor)) my_init_so()
{
    printf("init so\n");
}

int rand (void)
{
    printf("hock function \n");
    return 100;
}

attribute的具体作用这里先不说,可以先记住attribute可以定义一个加载动态库之后的一个初始化函数。


3. LD_PRELOAD hook malloc函数实现无侵入malloc插桩

利用这个原理,可以hook malloc函数,而且被监控的进程不需要改动任何代码。核心代码如下:

static void myInitHook(void)
{
    Logout("setting up hooks...");
    old_malloc_hook = __malloc_hook;
    old_free_hook   = __free_hook;
    __malloc_hook   = my_malloc_hook;
    __free_hook     = my_free_hook;
}
static void* myMallocHook(size_t size, const void* caller)
{
    void* res;
    restoreOldHooks();
    res = malloc(size);
    saveOldHooks();
 
    // Do your memory statistics here...
    snprintf(logBuff, sizeof(logBuff)
        , "malloc (%u) returned @%p", (unsigned int) size, res);
    Logout(logBuff);

    // 打印调用栈
    printBacktrace();

    // Restore our own hooks
    restoreMyHooks();
    return res;
}

把这个小工具封装成了一个库,可以拆包使用(https://github.com/zhaozhengcoder/libmallocTrace )可以无侵入的获得目标程序调用malloc,free,new,delete的函数调用找。

示例如下:

// example.cpp 
void leak(int num)
{
    printf("%s [malloc] allocating %d bytes...\n", __PRETTY_FUNCTION__, num);
    void * p1 = malloc(num);
    memset(p1, 0, num);

    printf("%s [new] allocating %d bytes...\n", __PRETTY_FUNCTION__, num);
    char * p2 = new char[num];
    memset(p2, 0, num);
    return;
}

int main(int argc, char** argv)
{
    srand((unsigned)time(NULL));
    printf("%s: PID: %d\n", __PRETTY_FUNCTION__, getpid());

    while (1) 
    {
        leak(rand() % 1024);
        notleak(rand() % 1024);
        sleep(rand() % 10);
    }
    return 0;
}
// 不需要修改原程序的代码,只需要ld preload这个库
LD_PRELOAD=../libmTrace.so ./example
trace log输出效果

相关文章

网友评论

      本文标题:基于LD_PRELOAD的动态库函数hook

      本文链接:https://www.haomeiwen.com/subject/vsseoltx.html