PYTHON-PTRACE(1) python-ptrace PYTHON-PTRACE(1)

python-ptrace - مستندات ابزار اشکال‌زدایی python-ptrace [تصویر: عدم نگهداری پروژه] [تصویر]
http://unmaintained.tech

این پروژه دیگر نگهداری نمی‌شود و به دنبال یک نگه‌دارنده جدید است.

python-ptrace یک اشکال‌زدای (debugger) نوشته‌شده به زبان پایتون است که از فراخوان سیستمی ptrace (در Linux، BSD و Darwin برای ردیابی فرآیندها) استفاده می‌کند.

python-ptrace یک پروژه متن‌باز نوشته‌شده به زبان پایتون تحت مجوز GNU GPLv2 است. این پروژه از پایتون ۳٫۶ و جدیدتر پشتیبانی می‌کند.

  • رابط کاربری شیءگرای سطح بالا در پایتون: PtraceDebugger و PtraceProcess
  • توانایی کنترل چندین فرآیند: دریافت رویدادهای fork در Linux
  • خواندن/نوشتن بایت‌ها در آدرس دلخواه: مدیریت هم‌ترازی حافظه و تقسیم بایت‌ها به طول کلمه پردازنده (cpu word)
  • اجرای گام‌به‌گام با استفاده از ()ptrace_singlestep یا وقفه سخت‌افزاری ۳
  • امکان استفاده از دیزاسمبلر distorm http://www.ragestorm.net/distorm
  • تخلیه (Dump) ثبات‌ها، نگاشت‌های حافظه، پشته و غیره
  • ردیاب و تجزیه‌کننده فراخوان‌های سیستمی <#syscall> (دستور strace.py)

وضعیت:

  • سیستم‌عامل‌های پشتیبانی‌شده: Linux، FreeBSD، OpenBSD
  • معماری‌های پشتیبانی‌شده: x86، x86_64 (در Linux)، PPC (در Linux)، ARM (در Linux EAPI)

ویژگی‌های ناموجود:

  • نمادها (Symbols): امکان توقف (break) روی یک تابع یا خواندن مقدار متغیر وجود ندارد
  • عدم پشتیبانی از زبان C: اشکال‌زدا کد اسمبلی را نمایش می‌دهد، نه کد C (یا ++C یا زبان‌های دیگر) شما را!
  • عدم پشتیبانی از ریسه‌ها (threads)

python-ptrace از پایتون ۳٫۶ و جدیدتر پشتیبانی می‌کند.

همچنین ببینید: python-ptrace در نمایه بسته‌های پایتون (PyPI) https://pypi.python.org/pypi/python-ptrace

آخرین آرشیو فشرده را از نمایه بسته‌های پایتون (PyPI) دریافت کنید: https://pypi.python.org/pypi/python-ptrace.

دانلود نسخه توسعه با استفاده از Git:

git clone https://github.com/vstinner/python-ptrace.git

مرور کد منبع python-ptrace https://github.com/vstinner/python-ptrace..SS وابستگی‌های اختیاری

•
دیزاسمبلر distorm (اختیاری) http://www.ragestorm.net/distorm

نکته: استفاده از pip اکیداً توصیه می‌شود.

به‌عنوان کاربر ریشه تایپ کنید:

python3 setup.py install

یا با استفاده از برنامه sudo:

sudo python3 setup.py install

برای اشکال‌زدایی سریع‌تر و پرهیز از ctypes، می‌توانید cptrace را نیز نصب کنید: رابط پایتونی تابع ()ptrace که به زبان C نوشته شده است:

python3 setup_cptrace.py install

برای اجرای تمام آزمون‌ها، کافی است تایپ کنید:

tox

پروژه tox https://testrun.org/tox/latest یک محیط مجازی تمیز برای اجرای آزمون‌ها ایجاد می‌کند.

تایپ کنید:

python3 runtests.py
python3 test_doc.py

همچنین امکان اجرای یک آزمون خاص وجود دارد:

PYTHONPATH=$PWD python3 tests/test_strace.py

مثالی کوتاه برای اتصال به یک فرایند در حال اجرا. این کد اشاره‌گر دستورالعمل را دریافت می‌کند، یک تک‌گام اجرا می‌کند، و اشاره‌گر دستورالعمل جدید را به دست می‌آورد:

import ptrace.debugger
import signal
import subprocess
import sys
def debugger_example(pid):
    debugger = ptrace.debugger.PtraceDebugger()
    print("Attach the running process %s" % pid)
    process = debugger.addProcess(pid, False)
    # process is a PtraceProcess instance
    print("IP before: %#x" % process.getInstrPointer())
    print("Execute a single step")
    process.singleStep()
    # singleStep() gives back control to the process. We have to wait
    # until the process is trapped again to retrieve the control on the
    # process.
    process.waitSignals(signal.SIGTRAP)
    print("IP after: %#x" % process.getInstrPointer())
    process.detach()
    debugger.quit()
