警告
本文最后更新于 2022-09-14,文中内容可能已过时。
在 archlinux 中 pwndbg 无法正常使用 pwngdb 的 heap 系列命令, 因为缺少 glibc 的调试符号. 但问题是在 arch 的构建系统中默认会 strip 掉二进制文件的调试符号, 以减小程序体积题高性能等. 为了获得更好的调试体验, 就来研究一下如何优雅地解决这个问题.
为什么 5 年过去了这个 issue 还没有被很好地解决
尝试自己编译一份带调试符号的 glibc 试试:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| #!/bin/sh
# Install Dependencies
sudo pacman -S git svn gd lib32-gcc-libs patch make bison fakeroot devtools
# Checkout glibc source
svn checkout --depth=empty svn://svn.archlinux.org/packages
cd packages
svn update glibc
cd glibc/repos/core-x86_64
# Add current locale to locale.gen.txt
grep -v "#" /etc/locale.gen >> locale.gen.txt
# Enable debug build in PKGBUILD
sed -i 's#!strip#debug#' PKGBUILD
# Build glibc and glibc-debug packages
makepkg --skipchecksums --config /usr/share/devtools/makepkg-x86_64.conf
# Install glibc-debug
sudo pacman -U *.pkg.tar.zst
|
这边注意可能的几个问题:
pacman -U 安装的时候可能会报错文件已存在,全部删掉即可
一定要把 glibc 也一并安装上,就算版本和你本地的一致,不能只装 glibc-debug, 这样会导致 CRC mismatch 的问题
所有步骤完成后要把 /etc/makepkg.conf
中所有 OPTIONS 中的 strip -> !strip
以及 !debug -> debug
如果机器上有 pwndbg 需要重新 sudo pacman -S pwndbg
安装一份挤掉老版,记得要添加 source /usr/share/pwndbg/gdbinit.py
到 ~/.gdbinit
可以愉快地断在 glibc 的源码中了:
当然缺点很明显, 每次更新 glibc 都需要自己重新 build, 后续尝试写个自动化来一键完成.
当然了, gef 还是可以在没有 debug symbols 的情况下很好地查看 heap chunks, 这里给出一个切换 gdb 插件的 zsh 脚本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
| # gdbs : gdb-switcher
gdbs() {
echo -e "\n[*] Which debugger ?"
echo -e "\n1 : Legacy GDB"
echo "2 : peda"
echo "3 : gef"
echo "4 : pwndbg"
echo "5 : dashboard"
echo "6 : radare2"
radare="no"
read choice
case $choice in
1) echo "[+] gdb-switch => gdb"
cp ~/.gdbinit-gdb ~/.gdbinit
;;
2) echo "[+] gdb-switch => peda"
cp ~/.gdbinit-peda ~/.gdbinit
;;
3) echo "[+] gdb-switch => gef"
cp ~/.gdbinit-gef ~/.gdbinit
;;
4) echo "[+] gdb-switch => pwndbg"
cp ~/.gdbinit-pwndbg ~/.gdbinit
;;
5) echo "[+] gdb-switch => dashboard"
cp ~/.gdbinit-dashboard ~/.gdbinit
;;
6) echo "[+] gdb-switch => radare2"
radare="run"
;;
esac
if [ "$#" -eq 1 ]; then
if [ "$radare" = "run" ]; then
echo "[+] debugger execution : radare2"
r2 $1
else
echo "[+] debugger execution"
gdb -q $1
fi
fi
}
|
如果你用 omz 的话, 放在 ~/.oh-my-zsh/funcs/
下,并且在 ~/.zshrc
中添加:
1
2
| fpath=($ZSH/funcs, "${fpath[@]}")
autoload +X gdbs
|
否则更改一下自定义函数存放的路径.
即可在启动 shell 时自动加载该函数, 并且可以通过 which 指令看到函数内部实现.