LD_PRELOAD替换含枚举与结构体函数及Curl_setopt定位问题
关于LD_PRELOAD Hook的两个问题解答
一、枚举/结构体指针的类型替代是否可行?
首先给出明确结论:类型替换本身是可行的,但你的代码存在语法错误导致无法运行。
具体分析:
- 枚举类型在C语言中本质是整数类型(通常默认是
int),用unsigned int替代枚举类型,在调用约定(参数传递、栈布局)层面完全兼容,不会因为类型不匹配导致调用失败。 Structure1*是指针类型,void*可以兼容任何指针类型,所以用void*替代结构体指针也是可行的,只要你在调用原函数时保证指针指向的实际类型正确即可。
你的代码里的明显错误:
- 变量名不匹配:函数参数是
handle,但调用原函数时写成了未定义的ptr;参数e2被写成了未定义的option。 - 缺少错误检查:调用
dlsym后没有判断是否成功获取函数指针,容易触发空指针调用崩溃。
修正后的代码示例:
#define _GNU_SOURCE #include <stdio.h> #include <stdarg.h> #include <dlfcn.h> typedef unsigned int (*foo_t)(void* ptr, unsigned int e2); unsigned int foo(void* handle, unsigned int e2) { printf("foo hooked!\n"); // 获取原函数指针并做错误检查 foo_t foo_f = (foo_t)dlsym(RTLD_NEXT, "foo"); if (!foo_f) { fprintf(stderr, "dlsym error: %s\n", dlerror()); return -1; // 根据实际枚举值返回对应错误码 } // 调用原函数,注意变量名要匹配 unsigned int result = foo_f(handle, e2); return result; }
二、Hook Curl_setopt失败的原因
你遇到的问题核心是:Curl_setopt是libcurl的内部未导出函数,无法通过LD_PRELOAD hook。
具体细节:
- 通过
nm -D看到的是动态库中对外导出的符号,Curl_setopt没有出现在列表里,说明它是libcurl的内部函数(可能被声明为static,或者编译时未开启符号导出),动态链接器无法识别这个符号,自然也无法通过dlsym获取它的地址。 - 反汇编
curl_easy_setopt没有看到对Curl_setopt的调用,大概率是因为:Curl_setopt被编译器内联到curl_easy_setopt的实现中了,所以没有显式的call指令;Curl_setopt是静态链接的内部函数,调用时直接使用相对地址,不会通过动态符号表查找。
如果想要hook curl的setopt逻辑,正确的做法是直接hook对外暴露的公开API curl_easy_setopt,它的声明是公开可查的:
CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
对应的hook代码示例:
#define _GNU_SOURCE #include <stdio.h> #include <dlfcn.h> #include <curl/curl.h> #include <stdarg.h> typedef CURLcode (*curl_easy_setopt_t)(CURL*, CURLoption, ...); CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...) { printf("curl_easy_setopt hooked! Option code: %d\n", option); curl_easy_setopt_t orig_func = (curl_easy_setopt_t)dlsym(RTLD_NEXT, "curl_easy_setopt"); if (!orig_func) { fprintf(stderr, "dlsym error: %s\n", dlerror()); return CURLE_FAILED_INIT; } // 正确转发可变参数 va_list args; va_start(args, option); CURLcode result = orig_func(curl, option, args); va_end(args); return result; }
内容的提问来源于stack exchange,提问作者tejas
相关产品推荐
相关产品推荐

