IDA 正确加载 libc.so 等动态库的调试信息

问题分析

在动态调试程序的时候,用gdb调试到libc的时候能正确加载符号信息,但同样的程序用IDA调试到libc的时候却缺失了libc中的许多符号,

这其实是IDA没有正确加载DWARF调试信息(debuginfo)所导致的

根本原因是系统中没有对应的调试信息(可以装libc6-dbg),或是调试信息所在的位置不正确

到网上找了一圈,发现IDA不能像gdb一样指定调试信息所在的目录,所以即便下载了调试信息也没办法直接加载,于是事情就变得有点复杂了

IDA官网上给出的解释是当前仅支持加载PDB,而不支持加载DWARF

Currently, only PDB files are supported.

不过去逆一下linux_server就会发现,其实IDA是支持加载DWARF的,只不过调试信息的路径默认为空,而且IDA没有提供方法对其进行修改

 

解决方法有四种

第零种方法:使用Load DWARF file插件,不过这个好像只能加载主程序的调试信息

第一种方法:把调试信息拷贝到优先级高的/usr/lib/debug/.build-id下,再通过patch修改linux_server的调试信息加载目录

第二种方法:给调试信息换个名字,比如libc-2.23.so.debug,避免和原来的libc-2.23.so重名

第三种方法:用IDC脚本加载调试信息

第四种方法:把调试信息附加到动态库上

这里推荐使用第一种方法,不用每次都修改二进制文件,比较方便

 

如图,虽然用的是带调试信息的libc,但是Load debug symbols的时候Output window会输出如下错误信息,这是因为加载了错误的libc-2.23.so

 

解决方案

准备工作

首先要下载libc对应的调试信息,对应的方法比较多

1、sudo apt-get install libc6-dbg

2、https://github.com/matrix1001/glibc-all-in-one

3、https://mirror.tuna.tsinghua.edu.cn/ubuntu/pool/main/g/glibc/下载对应版本的libc6-dbg_*.deb包,再用dpkg -i安装

 

解决方法一

下面主要用libc6-dbg演示,另外两种方法同理

切换工作目录到/usr/lib/debug/lib/x86_64-linux-gnu

执行以下命令,复制调试信息到/usr/lib/debug/.build-id下

复制代码
for file in `ls`
do
        buildid=`readelf -n $file|grep 'Build ID'|awk '{print $3}'`
        dir=`echo $buildid | cut -c1-2`
        fn=`echo $buildid | cut -c3-`
        sudo mkdir -p /usr/lib/debug/.build-id/$dir
        sudo cp $file /usr/lib/debug/.build-id/$dir/$fn
        sudo cp $file /usr/lib/debug/.build-id/$dir/${fn}.debug
done
复制代码

再对linux_server进行修改

1、在.rodata段中找地方写入字符串/usr/lib/debug/

2、对0x4163A3处的指令进行修改,将操作数改成字符串/usr/lib/debug/的所在位置

这样在调试的时候,IDA就会到/usr/lib/debug/.build-id下加载调试信息了

当需要加载libc信息的时候进行以下操作

1、Start/Attach debugged process

2、Pause debugged process

3、Modules->libc-2.23.so->Load debug info

4、Modules->libc-2.23.so->Analyze module

 

解决方法二

下面主要用glibc-all-in-one演示,另外两种方法同理

切换工作目录到glibc-all-in-one/libs/2.23-0ubuntu10_amd64

然后执行以下命令,对libc进行修改

objcopy -R .gnu_debuglink ./libc-2.23.so
objcopy --add-gnu-debuglink=libc-2.23.so.debug ./libc-2.23.so
mv .debug/libc-2.23.so .debug/libc-2.23.so.debug

再执行以下命令修改要调试的文件,使其加载修改后的libc

patchelf --set-interpreter `pwd`/ld-2.23.so 你的程序
patchelf --replace-needed libc.so.6 `pwd`/libc-2.23.so 你的程序

当需要加载libc信息的时候进行以下操作

1、Start/Attach debugged process

2、Pause debugged process

3、Modules->libc-2.23.so->Load debug info

4、Modules->libc-2.23.so->Analyze module

 

解决方法三

先用IDA打开对应的调试信息

选择File->Produce file->Dump database to IDC file...

打开导出的IDC脚本进行修改

1、写一个函数,将base设置为调用脚本时IDA的EA所选中的地址

static ask_libcbase(void)
{
  auto ea=get_screen_ea();
  base=ask_addr(ea,"input libc base");
}

2、将原来地址的0X7EFE替换为base-0X7EFE21CF9000+0X7EFE,这里的0X7EFE21CF9000是libc加载的基地址,要根据实际导出的IDC脚本进行修改

3、注释掉delete_*函数调用

4、注释掉create_*函数调用

5、注释掉make_*函数调用

当需要加载libc信息的时候进行以下操作

1、Start/Attach debugged process

2、Pause debugged process

3、Modules->libc-2.23.so->Jump to moudle base

4、File->Script File

5、Modules->libc-2.23.so->Analyze module

 

解决方法四

参考:https://stackoverflow.com/questions/15977961/how-to-undo-strip-i-e-add-symbols-back-to-stripped-binary

 

运行结果

用IDA来Start或者Attach你的程序

点击右侧的Modules->libc-2.23.so->Load debug symbols

 等待左下角显示AU:idle加载完成,此时仍有Name信息加载不全的问题

 再点击Modules->libc-2.23.so->Analyze module

然后耐心等待调试信息加载完成

最后的效果如下,_IO_FILE_plus_1等结构体都能被很好地识别,在右侧注释中有对应的成员信息,而且伪代码也能正常生成了

 

注意事项

apt里的patchelf是0.9版本的,有Bug

要自己到Github上编译0.10版本的才能正常使用

 

参考文献

1、https://blog.csdn.net/chinainvent/article/details/24129311?reload

2、https://www.douban.com/note/350501219/

3、https://stackoverflow.com/questions/34293646/how-to-add-debug-symbols-to-stripped-elf-binaries

4、https://stackoverflow.com/questions/15977961/how-to-undo-strip-i-e-add-symbols-back-to-stripped-binary

5、https://www.hex-rays.com/products/ida/support/idadoc/1457.shtml

posted @   Byaidu  阅读(4439)  评论(1编辑  收藏  举报
编辑推荐:
· 对象命名为何需要避免'-er'和'-or'后缀
· SQL Server如何跟踪自动统计信息更新?
· AI与.NET技术实操系列:使用Catalyst进行自然语言处理
· 分享一个我遇到过的“量子力学”级别的BUG。
· Linux系列:如何调试 malloc 的底层源码
阅读排行:
· C# 中比较实用的关键字,基础高频面试题!
· .NET 10 Preview 2 增强了 Blazor 和.NET MAUI
· Ollama系列05:Ollama API 使用指南
· 为什么AI教师难以实现
· 如何让低于1B参数的小型语言模型实现 100% 的准确率
点击右上角即可分享
微信分享提示