def main():
    args = [sys.executable, '-c', 'import time; time.sleep(60)']
    child_popen = subprocess.Popen(args)
    debugger_example(child_popen.pid)
    child_popen.kill()
    child_popen.wait()
if __name__ == "__main__":
    main()

کلاس PtraceProcess ابزاری کمکی برای دستکاری یک فرآیندِ تحت ردگیری است.

مثال:

tracer = PtraceProcess(pid)              # attach the process
tracer.singleStep()                      # execute one instruction
tracer.cont()                            # continue execution
tracer.syscall()                         # break at next syscall
tracer.detach()                          # detach process
# Get status
tracer.getreg('al')                      # get AL register value
regs = tracer.getregs()                  # read all registers
bytes = tracer.readBytes(regs.ax, 10)    # read 10 bytes
tracer.dumpCode()                        # dump code (as assembler or hexa is the disassembler is missing)
tracer.dumpStack()                       # dump stack (memory words around ESP)
# Modify the process
shellcode = '...'
ip = tracer.getInstrPointer()            # get EIP/RIP register
bytes = tracer.writeBytes(ip, shellcode) # write some bytes
tracer.setreg('ebx', 0)                  # set EBX register value to zero

برای مشاهده متدهای بیشتر، کد منبع ptrace/debugger/process.py را مطالعه کنید.

ابزار python-ptrace می‌تواند فراخوانی‌های سیستم را با استفاده از PTRACE_SYSCALL ردگیری کند.

پیمانه ptrace.syscall شامل کلاس PtraceSyscall است: این کلاس یک تجزیه‌گر برای فراخوانی‌های سیستم لینوکس مشابه با برنامه strace است.

مثال:

connect(5, <sockaddr_in sin_family=AF_INET, sin_port=53, sin_addr=212.27.54.252>, 28) = 0
open('/usr/lib/i686/cmov/libcrypto.so.0.9.8', 0, 0 <read only>) = 4
mmap2(0xb7e87000, 81920, 3, 2066, 4, 297) = 0xb7e87000
rt_sigaction(SIGWINCH, 0xbfb7d4a8, 0xbfb7d41c, 8) = 0

می‌توانید اطلاعات بیشتری به دست آورید: نوع نتیجه، آدرس مقدار، نوع آرگومان‌ها و نام آرگومان‌ها.

مثال‌ها:

long open(const char* filename='/usr/lib/i686/cmov/libcrypto.so.0.9.8' at 0xb7efc027, int flags=0, int mode=0 <read only>) = 4
long fstat64(unsigned long fd=4, struct stat* buf=0xbfa46e2c) = 0
long set_robust_list(struct robust_list_head* head=0xb7be5710, size_t len_ptr=12) = 0

برنامه strace.py بسیار شبیه برنامه strace است: نمایش فراخوانی‌های سیستم یک برنامه. مثال:

  • خروجی مناسب سیگنال: به [[signal|python-ptrace signal handling]] مراجعه کنید
  • پشتیبانی از چندین فرآیند
  • امکان ردگیری فرآیندهای در حال اجرا
  • امکان نمایش نام، نوع و آدرس آرگومان‌ها
  • گزینه --filename برای نمایش تنها فراخوانی‌های سیستمی که از نام فایل‌ها استفاده می‌کنند
  • گزینه --socketcall برای نمایش تنها فراخوانی‌های سیستم مرتبط با شبکه (استفاده از سوکت)
  • گزینه --syscalls برای فهرست کردن تمام فراخوانی‌های سیستم شناخته‌شده

$ ./strace.py /bin/ls
execve(/bin/ls, [['/bin/ls'],|[/* 40 vars */]]) = 756
brk(0)                                   = 0x0805c000
access('/etc/ld.so.nohwcap', 0)          = -2 (No such file or directory)
mmap2(NULL, 8192, 3, 34, -1, 0)          = 0xb7f56000
access('/etc/ld.so.preload', 4)          = -2 (No such file or directory)
(...)
close(1)                                 = 0
munmap(0xb7c5c000, 4096)                 = 0
exit_group(0)
---done---

این برنامه گزینه‌های متعددی دارد. به عنوان مثال با --socketcall (نمایش تنها توابع شبکه):

$ ./strace.py --socketcall nc localhost 8080
execve(/bin/nc, [['/bin/nc',|'localhost', '8080']], [[/*|40 vars */]]) = 12948
socket(AF_FILE, SOCK_STREAM, 0)          = 3
connect(3, <sockaddr_un sun_family=AF_FILE, sun_path=/var/run/nscd/socket>, 110) = -2 (No such file or directory)
socket(AF_FILE, SOCK_STREAM, 0)          = 3
connect(3, <sockaddr_un sun_family=AF_FILE, sun_path=/var/run/nscd/socket>, 110) = -2 (No such file or directory)
socket(AF_INET, SOCK_STREAM, 6)          = 3
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, 3217455272L, 4) = 0
connect(3, <sockaddr_in sin_family=AF_INET, sin_port=8080, sin_addr=127.0.0.1>, 16) = -111 (Connection refused)
(...)

