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 execveLD_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
相关产品推荐
相关产品推荐

