You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux下如何正确hook malloc函数?现有方案仍存递归问题

如何安全Hook malloc避免无限递归

你提到的两种Hook malloc的方案都会触发无限递归,核心原因是:第一次调用dlsym(RTLD_NEXT, "malloc")时,dlsym内部会调用malloc,而此时自定义的malloc已经被动态链接器优先加载,会再次进入自定义的malloc函数,由于real_malloc还未初始化,会反复调用dlsym导致无限递归。

以下是几种可行的解决方法:

方案1:利用构造函数提前获取真实malloc地址

通过GCC的__attribute__((constructor))属性,在程序进入main前自动执行初始化逻辑,提前获取libc的真实malloc地址。此时构造函数的执行时机早于任何用户代码的malloc调用,且dlsym在此阶段调用不会触发自定义的malloc hook,能安全完成初始化。

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

static void* (*real_malloc)(size_t) = NULL;

// 构造函数,程序启动时自动执行
__attribute__((constructor))
void init_real_malloc() {
    real_malloc = dlsym(RTLD_NEXT, "malloc");
    if (!real_malloc) {
        fprintf(stderr, "Failed to resolve real malloc: %s\n", dlerror());
        _exit(EXIT_FAILURE);
    }
}

void* malloc(size_t size) {
    printf("malloc(%zu) bytes requested\n", size);
    return real_malloc(size);
}

方案2:直接加载libc库获取malloc地址(底层方案)

跳过RTLD_NEXT,直接打开系统的libc动态库,从中获取malloc的符号地址。这种方式完全绕开了动态链接器的符号优先级,避免dlsym触发自定义malloc。

注意:不同系统的libc库路径不同,Linux下通常是libc.so.6,macOS下是libSystem.B.dylib,需要根据目标系统调整。

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

static void* (*real_malloc)(size_t) = NULL;

__attribute__((constructor))
void init_real_malloc() {
    // Linux下的libc路径,macOS替换为"libSystem.B.dylib"
    void* libc_handle = dlopen("libc.so.6", RTLD_NOW);
    if (!libc_handle) {
        fprintf(stderr, "Failed to open libc: %s\n", dlerror());
        _exit(EXIT_FAILURE);
    }

    real_malloc = dlsym(libc_handle, "malloc");
    if (!real_malloc) {
        fprintf(stderr, "Failed to resolve real malloc: %s\n", dlerror());
        dlclose(libc_handle);
        _exit(EXIT_FAILURE);
    }

    dlclose(libc_handle);
}

void* malloc(size_t size) {
    printf("malloc(%zu) bytes requested\n", size);
    return real_malloc(size);
}

方案3:使用GNU malloc钩子(已废弃,仅作参考)

GNU libc曾提供__malloc_hook接口用于注册malloc回调,无需替换malloc符号即可实现Hook。但该接口已被标记为废弃,未来可能被移除,仅作兼容性参考:

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

static void* (*old_malloc_hook)(size_t, const void*);

static void* my_malloc(size_t size, const void* caller) {
    // 临时禁用钩子,避免调用真实malloc时递归触发
    __malloc_hook = old_malloc_hook;
    printf("malloc(%zu) called from %p\n", size, caller);
    void* ptr = malloc(size);
    // 恢复钩子
    __malloc_hook = my_malloc;
    return ptr;
}

__attribute__((constructor))
void init_hook() {
    old_malloc_hook = __malloc_hook;
    __malloc_hook = my_malloc;
}

内容的提问来源于stack exchange,提问作者bobeff

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 17:42:01