gdb.py یک دیباگر خط فرمان مشابه gdb است، اما با قابلیت‌های کمتر: بدون پشتیبانی از نمادها (symbols)، بدون پشتیبانی از زبان C، بدون پشتیبانی از thread و غیره.

  • cont: ادامه اجرای برنامه
  • stepi: اجرای یک instruction
  • step: اجرای یک instruction، اما بدون ورود به فراخوانی‌ها (calls)

برای مشاهده فهرست تمام دستورهای موجود، help را وارد کنید.

•
دستور print مقدار را به صورت ده‌دهی (decimal) و شانزده‌شانزدهی (hexadecimal)، و همچنین نگاشت حافظه مرتبط (در صورت وجود) نمایش می‌دهد:
(gdb) print $eip
Decimal: 3086383120
Hexadecimal: 0xb7f67810
Address is part of mapping: 0xb7f67000-0xb7f81000 => /lib/ld-2.6.1.so (r-xp)
  • خروجی مناسب از signal: به [[signal|python-ptrace signal handling]] مراجعه کنید
  • ردیاب syscall با دستور "sys": به python-ptrace system call tracer <syscall> مراجعه کنید. یک مثال کوتاه:
(gdb) sys
long access(char* filename='/etc/ld.so.nohwcap' at 0xb7f7f35b, int mode=F_OK) = -2 (No such file or directory)
•
پشتیبانی از چندین فرآیند (process):
(gdb) proclist
<PtraceProcess #24187> (active)
<PtraceProcess #24188>
(gdb) proc
Process ID: 24187 (parent: 24182)
Process state: T (traced)
Process command line: [['tests/fork_execve']
(...)
(gdb)|switch; proc
Switch to <PtraceProcess #24188>
Process ID: 24188 (parent: 24187)
Process state: T (traced)
Process command line: ['/bin/ls']]
(...)
•
امکان اجرای چندین دستور در یک خط با استفاده از جداکننده ";":
(gdb) print $eax; set $ax=0xdead; print $eax
Decimal: 0
Hexadecimal: 0x00000000
Set $ax to 57005
Decimal: 57005
Hexadecimal: 0x0000dead
  • تنها با کد پایتون خالص (pure Python) نوشته شده است، بنابراین گسترش آن ساده است
  • تجزیه‌گر عبارات (Expression parser) از تمام عملگرهای محاسباتی (a+b، a/b، a<<b، a&b، ...)، پرانتزها، استفاده از ثبات‌ها (registers) و غیره، و ارجاع‌زدایی اشاره‌گر (pointer dereference) (مانند: print *($ebx+0xc)) پشتیبانی می‌کند.

$ ./gdb.py ls
execve(/bin/ls, [['/bin/ls'],|[/* 40 vars */]]) = 16182
(gdb) where
ASM 0xb7f47810: MOV EAX, ESP <==
ASM 0xb7f47812: CALL 0xb7f47a60
ASM 0xb7f47817: MOV EDI, EAX
ASM 0xb7f47819: CALL 0xb7f47800
(gdb) regs
     EBX = 0xb7f4781e
     ECX = 0x0001d2f4
     EDX = 0xb7f61ff4
     ESI = 0x00000000
     (...)
(gdb) proc
Process ID: 16182
Process command line: [['/bin/ls']
Process|environment: ['TERM=xterm', 'SHELL=/bin/bash', (...)]]
Process working directory: /home/vstinner/prog/fusil/ptrace/trunk
(gdb) stack
STACK: 0xbfc58000..0xbfc6e000
STACK -8: 0x00000000
STACK -4: 0xb7f4781e
STACK +0: 0x00000001
STACK +4: 0xbfc6c6bb
STACK +8: 0x00000000
(gdb) maps
MAPS: 08048000-0805b000 r-xp 00000000 08:03 2588939    /bin/ls
MAPS: 0805b000-0805c000 rw-p 00012000 08:03 2588939    /bin/ls
(...)
MAPS: b7f61000-b7f63000 rw-p 00019000 08:03 1540553    /lib/ld-2.6.1.so
MAPS: bfc58000-bfc6e000 rw-p bfc58000 00:00 0          [[stack]
MAPS:|ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]]
(gdb) quit
Quit.
Terminate <PtraceProcess pid=16182>
Quit gdb.

تمامی رویدادهای فرآیند بر پایهٔ کلاس ProcessEvent هستند.

  • ProcessExit: فرآیند با یک کد خروج (exitcode) پایان یافته، توسط یک سیگنال کشته شده، یا به شکل غیرعادی خارج شده است
  • ProcessSignal: فرآیند یک سیگنال دریافت کرده است
  • NewProcessEvent: فرآیند جدیدی ایجاد شده است، برای نمونه پس از فراخوان سیستمی fork()

