调试由ifunc加载的liblzma中crc64_resolve函数遇阻求助
调试xz后门中crc64_resolve IFUNC函数的问题与解决
问题根源
crc64_resolve作为IFUNC解析器,会在**liblzma库加载的重定位阶段(RTLD_NOW模式)**立即执行,你先启动sshd再attach gdb的方式,会错过这个执行时机——此时liblzma已经加载完成,该函数早就执行过了。- 直接修改已被进程加载的库文件的磁盘副本,不会同步到进程内存中的映射内容,进程加载库后,磁盘文件的修改对已运行的进程无影响。
修正后的调试流程
1. 预先修改未加载的liblzma文件
确保修改的是未被任何进程加载的库文件:
# 重新编译并复制目标库 make clean && ./configure && make cp src/liblzma/.libs/liblzma.so.5.6.1 ../liblzma.so.5 # 获取crc64_resolve的文件偏移 # 先找函数的虚拟起始地址 objdump -D liblzma.so.5 | grep -w crc64_resolve # 输出示例:000000000005f120 <crc64_resolve>: # 再获取库的加载基地址(ELF首段LOAD的文件偏移) readelf -l liblzma.so.5 | grep -w LOAD | head -1 # 输出示例:LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x000f98 0x000f98 R E 0x1000 # 此处函数文件偏移等于虚拟起始地址(因为基地址为0),即0x5f120 # 用hexedit修改该偏移处首字节为0xCC(int3断点) hexedit liblzma.so.5
2. 用gdb直接启动sshd(而非事后attach)
只有让gdb从进程启动阶段就接管,才能捕获IFUNC解析器的执行:
# 以root身份,指定LD_LIBRARY_PATH并启动gdb调试sshd sudo env -i LD_LIBRARY_PATH=/home/vboxuser/xz/ gdb /usr/sbin/sshd
3. 在gdb中配置断点并启动进程
进入gdb后执行:
# 捕获liblzma加载事件(可选,用于确认库加载时机) catch load liblzma.so.5 # 启动sshd并指定参数 run -D -p 2222
当liblzma加载触发暂停后,继续设置断点并执行:
# 直接给crc64_resolve设置符号断点 b crc64_resolve # 继续执行进程 c
此时会触发你预先插入的0xCC断点,进入crc64_resolve的调试流程。
备选方案:用预加载库拦截启动流程
如果直接启动调试有问题,可通过LD_PRELOAD让进程暂停在启动初期,给gdb留足设置断点的时间:
- 编写预加载库代码(
preload.c):
#include <stdio.h> void __attribute__((constructor)) preload_init() { fprintf(stderr, "Preloaded, attach gdb and set wait=0 to continue\n"); volatile int wait = 1; while (wait); }
- 编译为共享库:
gcc -shared -fPIC preload.c -o preload.so
- 启动sshd并加载预加载库:
sudo env -i LD_PRELOAD=/home/vboxuser/xz/preload.so LD_LIBRARY_PATH=/home/vboxuser/xz/ /usr/sbin/sshd -D -p 2222
此时进程会卡在preload_init中,attach gdb后执行set wait=0即可继续,同时可提前设置crc64_resolve的断点。
验证要点
- 用
cat /proc/<pid>/maps | grep liblzma查看进程内存映射,确认加载的是你修改后的库文件路径。 - 确认IFUNC解析器的执行时机:库加载的重定位阶段,必须让gdb在进程启动初期接管。
内容的提问来源于stack exchange,提问作者coffee
相关产品推荐
相关产品推荐

