gdb使用教程
gdb是在CTF做題中非常重要的動態分析二進制的工具,這里我們列出兩個常用的gdb插件并給出安裝方法。同時介紹一些常用的gdb命令,一開始可能記不住,關鍵還是要多加練習,多做題多分析才能熟練運用。
gdb-peda安裝
git clone https://github.com/longld/peda.git ~/peda
echo "source ~/peda/peda.py" >> ~/.gdbinit
echo "DONE! debug your program with gdb and enjoy"
這里提供了一下命令支持debugg和exp開發
aslr– 查看GDB的ASLR設置checksec– 查看各種安全配置dumpargs– 顯示函數的傳參,當在call指令處斷下時dumprop– Dump所有ROP gadgets在特定的內存范圍elfheader– 獲取header的信息elfsymbol– 獲取non-debugging的符號信息lookup– 在指定地址范圍內查找地址引用patch– 在內存開始處 ( with string/hexstring/int ) Patchpattern– 內存循環模式的操作procinfo– 在/proc/pid/顯示各種信息pshow– 顯示各種PEDA操作和其他的設置pset– 設置各種PEDA的操作和其他配置readelf– 獲取elf文件header信息ropgadget– 獲取ROP gadgets(二進制或者庫)ropsearch– 在內存中查找ROP gadgetssearchmem|find– 尋找內存的pattern,支持regex查找shellcode– 生成或者下載常見的shellcodesskeleton– 生成python利用漏洞模板vmmap– 獲得section的虛擬映射地址范圍xormem– XOR a memory region with a key 通過key XOR 一個內存域
pwndbg
除了peda還有一些別的插件供我們選用,如pwndbg增加了一些查看堆的命令,這在做題目的時候非常方便查看內存。
直接按照命令下載即可,這個過程中可能需要用到梯子。
git clone https://github.com/pwndbg/pwndbg
cd pwndbg
./setup.sh
在~/.gdbinit中可以選擇使用的插件,我們將不用的插件注釋掉即可。
gdb 的組成架構和基本工作原理

gdb 通過系統調用 ptrace 來接管一個進程的執行。ptrace 系統調用提供了一種方法使得父進程可以觀察和控制其它進程的執行,檢查和改變其核心映像以及寄存器。它主要用來實現斷點調試和系統調用跟蹤。
具體特性可以在他們的官方文檔中查看。
gdb 的三種調試方式
- 運行并調試一個新進程
- 運行 gdb,通過命令行或
file命令指定目標程序。 - 輸入
run命令, gdb 執行下面的操作:- 通過
fork()系統調用創建一個新進程 - 在新創建的子進程中執行操作:
ptrace(PTRACE_TRACEME, 0, 0, 0) - 在子進程中通過
execv()系統調用加載用戶指定的可執行文件
- 通過
- 運行 gdb,通過命令行或
- attach 并調試一個已經運行的進程
- 用戶確定需要進行調試的進程 PID
- 運行 gdb,輸入
attach <pid>,gdb 將對指定進程執行操作:ptrace(PTRACE_ATTACH, pid, 0, 0)
- 遠程調試目標機上新創建的進程
- gdb 運行在調試機上,gdbserver 運行在目標機上,兩者之間的通信數據格式由 gdb 遠程串行協議(Remote Serial Protocol)定義
- RSP 協議數據的基本格式為:
$..........#xx - gdbserver 的啟動方式相當于運行并調試一個新創建的進程
斷點的實現
斷點的功能是通過內核信號實現的,在 x86 架構上,內核向某個地址打入斷點,實際上就是往該地址寫入斷點指令 INT 3,即 0xCC。目標程序運行到這條指令之后會觸發 SIGTRAP 信號,gdb 捕獲這個信號,并根據目標程序當前停止的位置查詢 gdb 維護的斷點鏈表,若發現在該地址確實存在斷點,則可判定為斷點命中。
常用命令
break – b
break <address>指定地址下斷點(最常用),如
break在所選棧幀中執行的下一條指令處設置斷點。break <function>函數入口處設置斷電break <line>源文件指定行下斷點break -Nbreak +N在源代碼文件當前行的偏移N下斷點。break <filename:line>在源碼文件filename的line行處打斷點。break <filename:function>在源碼文件filename的function函數入口處打斷點。break ... if <cond>設置條件斷點,...代表上述參數之一(或無參數),cond為條件表達式,僅在cond值非零時停住程序。x
檢查內存,常用。x/nfu <addr>x <addr>n,f, 和u都是可選參數,用于指定要顯示的內存以及如何格式化。addr是要開始顯示內存的地址的表達式。n重復次數(默認值是 1),指定要顯示多少個單位(由u指定)的內存值。f顯示格式(初始默認值是x),顯示格式是print('x','d','u','o','t','a','c','f','s')使用的格式之一,再加i(機器指令)。u單位大小,b表示單字節,h表示雙字節,w表示四字節,g表示八字節。
info
我們在安裝的gdb插件中可以看到這些信息,大家可以當作一個手冊來查閱。
info breakpoints -- i b查看斷點,觀察點和捕獲點的列表。info breakpoints [list…]info break [list…]list…用來指定若干個斷點的編號(可省略),可以是2,1-3,2 5等。
info display打印自動顯示的表達式列表,每個表達式都帶有項目編號,但不顯示其值。info reg顯示當前寄存器信息。info threads打印出所有線程的信息,包含 Thread ID、Target ID 和 Frame。info frame打印出指定棧幀的詳細信息。info proc查看 proc 里的進程信息。
disassemble – disas
反匯編命令。
disas <func>反匯編指定函數disas <addr>反匯編某地址所在函數disas <begin_addr> <end_addr>反匯編從開始地址到結束地址的部分
delete – d
刪除斷點。參數使用空格分隔。不帶參數時刪除所有斷點。
clear
在指定行或函數處清除斷點。參數可以是行號,函數名稱或 * 跟一個地址。
disable – dis
禁用斷點,參數使用空格分隔。不帶參數時禁用所有斷點。
finish – fin
執行直到選定的棧幀返回。
watch
為表達式設置觀察點。每當一個表達式的值改變時,觀察點就會停止執行您的程序。
backtrace – bt
打印整個棧的回溯。
bt打印整個棧的回溯,每個棧幀一行。bt n類似于上,但只打印最內層的 n 個棧幀。bt -n類似于上,但只打印最外層的 n 個棧幀。bt full n類似于bt n,還打印局部變量的值。注意:使用 gdb 調試時,會自動關閉 ASLR,所以可能每次看到的棧地址都不變。
step – s
單步執行程序,直到到達不同的源碼行。step [N] 參數 N 表示執行 N 次(或由于另一個原因直到程序停止)。
next – n
單步執行程序,執行完子程序調用。next [N]
與 step 不同,如果當前的源代碼行調用子程序,則此命令不會進入子程序,而是繼續執行,將其視為單個源代碼行。
return
您可以使用 return 命令取消函數調用的執行。如果你給出一個表達式參數,它的值被用作函數的返回值。
return <expression>將expression的值作為函數的返回值并使函數直接返回。
print – p
求表達式 expr 的值并打印。可訪問的變量是所選棧幀的詞法環境,以及范圍為全局或整個文件的所有變量。
print [expr]print /f [expr]通過指定/f來選擇不同的打印格式,其中f是一個指定格式的字母
cannot find a shell for gdb.attach
https://github.com/Gallopsled/pwntools/issues/1010
參考