صفت‌ها:

  • تمامی رویدادها دارای صفت "process" هستند
  • رویداد ProcessExit دارای صفت‌های "exitcode" و "signum" است (هر دو می‌توانند None باشند)
  • رویداد ProcessSignal دارای صفت‌های "signum" و "name" است

برای NewProcessEvent، از صفت process.parent جهت دریافت فرآیند والد استفاده کنید.

نکته: ProcessSignal دارای متد display() برای نمایش محتوای خود است. درست پس از دریافت پیام از آن استفاده کنید، چرا که حافظه فرآیند را برای تحلیل دلایل ارسال سیگنال می‌خواند.

عمومی‌ترین تابع waitProcessEvent() است: این تابع منتظر هر رویدادی از فرآیند (خروج، سیگنال یا فرآیند جدید) می‌ماند:

event = debugger.waitProcessEvent()

برای انتظار جهت یک یا چند سیگنال، از متدهای waitSignals() استفاده کنید. بدون آرگومان، منتظر هر سیگنالی می‌ماند. رویدادهایی غیر از سیگنال به عنوان استثنای Python ایجاد می‌شوند. مثال‌ها:

signal = debugger.waitSignals()
signal = debugger.waitSignals(SIGTRAP)
signal = debugger.waitSignals(SIGINT, SIGTERM)

نکته: متغیر signal یک شیء ProcessSignal است؛ از signal.signum جهت دریافت شماره سیگنال استفاده کنید.

جهت انتظار برای هر رویدادی از یک فرآیند، از متد waitEvent() استفاده کنید:

event = process.waitEvent()

برای انتظار جهت یک یا چند سیگنال، از متد waitSignals() استفاده کنید. بدون آرگومان، منتظر هر سیگنالی می‌ماند. سایر رویدادهای فرآیند به عنوان استثنای Python ایجاد می‌شوند. مثال‌ها:

signal = process.waitSignals()
signal = process.waitSignals(SIGTRAP)
signal = process.waitSignals(SIGINT, SIGTERM)

نکته: همانند debugger.waitSignals()، متغیر signal یک شیء ProcessSignal است.

کلاس PtraceSignal هنگام دریافت یک سیگنال تلاش می‌کند اطلاعات مفیدی را نمایش دهد. بسته به شماره سیگنال، اطلاعات متفاوتی را نشان می‌دهد.

این کلاس از دستورالعمل جاری که به کد اسمبلی دیکد شده است برای درک دلیل ارسال سیگنال استفاده می‌کند.

در حال حاضر تنها Intel x86 (معماری i386 و احتمالاً x86_64) پشتیبانی می‌شود.

هنگامی که یک فرآیند سیگنالی دریافت می‌کند، python-ptrace تلاش می‌کند علت ارسال سیگنال را توضیح دهد.

اطلاعات عمومی (برای همه سیگنال‌ها نمایش داده نمی‌شود، برای نمونه برای SIGABRT نشان داده نمی‌شود):

  • دستورالعمل CPU که موجب فروپاشی (crash) شده است
  • ثبات‌های CPU مرتبط با فروپاشی
  • نگاشت‌های حافظه مربوط به آدرس‌های حافظه

دسته‌بندی سیگنال‌ها:

•
SIGFPE
•
تقسیم بر صفر
•
SIGSEGV، SIGBUS
  • خواندن نامعتبر حافظه
  • نوشتن نامعتبر حافظه
  • سرریز پشته
  • دسترسی نامعتبر به حافظه
•
SIGABRT
•
توقف نابهنگام برنامه (abort)
•
SIGCHLD
•
خروج فرآیند فرزند

