协程的hook操作

本文介绍了hook机制的基本原理,包括函数劫持和动态链接库操作,展示了如何通过环境变量LD_PRELOAD实现hook系统函数(如malloc和read),以及通过源码入侵(如libco库)进行hook的方法。实例演示了如何统计malloc调用次数和hook读函数。

1. hook 原理

hook机制本质上是一种函数的劫持技术,比如我们通常需要调用malloc函数来进行内存分配,那么能不能我们自己封装一个同名、同入参和同返回值的malloc函数来替代系统的malloc函数,在我们自己封装的malloc函数中实现一些特定的功能,而且也能回调系统的malloc,这就是hook机制。
系统提供给我们的dlopen、dlsym族函数可以用来操作动态链接库,比如我们要hook系统调用函数read,我们可以使用dlsym族函数获取hook前函数的地址,这样就可以在自己实现的read中回调原函数,并加上一些额外的逻辑,并且在运行是会调用我们的版本了。
通过hook机制,libco可以达到用户无感的情况下把同步的代码替换为异步,这也是腾讯工程师写出libco的目的。libco库里面提供了socket族函数的hook,使得后台逻辑服务几乎不用修改逻辑代码就可以完成异步化改造,号称单机可以达到千万连接。

1.1 函数解析

#include <dlfcn.h>  
void * dlopen( const char * pathname, int mode ); 
  函数描述: 
  在dlopen的()函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。使用dlclose()来卸载打开的库。 
  mode:分为这两种 
  RTLD_LAZY 暂缓决定,等有需要时再解出符号 
  RTLD_NOW 立即决定,返回前解除所有未决定的符号。 
  RTLD_LOCAL 
  RTLD_GLOBAL 允许导出符号 
  RTLD_GROUP 
  RTLD_WORLD 


  返回值: 
  打开错误返回NULL 
  成功,返回库引用 
  编译时候要加入 -ldl (指定dl库) 
根据动态链接库操作句柄与符号,返回符号对应的地址。
包含头文件:
#include <dlfcn.h>
函数定义:
void*dlsym(void* handle,const char* symbol)
函数描述:
dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的地址。使用这个函数不但可以获取函数地址,也可以获取变量地址。
handle是由 dlopen打开 动态链接库后返回的 指针,symbol就是要求获取的函数或 全局变量的名称。

dlsym主要针对系统库的调用,dlopen主要针对第三方的库。且两者使用都需要包含头文件#include <dlfcn.h>。

2. hook实现

hook的实现有两种方法,第一种是使用环境变量LD_PRELOAD,第二种是直接代码入侵。

2.1 使用环境变量LD_PRELOAD

系统为我们提供了 dlopen,dlsym工具,用于运行时加载动态库。可执行文件在运行时可以加载不同的动态库,这就为hook系统函数提供了基础。下面用一个小小的例子来说明如何利用dlsym工具hook系统函数。假设现在我们需要统计程序中malloc的调用次数,但是不能修改原有程序。最简单的思路类似于Java中动态代理Proxy的做法,先找到系统的malloc函数,然后将其替换为自定义的函数,在自定义函数中增加调用次数,并回调系统的原有malloc函数。例如我们要统计以下main.c中调用malloc的次数:

// main.c
#include <stdio.h>
#include <stdlib.h>

int main() {
   
   
    int index;
    for (index=0; index < 10; index++) {
   
   
        char* p = (char*)malloc(4);
        printf("index:%d, p[0]=%d\n", index, *p);
        free(p);
    }
    printf("hello world\n");
    return 0;
}

为了能让自己的malloc函数回调系统的malloc函数,我们需要利用dlsym获取系统的malloc函数。

// myhook.c
#include <stdlib.h>
#include <dlfcn.h>
#include <stdio.h>

int count = 0;

void *malloc(size_t size) {
   
   
    void *(*myMalloc)(size_t) = dlsym(RTLD_NEXT, "malloc");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值