問題分析
在動態調試程序的時候,用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
解決方法四
運行結果
用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
5、https://www.hex-rays.com/products/ida/support/idadoc/1457.shtml