Signal: SIGFPE
Division by zero
- instruction: IDIV DWORD [[EBP-0x8]
- register ebp=0xbfdc4a98

Signal: SIGSEGV
Invalid read from 0x00000008
- instruction: MOV EAX, [EAX+0x8]]
- mapping: 0x00000008 is not mapped in memory
- register eax=0x00000000
PID: 23766
Signal: SIGSEGV
Invalid write to 0x00000008 (size=4 bytes)
- instruction: MOV DWORD [[EAX+0x8],|0x2a
- mapping: 0x00000008..0x0000000b is not mapped in memory
- register eax=0x00000000

اطلاعات ارائه‌شده:

  • نشانی خطای دسترسی به حافظه (segmentation fault)
  • (در صورت امکان) اندازه خواندن/نوشتن نامعتبر در حافظه
  • دستور پردازنده (CPU) که موجب فروپاشی (crash) شده است
  • ثبات‌های پردازنده (CPU) مرتبط با فروپاشی
  • نگاشت‌های حافظه برای نشانی حافظه مرتبط

Signal: SIGSEGV
STACK OVERFLOW! Stack pointer is in 0xbf534000-0xbfd34000 => [stack]] (rw-p)
- instruction: MOV BYTE [[EBP-0x1004],|0x0
- mapping: 0xbf533430 is not mapped in memory
- register <stack ptr>=0xbf533430
- register ebp=0xbf534448

PID: 24008
Signal: SIGCHLD
Child process 24009 exited normally
Signal sent by user 1000

اطلاعات:

  • شناسه فرآیند فرزند
  • شناسه کاربر فرآیند فرزند

خواندن نامعتبر:

Signal: SIGSEGV
Invalid read from 0x00000008
- instruction: MOV EAX, [EAX+0x8]
- mapping: (no memory mapping)
- register eax=0x00000000

نوشتن نامعتبر (MOV):

Signal: SIGSEGV
Invalid write to 0x00000008 (size=4 bytes)
- instruction: MOV DWORD [EAX+0x8], 0x2a
- mapping: (no memory mapping)
- register eax=0x00000000

abort():

Signal: SIGABRT
Program received signal SIGABRT, Aborted.

ببینید:

  • ptrace/debugger/ptrace_signal.py
  • ptrace/debugger/signal_reason.py

انقیاد پایتون (Python binding) برای ptrace نوشته‌شده به زبان C.

مثال نمونه:

>>> import cptrace
>>> cptrace.ptrace(1, 1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: ptrace(request=1, pid=1, 0x(nil), 0x(nil)) error #1: Operation not permitted

  • Anthony Gelibert <anthony.gelibert AT me.com> - رفع اشکال cptrace در Apple
  • Dimitris Glynos <dimitris AT census-labs.com> - پیروی از دستورهای gdb.py
  • Jakub Wilk <jwilk AT debian.org> - اصلاح برای GNU/kFreeBSD
  • Mark Seaborn <mrs AT mythic-beasts.com> - ایجاد گزینه -i برای strace
  • Mickaël Guérin aka KAeL <mickael.guerin AT crocobox.org> - پورت به OpenBSD
  • teythoon - تبدیل تمام کلاس‌ها به کلاس‌های نوع جدید (new-style classes)
Bursztyka aka Tuna <tuna AT lyua.org> - پورت به x86_64
•
Victor Stinner <victor.stinner AT gmail.com> - نویسنده و نگه‌دارنده python-ptrace

•
نویسندگان procps (برنامه‌های top و uptime)

  • اصلاح آرگومان‌های فراخوان‌های سیستمی pipe/pipe2 جهت نمایش مناسب در قالب فراخوانی. وصله توسط José Pereira.
  • افزودن پشتیبانی از شناسه‌های فرعی دستگاه (minor device ID) سه‌رقمی در PROC_MAP_REGEX. وصله توسط fab1ano.
  • افزودن پشتیبانی از RISCV (riscv32/riscv64). وصله توسط Andreas Schwab و vimer/yuzibo.
  • رفع استثنای سرگردان ایجادشده توسط فرایندهای فرزندی که با کد خروج ۲۵۵ خاتمه می‌یابند. وصله توسط Duane Voth/duanev.
  • حذف استفاده از ماژول imp. همکاری بین Mario Haustein/hamarituc و Stephen Kitt/skitt.

  • افزودن پشتیبانی از Arm 64bit (AArch64).
  • پیاده‌سازی PTRACE_GETREGSET و PTRACE_SETREGSET که در AArch64 مورد نیاز و در لینوکس در دسترس هستند.
  • مورد #66: رفع انتظار SIGTRAP|0x80 یا SIGTRAP در syscall_state.exit (PTRACE_O_TRACESYSGOOD).
  • شاخه توسعه master به main تغییر نام یافت. برای دیدن دلایل، https://sfconservancy.org/news/2020/jun/23/gitbranchname را ببینید.

  • افزودن ماژول جاافتاده به دستورالعمل‌های نصب
  • به‌روزرسانی README.rst
  • بازگشت پروژه به وضعیت آزمایشی (beta) و نگه‌داری

  • حذف ثابت RUNNING_WINDOWS: نرم‌افزار python-ptrace از Windows پشتیبانی نمی‌کند.
  • پایان پشتیبانی از Python 2.7. وابستگی six دیگر مورد نیاز نیست.
  • افزودن close_fds و pass_fds به تابع createChild(). وصله توسط Jean-Baptiste Skutnik.
  • بهبود خروجی strace.py برای پرچم‌های open و پارامترهای اختیاری open. وصله توسط Jean-Baptiste Skutnik.
  • افزودن پشتیبانی از PowerPC 64-bit (ppc64). وصله توسط Jean-Baptiste Skutnik.

  • اصلاح readProcessMappings() برای شناسه دستگاه ۳ رقمی. وصله توسط Cat Stevens.
  • پایان پشتیبانی از Python 2.
  • Issue #36: رفع مشکل جدا شدن (detaching) از شیء فرآیندی که بدون is_attached=True ایجاد شده است
  • پروژه اکنون به ماژول six نیاز دارد.
  • پروژه منتقل شد به: https://github.com/vstinner/python-ptrace

•
Issue #42: رفع مشکل test_strace.py: سازگاری با فراخوان سیستمی openat().

•
Issue #35: رفع مشکل strace.py هنگام ردگیری چندین فرآیند: استفاده از فرآیند صحیح. اصلاحات پیشنهادشده توسط Daniel Trnka.

  • افزودن ردگیری فرآیندهای ایجادشده با فراخوان سیستمی clone (که معمولاً به عنوان نخ‌ها یا threads شناخته می‌شوند).
  • gdb.py: افزودن دستور gcore، رونوشت‌برداری (تخلیه) از حافظهٔ فرآیند.
  • امکان استفاده از نام دستورات بدون مسیر مطلق.
  • اصلاح بایندینگ ptrace: پاک‌سازی errno پیش از فراخوانی ptrace().
  • اصلاح PtraceSyscall.exit() برای کدهای خطای ناشناخته
  • پروژه به GitHub منتقل شد: https://github.com/haypo/python-ptrace
  • حذف ماژول ptrace.ctypes_errno: استفادهٔ مستقیم از تابع ctypes.get_errno()
  • حذف ماژول ptrace.ctypes_errno: استفادهٔ مستقیم از نوع‌های ctypes.c_int8، ctypes.c_uint32 و ...

  • افزودن پروتوتایپ تمام فراخوان‌های سیستمی لینوکس
  • افزودن نمادهای خطا (مانند ENOENT) افزون بر متن خطا، برای strace
  • اصلاح حالت open به طوری که O_RDONLY در صورتی که تنها حالت دسترسی به فایل باشد، نمایش داده شود
  • Python 3: اصلاح قالب‌بندی آرگومان‌های رشته‌ای فراخوان سیستمی (مانند نام فایل‌ها)، رمزگشایی بایت‌ها با استفاده از کدگذاری محلی (locale)
  • Issue #17: تجزیه‌کنندهٔ فراخوان‌های سیستمی اکنون از O_CLOEXEC و SOCK_CLOEXEC پشتیبانی می‌کند، اصلاح آزمون‌های واحد روی Python 3.4 و نسخه‌های جدیدتر

  • به‌روزرسانی MANIFEST.in جهت گنجاندن تمام فایل‌ها
  • اصلاحات جهت پشتیبانی از Python 3.5

  • Issue #9: بازنویسی متدهای waitProcessEvent() و waitSignals() در PtraceProcess برای فراخوانی نکردن waitpid() با مقدار pid=-1. یک شرایط رقابتی (race condition) با waitpid(-1) و fork وجود دارد؛ وضعیت فرآیند فرزند ممکن است پیش از آن‌که دیباگر از ایجاد فرآیند فرزند جدید مطلع شود، بازگردانده شود.
  • Issue #10: اصلاح PtraceProcess.readBytes() برای فرآیندهایی که توسط دیباگر ایجاد نشده‌اند (مانند fork) در صورتی که هسته دسترسی به نگاشت‌های خصوصی /proc/pid/mem را مسدود کند. استفادهٔ جایگزین از PTRACE_PEEKTEXT که کندتر است اما دیباگری که فرآیند را ردگیری می‌کند همواره مجاز به استفاده از آن است.

  • پشتیبانی آزمایشی از Python 3.3 در همان پایه کد
  • حذف پشتیبانی از Python 2.5
  • حذف ماژول ptrace.compatibility
  • اصلاح Process.readStruct() و Process.readArray() روی x86_64
  • پشتیبانی آزمایشی از معماری ARM (رابط Linux EAPI)، برنامهٔ strace.py روی Raspberry Pi (armv6l) آزمایش شده است

  • اصلاح os_tools.RUNNING_LINUX برای Python 2.x کامپایل‌شده روی هستهٔ لینوکس 3.x
  • پشتیبانی از FreeBSD روی x86_64
  • افزودن پروتوتایپ ناموجود فراخوان سیستمی unlinkat(). وصله توسط Matthew Fernandez نوشته شده است.

  • syscall: اصلاح تجزیهٔ socketcall در Linux x86
  • syscall: اصلاح پروتوتایپ socket()

  • تبدیل تمام کلاس‌ها به کلاس‌های new-style، وصله توسط teythoon نوشته شده است
  • اصلاح کامپایل روی Apple، وصله توسط Anthony Gelibert نوشته شده است
  • پشتیبانی از GNU/kFreeBSD، وصله توسط Jakub Wilk نوشته شده است
  • پشتیبانی از sockaddr_in6 (نشانی IPv6)

  • پشتیبانی از distrom3
  • پشتیبانی از Python 3
  • تغییر نام گزینهٔ --socketcall در strace.py به --socket، و اصلاح این گزینه برای FreeBSD و Linux/64 bits
  • افزودن MANIFEST.in: شامل کردن تمام فایل‌ها در بستهٔ توزیع سورس (تست‌ها، ماژول cptrace و ...)
•
رفع اشکال زیرثبات‌های ۶۴ بیتی (تنظیم ماسک برای eax، ebx، ecx و edx)

  • ایجاد دستورهای follow، showfollow، resetfollow و xray در gdb.py. وصله توسط Dimitris Glynos نوشته شده است
  • وب‌گاه پروژه منتقل شد به: http://bitbucket.org/haypo/python-ptrace
  • جایگزینی انواع داده (u)intXX_t با c_(u)intXX
  • ایجاد متد MemoryMapping.search() و اکنون MemoryMapping یک ارجاع ضعیف به فرایند نگه می‌دارد

تغییرات قابل مشاهده برای کاربر:

  • اکنون python-ptrace به Python 2.5 وابسته است
  • دسترسی نامعتبر به حافظه: افزودن آدرس خطا در نام
  • به‌روزرسانی وصله تبدیل Python 3.0
  • ایجاد گزینه -i (--show-ip) در strace.py: نمایش اشاره‌گر دستورالعمل
  • افزودن یک مثال جدید (itrace.py) نوشته‌شده توسط Mark Seaborn و مبتنی بر strace.py

تغییرات API:

  • در PtraceSyscall: ذخیره اشاره‌گر دستورالعمل هنگام ورود به فراخوان سیستمی (اگر گزینه instr_pointer=True باشد، به‌طور پیش‌فرض غیرفعال است)
  • حذف PROC_DIRNAME و procFilename() از ptrace.linux_proc

رفع باگ‌ها:

  • رفع اشکال locateProgram() برای مسیر نسبی
  • رفع اشکال تفسیر خطای حافظه در دستورالعمل MOSVW (مبدأ ESI و مقصد EDI است، نه برعکس!)

تغییرات قابل مشاهده:

  • نوشتن یک مثال (ساده‌ترین دیباگر) و آغاز مستندسازی کد
  • در gdb.py: ایجاد دستور "dbginfo"
  • تجزیه فراخوان‌های سیستمی socket در FreeBSD
  • در دسترسی نامعتبر به حافظه (SIGSEGV)، ارزیابی عبارت dereference برای دریافت آدرس خطا در سیستم‌عامل‌های فاقد siginfo (مانند FreeBSD)
  • اصلاحات برای پشتیبانی حداقلی از Windows: رفع اشکال ایمپورت‌ها، رفع اشکال locateProgram()

سایر تغییرات:

  • شکستن سازگاری API: - تغییر نام PtraceDebugger.traceSysgood() به PtraceDebugger.enableSysgood() - تغییر نام PtraceDebugger.trace_sysgood به PtraceDebugger.use_sysgood - حذف PtraceProcess.readCode()
  • ایجاد تابع createChild() که تمام فایل‌ها به جز stdin، stdout و stderr را می‌بندد
  • در FreeBSD، فراخوانی مجدد waitpid(pid) هنگام خروج فرایند برای جلوگیری از ایجاد فرایند زامبی

  • رفع باگ: رفع غلط املایی در gdb.py (تغییر commands => command_str)، امکان نوشتن بیش از یک دستور وجود نداشت...
  • رفع باگ: رفع غلط املایی در کلاس SignalInfo (حذف "self."). هنگامی که فرایندی یک سیگنال SIGCHLD دریافت می‌کرد (به دلیل fork)، دیباگر به علت این باگ خارج می‌شد.
  • رفع باگ: متد Debugger._wait() خروج غیرعادی فرایند را به عنوان یک رخداد عادی برمی‌گرداند؛ این رخداد به عنوان استثنا بالا کشیده نمی‌شود
  • در PtraceSignal: آرگومان‌های از پیش قالب‌بندی‌شده (مانند آرگومان‌های execve) پاک نشوند

  • پروژه یک وب‌گاه اختصاصی جدید دارد: http://python-ptrace.hachoir.org
  • ایجاد cptrace: بایندینگ پایتون اختیاری برای ptrace که با C نوشته شده است (سریع‌تر از ptrace، بایندینگ پایتون که با ctypes در پایتون نوشته شده بود)
  • افزودن صفت name به کلاس‌های SignalInfo
  • اصلاحاتی برای کمک به سازگاری با Python 3.0: عدم استفاده از sys.exc_clear() (که بی‌فایده بود) در writeBacktrace()
  • در ProcessState: ایجاد صفت‌های utime، stime و starttime

تغییرات قابل مشاهده:

  • تغییر نام پروژه به "python-ptrace" (نام پیشین "Ptrace بود)
  • در strace.py: ایجاد گزینه --ignore-regex
  • در PtraceSignal: پشتیبانی از SIGBUS، نمایش ثبات‌های مربوطه و دستورالعمل
  • پشتیبانی از ردگیری فراخوان سیستمی execve()

تغییرات توسعه‌دهندگان:

  • رابط API جدید با نسخه 0.3.2 ناسازگار است
  • متد PtraceProcess.waitProcessEvent() آرگومان اختیاری blocking=False را می‌پذیرد
  • متدهای PtraceProcess.getreg()/setreg() قادر به خواندن/نوشتن "زیرثبات‌های" i386 و x86-64 مانند al یا bx هستند
  • حذف تابع iterProc() و جایگزینی با openProc() به همراه فراخوانی صریح .close() برای اطمینان از بسته شدن فایل‌ها
  • ایجاد searchProcessesByName()
  • جایگزینی مقدار ثابت CPU_PPC با CPU_POWERPC و ایجاد CPU_PPC32 و CPU_PPC64
  • ایجاد شیء MemoryMapping، مورد استفاده توسط متدهای readMappings() و findStack() در PtraceProcess
  • تعریف همیشگی تمام متدهای PtraceProcess، اما بالا کشیدن خطا در صورت عدم پیاده‌سازی تابع

  • رفع اشکال strace.py --socketcall: تابع SyscallState.enter() پیش از پردازش socketcall، تابع ignore_callback را فراخوانی می‌کند
  • پشتیبانی از backendهای دیگر:
•
نمادهای بازگردانی رد پشته (Backtrace symbols):
  • کتابخانه GNU BFD؟
  • elfsh؟
  • برنامه addr2line؟
  • بررسی تابع dl_iterate_phdr() از libdl
•
پشتیبانی از دیس‌اسمبلرهای دیگر (به‌جز distorm)، و در نتیجه هر دو نحو Intel (اینتل و AT&T)
•
پشتیبانی از ریسه‌ها (threads): سایر backendها (به‌جز python-ptrace) از پیش از ریسه‌ها پشتیبانی می‌کنند

•
رفع اشکال دستور "step" در gdb.py روی پرش‌ها (jump). نمونه‌ای که در آن دستور step هرگز متوقف نخواهد شد:
(gdb) where
ASM 0xb7e3b917: JMP 0xb7e3b8c4 (eb ab)
ASM 0xb7e3b919: LEA ESI, [ESI+0x0] (8db426 00000000)
  • حذف وصله موقت (hack) عبارت "except PtraceError, err: if err.errno == ESRCH" در gdb.py؛ تشخیص خاتمه فرایند باید توسط PtraceProcess یا PtraceDebugger انجام شود
  • استفاده از نقطه‌توقف‌های سخت‌افزاری اینتل (Intel hardware breakpoints): بررسی کد منبع vtrace
  • پشتیبانی از Darwin:

•
فازر Fusil http://fusil.readthedocs.io

•
محیط ایزوله (Sandboxing): Plash http://plash.beasts.org

  • نرم‌افزار vtrace http://kenshoto.com/vtrace: کتابخانه پایتون (Windows و Linux) با پشتیبانی از ریسه‌ها (threads)
  • نرم‌افزار subterfuge http://subterfugue.org نوشته Mike Coleman: کتابخانه پایتون (Linux): شامل بایندینگ پایتون برای ptrace نوشته‌شده با زبان C برای Python 2.1/2.2. با Python 2.5 کار نمی‌کند (پروژه قدیمی است و از سال ۲۰۰۲ نگهداری نشده است)
  • برنامه strace http://sourceforge.net/projects/strace (لینوکس، BSD)
  • برنامه ltrace (لینوکس)
  • برنامه truss (سولاریس و BSD)
  • نرم‌افزار pytstop http://www.secdev.org/projects/pytstop نوشته Philippe Biondi: دیباگری مشابه gdb اما در مرحله بسیار اولیه (برای نمونه، فاقد دیس‌اسمبلر)، با استفاده از بایندینگ پایتون ptrace نوشته‌شده با C (برگرفته از subterfuge)
  • اسکریپت strace.py http://www.secdev.org/articles/reverse/strace.py نوشته Philippe Biondi
  • مجموعه Fenris http://lcamtuf.coredump.cx/fenris: مجموعه‌ای از ابزارهای مناسب برای تحلیل کد، دیباگ، تحلیل پروتکل، مهندسی معکوس، جرم‌یابی دیجیتال، عیب‌یابی، ممیزی امنیتی و پژوهش در زمینه آسیب‌پذیری
  • ابزار PyDBG http://pedram.redhive.com/PaiMei/docs: دیباگر ویندوز نوشته‌شده با پایتون خالص

Victor Stinner

2014, Victor Stinner

December 14, 2025 0.9.9