libdebug 是一個開源 Python 函式庫,用於自動偵錯二進位執行檔。
使用 libdebug,您可以完全控制調試的可執行檔的流程。有了它,您可以:
當多次執行相同的可執行檔時,選擇高效的實作會產生不同的結果。因此,libdebug 優先考慮效能。
首頁:https://libdebug.org
文件:https://docs.libdebug.org
烏班圖:
sudo apt install -y python3 python3-dev libdwarf-dev libelf-dev libiberty-dev linux-headers-generic libc6-dbg
德班:
sudo apt install -y python3 python3-dev libdwarf-dev libelf-dev libiberty-dev linux-headers-generic libc6-dbg
拱門Linux:
sudo pacman -S python libelf libdwarf gcc make debuginfod
軟呢帽:
sudo dnf install -y python3 python3-devel kernel-devel binutils-devel libdwarf-devel
python3 -m pip install libdebug
PyPy3 受支持,但不建議,因為它在我們的大多數測試中表現較差。
如果您想保持最新的最前沿功能(並且您不介意處於不穩定的分支上),您可以從不同的分支(例如,開發)進行安裝。
python3 -m pip install git+https://github.com/libdebug/libdebug.git@dev
現在您已經安裝了 libdebug,您可以開始在腳本中使用它了。以下是如何使用 libdebug 調試二進位檔案的簡單範例:
from libdebug import debugger
d = debugger ( "./test" )
# Start debugging from the entry point
d . run ()
my_breakpoint = d . breakpoint ( "function" )
# Continue the execution until the breakpoint is hit
d . cont ()
# Print RAX
print ( f"RAX is { hex ( d . regs . rax ) } " )
# Write to memory
d . memory [ 0x10ad , 8 , "binary" ] = b"Hello! x00 x00 "
# Continue the execution
d . cont ()
上面的腳本將在工作目錄中執行二進位test
,並停在與符號「function」對應的函數處。然後它將列印 RAX 暫存器的值並終止進程。
libdebug 可以做的事情還有很多。請閱讀文件以了解更多資訊。
libdebug 提供了許多進階功能。看看這個用訊號施展魔法的腳本:
from libdebug import debugger , libcontext
libcontext . terminal = [ 'tmux' , 'splitw' , '-h' ]
# Define signal catchers
def catcher_SIGUSR1 ( t : ThreadContext , catcher : SignalCatcher ) -> None :
t . signal = 0x0
print ( f"SIGUSR1: Signal number { catcher } " )
def catcher_SIGINT ( t : ThreadContext , catcher : SignalCatcher ) -> None :
print ( f"SIGINT: Signal number { catcher } " )
def catcher_SIGPIPE ( t : ThreadContext , catcher : SignalCatcher ) -> None :
print ( f"SIGPIPE: Signal number { catcher } " )
def handler_geteuid ( t : ThreadContext , handler : SyscallHandler ) -> None :
t . regs . rax = 0x0
# Initialize the debugger
d = debugger ( '/path/to/executable' , continue_to_binary_entrypoint = False , aslr = False )
# Register signal catchers
catcher1 = d . catch_signal ( "SIGUSR1" , callback = catcher_SIGUSR1 )
catcher2 = d . catch_signal ( "SIGINT" , callback = catcher_SIGINT )
catcher3 = d . catch_signal ( "SIGPIPE" , callback = catcher_SIGPIPE )
# Register signal hijackings
d . hijack_signal ( "SIGQUIT" , "SIGTERM" )
d . hijack_signal ( "SIGINT" , "SIGPIPE" , recursive = True )
# Define which signals to block
d . signals_to_block = [ "SIGPOLL" , "SIGIO" , "SIGALRM" ]
d . handle_syscall ( "geteuid" , on_exit = handler_geteuid )
# Continue execution
d . cont ()
# Disable the catchers after execution
catcher1 . disable ()
catcher2 . disable ()
catcher3 . disable ()
bp = d . breakpoint ( 0xdeadc0de , hardware = True )
d . cont ()
d . wait ()
d . gdb ()
libdebug 還允許您盡快執行所有命令,而不必等待停止事件。若要啟用此模式,您可以使用auto_interrupt_on_command=True
from libdebug import debugger
d = debugger ( "/path/to/executable" , auto_interrupt_on_command = True )
pipes = d . run ()
bp = d . breakpoint ( "function" )
d . cont ()
# Read shortly after the cont is issued
# The process is forcibly stopped to read the register
value = d . regs . rax
print ( f"RAX is { hex ( value ) } " )
system_offset = d . symbols . filter ( "system" )[ 0 ]. start
libc_base = d . maps . filter ( "libc" )[ 0 ]. base
system_address = libc_base + system_offset
d . memory [ 0x12ebe , 8 , "libc" ] = int . to_bytes ( system_address , 8 , "little" )
d . cont ()
d . wait ()
# Here we should be at the breakpoint
# This value is read while the process is stopped at the breakpoint
ip_value = d . regs . rip
print ( f"RIP is { hex ( ip_value ) } " )
d . kill ()
如果您打算在工作中使用 libdebug,請使用以下 biblatex 引用此儲存庫:
@software{libdebug_2024,
title = {libdebug: {Build} {Your} {Own} {Debugger}},
copyright = {MIT Licence},
url = {https://libdebug.org},
publisher = {libdebug.org},
author = {Digregorio, Gabriele and Bertolini, Roberto Alessandro and Panebianco, Francesco and Polino, Mario},
year = {2024},
doi = {10.5281/zenodo.13151549},
}