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
آرتش لينكس:
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},
}