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 @ 2020-04-19 02:48  Byaidu  阅读(3855)  评论(1编辑  收藏  举报