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

LD_PRELOAD注入自定义malloc/free失效问题求助

LD_PRELOAD替换malloc/free失效的问题分析与解决

核心原因

你遇到的问题本质是:这类程序(Discord、Telegram、MS Teams、Firefox都基于Chromium/Electron框架)启动后会通过execve创建子进程,而Chromium的沙箱机制会主动清除环境变量,且部分子进程可能以SUID权限启动,导致LD_PRELOAD无法被继承。另外,你的预加载库可能只覆盖了malloc和free,但程序后续调用了其他内存分配函数(如calloc、realloc),造成"不再调用"的错觉。

解决办法

1. 禁用Chromium沙箱(快速验证实验)

Chromium沙箱会严格限制子进程的环境变量和权限,直接添加--no-sandbox参数可以绕过这个限制:

LD_PRELOAD=./my_malloc.so /snap/discord/151/usr/share/discord/Discord --no-sandbox

注意:关闭沙箱会降低程序安全性,仅用于实验场景。

2. 让LD_PRELOAD传递到所有子进程

  • 全局设置环境变量:通过pam_env让所有登录进程继承LD_PRELOAD,编辑/etc/security/pam_env.conf添加:
    LD_PRELOAD DEFAULT=/绝对路径/your/my_malloc.so
    
    测试完成后务必删除该行,避免影响系统所有进程。
  • 追踪并手动启动子进程:用strace查看程序的execve调用,找到子进程启动命令后手动注入LD_PRELOAD:
    strace -f -e execve /snap/discord/151/usr/share/discord/Discord 2>&1 | grep execve
    
    输出中会显示子进程的启动路径,直接用LD_PRELOAD启动该路径的二进制文件。

3. 完善预加载库的覆盖范围

确保替换所有内存分配相关函数,避免程序绕过你的实现:

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

// 保存原始函数指针
static void* (*orig_malloc)(size_t) = NULL;
static void (*orig_free)(void*) = NULL;
static void* (*orig_calloc)(size_t, size_t) = NULL;
static void* (*orig_realloc)(void*, size_t) = NULL;

void* malloc(size_t size) {
    if (!orig_malloc) orig_malloc = dlsym(RTLD_NEXT, "malloc");
    void* ptr = orig_malloc(size);
    printf("allocated: %zu bytes, at: %p\n", size, ptr);
    return ptr;
}

void free(void* ptr) {
    if (!orig_free) orig_free = dlsym(RTLD_NEXT, "free");
    printf("free at: %p\n", ptr);
    orig_free(ptr);
}

void* calloc(size_t nmemb, size_t size) {
    if (!orig_calloc) orig_calloc = dlsym(RTLD_NEXT, "calloc");
    void* ptr = orig_calloc(nmemb, size);
    printf("callocated: %zu * %zu = %zu bytes, at: %p\n", nmemb, size, nmemb*size, ptr);
    return ptr;
}

void* realloc(void* ptr, size_t size) {
    if (!orig_realloc) orig_realloc = dlsym(RTLD_NEXT, "realloc");
    void* new_ptr = orig_realloc(ptr, size);
    printf("reallocated: %zu bytes, from %p to %p\n", size, ptr, new_ptr);
    return new_ptr;
}

编译命令:

gcc -shared -fPIC -ldl -o my_malloc.so my_malloc.c

4. 验证库的加载状态

用ps aux | grep <程序名>找到所有相关进程,然后查看进程的映射表确认你的库是否加载:

cat /proc/<进程PID>/maps | grep my_malloc.so

如果某个进程没有加载你的库,说明该进程启动时未继承LD_PRELOAD,需要用前面的方法处理。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 12:25:15