PYTHON-PTRACE(1)
π¦ PYTHON-PTRACE(1) β the python-ptrace manual, bestie edition π¦
π NAME π
python-ptrace β python-ptrace Documentation [image: No Maintenance Intended] [image] <http://unmaintained.tech/>
Okay so first thing: this project is no longer maintained and is looking for a new maintainer. Not me casually dropping the emotional lore first π
python-ptrace is a debugger using ptrace (Linux, BSD and Darwin system call to trace processes) written in Python. π
python-ptracedocumentation β<http://python-ptrace.readthedocs.io/>python-ptraceat GitHub β<https://github.com/vstinner/python-ptrace>python-ptraceat the Python Cheeseshop (PyPI) β<https://pypi.python.org/pypi/python-ptrace>
python-ptrace is an opensource project written in Python under GNU GPLv2 license. It supports Python 3.6 and newer. π«Ά
β¨ FEATURES β¨
- High level Python object API :
PtraceDebuggerandPtraceProcess - Able to control multiple processes: catch fork events on Linux
- Read/write bytes to arbitrary address: take care of memory alignment and split bytes to cpu word
- Execution step by step using
ptrace_singlestep()or hardware interruption 3 - Can use
distorm<http://www.ragestorm.net/distorm/>disassembler - Dump registers, memory mappings, stack, etc.
- Syscall tracer and parser
<#syscall>(strace.pycommand)
Status: π
- Supported operating systems: Linux, FreeBSD, OpenBSD
- Supported architectures: x86, x86_64 (Linux), PPC (Linux), ARM (Linux EAPI)
Missing features: π
- Symbols: it's not possible to break on a function or read a variable value
- No C language support: debugger shows assembler code, not your C (C++ or other language) code!
- No thread support
πΈ TABLE OF CONTENTS πΈ
Bestie, hereβs the whole map, and then we immediately start walking through it. No cap. πΊοΈ
π§ Install python-ptrace π§
python-ptrace supports Python 3.6 and newer.
π¦ Linux packages π¦
- Debian:
python-ptraceDebian package β<http://packages.qa.debian.org/p/python-ptrace.html>. - Mandriva:
python-ptraceMandriva package β<http://sophie.zarb.org/rpmfind?search=python-ptrace&st=rpmname> - OpenEmbedded:
python-ptracerecipe β<http://git.openembedded.net/?p=org.openembedded.dev.git;a=tree;f=packages/python> - Arch Linux:
python-ptraceArch Linux package β<http://aur.archlinux.org/packages.php?ID=19609> - Gentoo:
dev-python/python-ptraceβ<http://packages.gentoo.org/package/dev-python/python-ptrace>
See also python-ptrace on Python Package Index (PyPI) β <https://pypi.python.org/pypi/python-ptrace>
π οΈ Install from source π οΈ
π Download tarball π
Get the latest tarball at the Python Package Index (PyPI) β <https://pypi.python.org/pypi/python-ptrace>.
πΏ Download development version πΏ
Download the development version using Git:
git clone https://github.com/vstinner/python-ptrace.git
Browse python-ptrace source code β <https://github.com/vstinner/python-ptrace>.
π§© Option dependency π§©
distormdisassembler (optional) β<http://www.ragestorm.net/distorm/>
π» Installation π»
Note: pip is strongly recommanded. π«‘
Type as root:
python3 setup.py install
Or using sudo program:
sudo python3 setup.py install
β‘ cptrace β‘
For faster debug and to avoid ctypes, you can also install cptrace: Python binding of the ptrace() function written in C:
python3 setup_cptrace.py install
π§ͺ Run tests π§ͺ
π§ͺ Run tests with tox π§ͺ
To run all tests, just type:
tox
The tox project β <https://testrun.org/tox/latest/> β creates a clean virtual environment to run tests.
π§ͺ Run tests manually π§ͺ
Type:
python3 runtests.py
python3 test_doc.py
It's also possible to run a specific test:
PYTHONPATH=$PWD python3 tests/test_strace.py
π python-ptrace usage π
π Hello World π
Short example attaching a running process. It gets the instruction pointer, executes a single step, and gets the new instruction pointer:
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()
π§ API π§
π«Ά PtraceProcess π«Ά
The PtraceProcess class is an helper to manipulate a traced process.
Example:
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
Read ptrace/debugger/process.py source code to see more methods.
π Trace system calls (syscalls) π
python-ptrace can trace system calls using PTRACE_SYSCALL.
π§ PtraceSyscall π§
ptrace.syscall module contains PtraceSyscall class: it's a parser of Linux syscalls similar to strace program.
Example:
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
You can get more information: result type, value address, argument types, and argument names.
Examples:
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 π΅οΈ
Program strace.py is very close to strace program: display syscalls of a program. Example:
β¨ Features (strace.py edition) β¨
- Nice output of signal: see
[[signal|python-ptrace signal handling]] - Supports multiple processes
- Can trace running process
- Can display arguments name, type and address
- Option
--filenameto show only syscall using file names - Option
--socketcallto show only syscall related to network (socket usage) - Option
--syscallsto list all known syscalls
π Example (strace.py edition) π
$ ./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---
π Options (strace.py edition) π
The program has many options. Example with --socketcall (display only network functions):
$ ./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.py is a command line debugger similar to gdb, but with fewer features: no symbol support, no C language support, no thread support, etc.
πΉοΈ Some commands πΉοΈ
cont: continue executionstepi: execute one instructionstep: execute one instruction, but don't enter into calls
Type help to list all available commands.
π Features (gdb.py edition) π
printcommand displays value as decimal and hexadecimal, but also the related memory mapping (if any):
(gdb) print $eip
Decimal: 3086383120
Hexadecimal: 0xb7f67810
Address is part of mapping: 0xb7f67000-0xb7f81000 => /lib/ld-2.6.1.so (r-xp)
- Nice output of signal: see
[[signal|python-ptrace signal handling]] - Syscall tracer with command
"sys": seepython-ptrace system call tracer <syscall>. Short example:
(gdb) sys
long access(char* filename='/etc/ld.so.nohwcap' at 0xb7f7f35b, int mode=F_OK) = -2 (No such file or directory)
- Supports multiple processes:
(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']]
(...)
- Allow multiple commands on the same line using
";"separator:
(gdb) print $eax; set $ax=0xdead; print $eax
Decimal: 0
Hexadecimal: 0x00000000
Set $ax to 57005
Decimal: 57005
Hexadecimal: 0x0000dead
- Only written in pure Python code, so it's easy to extend
- Expression parser supports all arithmetic operator (
a+b,a/b,a<<b,a&b, ...), parenthesis, use of registers, etc. and pointer dereference (ex:print *($ebx+0xc)).
πΌοΈ Screenshot
ok bestie, real talk β here's what an actual live session looks like, in all its glory β¨
$ ./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.
likeβ¦ she's literally doing the most and doing it flawlessly π
π« python-ptrace process events
Process events
every single process event is built on the ProcessEvent class β she's the blueprint, the moment, the mother of them all π
ProcessExit: the process exited with an exitcode, got killed by a signal, or exited abnormallyProcessSignal: the process received a signalNewProcessEvent: a new process got created, e.g. after afork()syscall
Attributes (the little details that matter):
- all events have a
"process"attribute ProcessExithas"exitcode"and"signum"attributes (both can beNone)ProcessSignalhas"signum"and"name"attributes
for NewProcessEvent, hop over to the process.parent attribute to grab the parent process π«Ά
π‘ Note:ProcessSignalhas adisplay()method that shows off its content. Call it right after you receive the message, because it reads process memory to figure out why the signal was sent β so the tea goes stale fast.
Wait for any process event
the most generic one is waitProcessEvent() β it waits for any process event at all (exit, signal, or new process):
event = debugger.waitProcessEvent()
if you want one or more specific signals, that's what the waitSignals() methods are for. call it with no argument and it waits for any signal. any event that isn't a signal gets raised as a Python exception. examples, bestie:
signal = debugger.waitSignals()
signal = debugger.waitSignals(SIGTRAP)
signal = debugger.waitSignals(SIGINT, SIGTERM)
π‘ Note:signalis aProcessSignalobject β usesignal.signumto get the signal number.
Wait for a specific process events
want any event from one specific process? that's waitEvent():
event = process.waitEvent()
for one or more signals, use the waitSignals() method. no argument = waits for any signal. other process events get raised as a Python exception. examples:
signal = process.waitSignals()
signal = process.waitSignals(SIGTRAP)
signal = process.waitSignals(SIGINT, SIGTERM)
π‘ Note: just likedebugger.waitSignals(),signalis aProcessSignalobject.
π¦ python-ptrace signal handling
Introduction
PtraceSignal genuinely tries to serve useful info whenever a signal comes through. depending on which signal number it is, it shows you different things π
it takes the current instruction, decoded as assembler code, to figure out why the signal got raised.
only Intel x86 (i386, maybe x86_64) is supported rn, sorry to the rest of the architectures π
when a process receives a signal, python-ptrace tries to explain why the signal was emitted.
General information (heads up: not shown for all signals, e.g. not for SIGABRT):
- the CPU instruction that caused the crash
- the CPU registers related to the crash
- the memory mappings of the memory addresses
Categorize signals:
SIGFPE- Division by zero
SIGSEGV,SIGBUS- Invalid memory read
- Invalid memory write
- Stack overflow
- Invalid memory access
SIGABRT- Program abort
SIGCHLD- Child process exit
Examples
β Division by zero (SIGFPE)
Signal: SIGFPE
Division by zero
- instruction: IDIV DWORD [[EBP-0x8]
- register ebp=0xbfdc4a98
π Invalid memory read/write (SIGSEGV)
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
Given information β here's what you're getting, no cap:
- address of the segmentation fault
- (if possible) the size of the invalid memory read/write
- the CPU instruction that caused the crash
- the CPU registers related to the crash
- the memory mappings of the related memory address
π Stack overflow (SIGSEGV)
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
πΆ Child exit (SIGCHLD)
PID: 24008
Signal: SIGCHLD
Child process 24009 exited normally
Signal sent by user 1000
Information:
- child process identifier
- child process user identifier
Examples (the short round-up) β¨
Invalid read:
Signal: SIGSEGV
Invalid read from 0x00000008
- instruction: MOV EAX, [EAX+0x8]
- mapping: (no memory mapping)
- register eax=0x00000000
Invalid write (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.
Source code
go look, she's literally right there:
ptrace/debugger/ptrace_signal.pyptrace/debugger/signal_reason.py
π cptrace Python module
a Python binding for ptrace, written in C. tiny, powerful, iconic π
Example
dummy example, just vibes:
>>> 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
π Authors
π Contributors
- Anthony Gelibert
<anthony.gelibert AT me.com>β fix cptrace on Apple - Dimitris Glynos
<dimitris AT census-labs.com>β follow gdb.py commands - Jakub Wilk
<jwilk AT debian.org>β fix for GNU/kFreeBSD - Mark Seaborn
<mrs AT mythic-beasts.com>β Create-ioption for strace - MickaΓ«l GuΓ©rin aka KAeL
<mickael.guerin AT crocobox.org>β OpenBSD port - teythoon β convert all classes to new-style classes
- T. Bursztyka aka Tuna
<tuna AT lyua.org>β x86_64 port - Victor Stinner
<victor.stinner AT gmail.com>β python-ptrace author and maintainer
π Thanks
- procps authors (top and uptime programs)
π Changelog
python-ptrace 0.9.9 (2024-03-13)
- Fix arguments of pipe/pipe2 system calls for proper display in call format. Patch by JosΓ© Pereira.
- Introduced support for three-digit minor device IDs in
PROC_MAP_REGEX. Patch by fab1ano. - Added RISCV (riscv32/riscv64) support. Patch by Andreas Schwab and vimer/yuzibo.
- Fix stray exception raised by child processes terminating with exit code 255. Patch by Duane Voth/duanev.
- Removed usage of the
impmodule. Collaboration between Mario Haustein/hamarituc and Stephen Kitt/skitt.
python-ptrace 0.9.8 (2021-03-17)
- Added Arm 64bit (AArch64) support.
- Implemented
PTRACE_GETREGSETandPTRACE_SETREGSETrequired on AArch64 and available on Linux. - Issue #66: Fix
SIGTRAP|0x80orSIGTRAPwait insyscall_state.exit(PTRACE_O_TRACESYSGOOD). - The development branch
masterwas renamed tomain. Seehttps://sfconservancy.org/news/2020/jun/23/gitbranchname/for the rationale.
python-ptrace 0.9.7 (2020-08-10)
- Add missing module to install directives
- Update
README.rst - Project back in beta and maintenance
python-ptrace 0.9.6 (2020-08-10)
- Remove
RUNNING_WINDOWSconstant: python-ptrace doesn't not support Windows. - Drop Python 2.7 support.
sixdependency is no longer needed. - Add
close_fdsandpass_fdstocreateChild()function. Patch by Jean-Baptiste Skutnik. - Enhance
strace.pyoutput for open flags and open optional parameters. Patch by Jean-Baptiste Skutnik. - Add support for PowerPC 64-bit (ppc64). Patch by Jean-Baptiste Skutnik.
python-ptrace 0.9.5 (2020-04-13)
- Fix
readProcessMappings()for device id on 3 digits. Patch by Cat Stevens. - Drop Python 2 support.
python-ptrace 0.9.4 (2019-07-30)
- Issue #36: Fix detaching from process object created without
is_attached=True - The project now requires the
sixmodule. - Project moved to:
https://github.com/vstinner/python-ptrace
python-ptrace 0.9.3 (2017-09-19)
- Issue #42: Fix
test_strace.py: tolerate theopenat()syscall.
python-ptrace 0.9.2 (2017-02-12)
- Issue #35: Fix
strace.pywhen tracing multiple processes: use the correct process. Fix suggested by Daniel Trnka.
python-ptrace 0.9.1 (2016-10-12)
- Added tracing of processes created with the clone syscall (commonly known as threads).
gdb.py: addgcorecommand, dump the process memory.- Allow command names without absolute path.
- Fix ptrace binding: clear errno before calling
ptrace(). - Fix
PtraceSyscall.exit()for unknown error code - Project moved to GitHub:
https://github.com/haypo/python-ptrace - Remove the
ptrace.ctypes_errnomodule: use directly thectypes.get_errno()function - Remove the
ptrace.ctypes_errnomodule: use directlyctypes.c_int8,ctypes.c_uint32, ... types
python-ptrace 0.9 (2016-04-23)
- Add all Linux syscall prototypes
- Add error symbols (e.g.
ENOENT), in addition to error text, for strace - Fix open mode so
O_RDONLYshows if it's the only file access mode - Python 3: fix formatting of string syscall arguments (ex: filenames), decode bytes from the locale encoding
- Issue #17: syscall parser now supports
O_CLOEXECandSOCK_CLOEXEC, fix unit tests on Python 3.4 and newer
python-ptrace 0.8.1 (2014-10-30)
- Update
MANIFEST.into include all files - Fix to support Python 3.5
π python-ptrace 0.8 (2014-10-05)
- Issue #9: no cap, they rewrote
waitProcessEvent()andwaitSignals()over inPtraceProcessso they stop callingwaitpid()withpid=-1. Why? because there's a literal race condition betweenwaitpid(-1)andforkβ the status of the child process can come back before the debugger even finds out the new child process was created. chaos. π - Issue #10: fixed
PtraceProcess.readBytes()for processes the debugger didn't create itself (ex:fork) for when the kernel blocks access to private mappings of/proc/pid/mem. The glow-up: fall back toPTRACE_PEEKTEXT, which is slower but a debugger tracing the process is always allowed to use it. slow but legal, we love that for us π
πΈ python-ptrace 0.7 (2013-03-05)
- experimental support of Python 3.3 in the same code base π¦
- dropped support of Python 2.5 (rip bozo)
- removed the
ptrace.compatibilitymodule - fixed
Process.readStruct()andProcess.readArray()on x86_64 - experimental support of ARM architecture (Linux EAPI) β
strace.pyhas been tested on Raspberry Pi (armv6l) π
β python-ptrace 0.6.6 (2013-12-16)
- fixed
os_tools.RUNNING_LINUXfor Python 2.x compiled on Linux kernel 3.x - FreeBSD on x86_64 is supported now π
- added the missing prototype of the
unlinkat()system call. patch written by Matthew Fernandez β ty bestie π«Ά
π python-ptrace 0.6.5 (2013-06-06)
syscall: fixed parsingsocketcallon Linux x86syscall: fixed the prototype ofsocket()
β¨ python-ptrace 0.6.4 (2012-02-26)
- converted all classes to new-style classes, patch written by teythoon
- fixed compilation on Apple, patch written by Anthony Gelibert π
- GNU/kFreeBSD support, patch written by Jakub Wilk
sockaddr_in6(IPv6 address) support β hi bestie in six dimensions π
π¦ python-ptrace 0.6.3 (2011-02-16)
- support distrom3
- Python 3 support (era-defining, honestly)
- renamed
strace.pyoption--socketcallto--socket, and fixed this option for FreeBSD and Linux/64 bits - added
MANIFEST.in: include all files in source distribution (tests,cptracemodule, ...) π¦
π python-ptrace 0.6.2 (2009-11-09)
- fixed 64 bits sub registers (set mask for
eax,ebx,ecx,edx)
π python-ptrace 0.6.1 (2009-11-07)
- created
follow,showfollow,resetfollow,xraycommands ingdb.py. patch written by Dimitris Glynos - project website moved to:
http://bitbucket.org/haypo/python-ptrace/ - replaced types
(u)intXX_tbyc_(u)intXX - created
MemoryMapping.search()method, andMemoryMappingnow keeps a weak reference to the process (clingy but in a healthy way)
π python-ptrace 0.6 (2009-02-13)
User visible changes:
python-ptracenow depends on Python 2.5- invalid memory access: add the fault address in the name
- updated the Python 3.0 conversion patch
- created
-i(--show-ip) option forstrace.py: shows the instruction pointer - added a new example (
itrace.py) written by Mark Seaborn and based onstrace.py
API changes:
PtraceSyscall: store the instruction pointer at syscall enter (if the optioninstr_pointer=True, disabled by default)- removed
PROC_DIRNAMEandprocFilename()fromptrace.linux_proc
Bugfixes:
- fixed
locateProgram()for relative path - fixed interpretation of memory fault on the
MOSVWinstruction (source isESIand destination isEDI, and not the inverse!) π
π python-ptrace 0.5 (2008-09-13)
Visible changes:
- wrote an example (the most simple debugger) and began to document the code
gdb.py: created"dbginfo"command- parse socket syscalls on FreeBSD
- on invalid memory access (
SIGSEGV), eval the dereference expression to get the fault address on OS withoutsiginfo(e.g. FreeBSD) - fixes to get minimal Windows support: fix imports, fix
locateProgram()
Other changes:
- break the API, periodt:
- rename
PtraceDebugger.traceSysgood()toPtraceDebugger.enableSysgood() - rename
PtraceDebugger.trace_sysgoodtoPtraceDebugger.use_sysgood - remove
PtraceProcess.readCode()
- rename
- created
createChild()function which close all files exceptstdin,stdoutandstderr - on FreeBSD, on process exit recalls
waitpid(pid)to avoid zombi process π§
π python-ptrace 0.4.2 (2008-08-28)
- BUGFIX: fixed a typo in
gdb.py(commands=>command_str) β it wasn't possible to write more than one command... the way that bugs in typos ruin everything π - BUGFIX: fixed a typo in
SignalInfoclass (remove"self."). When a process received a signalSIGCHLD(because of a fork), the debugger exited because of this bug. iconic fail tbh - BUGFIX:
Debugger._wait()returns abnormal process exit as a normal event, the event is not raised as an exception PtraceSignal: don't clear preformatted arguments (e.g. arguments ofexecve)
π¦ python-ptrace 0.4.1 (2008-08-23)
- the project has a new dedicated website:
http://python-ptrace.hachoir.org/β¨ - created
cptrace: optional Python binding of ptrace written in C (faster than ptrace, the Python binding written in Python withctypes) - added
nameattribute toSignalInfoclasses - fixes to help Python 3.0 compatibility: don't use
sys.exc_clear()(was useless) inwriteBacktrace() ProcessState: createdutime,stime,starttimeattributes
π python-ptrace 0.4.0 (2008-08-19)
Visible changes:
- renamed the project to
"python-ptrace"(old name was"Ptrace) strace.py: created--ignore-regexoptionPtraceSignal: supportSIGBUS, display the related registers and the instruction- support
execve()syscall tracing
Developer changes:
- the new API is incompatible with 0.3.2 (glow-up, not a downgrade)
PtraceProcess.waitProcessEvent()accepts optionalblocking=FalseargumentPtraceProcess.getreg()/setreg()are able to read/write i386 and x86-64 "sub-registers" likealorbx- removed
iterProc()function, replaced byopenProc()with explicit call to.close()to make sure that files are closed - created
searchProcessesByName() - replaced
CPU_PPCconstant byCPU_POWERPCand createdCPU_PPC32andCPU_PPC64 - created
MemoryMappingobject, used byreadMappings()andfindStack()methods ofPtraceProcess - always define all
PtraceProcessmethods but raise an error if the function is not implemented
π₯ TODO π₯
Main tasks
- fix
strace.py --socketcall:SyscallState.enter()callsignore_callbackbeforesocketcallare proceed - support other backends:
- GDB MI:
http://code.google.com/p/pygdb/ - ktrace: (FreeBSD and Darwin): would help Darwin support
- utrace (new Linux debugger):
http://sourceware.org/systemtap/wiki/utrace - vtrace?
- PyDBG: works on Windows
- GDB MI:
- backtrace symbols:
- GNU BFD?
- elfsh?
- addr2line program?
- see
dl_iterate_phdr()function oflibdl
- support other disassemblers (than distorm), and so both Intel syntax (Intel and AT&T)
- BFD
http://www.ragestorm.net/distorm/- libasm (ERESI)
- libdisasm (bastard)
http://www.woodmann.com/collaborative/tools/index.php/Category:X86_Disassembler_Libraries
- support threads: other backends (than python-ptrace) already support threads
Minor tasks
- fix
gdb.py"step"command on a jump. Example where step will never stop:
(gdb) where
ASM 0xb7e3b917: JMP 0xb7e3b8c4 (eb ab)
ASM 0xb7e3b919: LEA ESI, [ESI+0x0] (8db426 00000000)
- remove
gdb.py"except PtraceError, err: if err.errno == ESRCH"hack, process death detection should be done byPtraceProcessorPtraceDebugger - use Intel hardware breakpoints: set vtrace source code
- support Darwin:
- ktrace? need to recompile Darwin kernel with
KTRACEoption - get registers:
http://unixjunkie.blogspot.com/2006/01/darwin-ptrace-and-registers.html PT_DENY_ATTACH:http://steike.com/code/debugging-itunes-with-gdb/PT_DENY_ATTACH:http://landonf.bikemonkey.org/code/macosx/ptrace_deny_attach.20041010201303.11809.mojo.html
- ktrace? need to recompile Darwin kernel with
not all of this is done, bestie β it's a wishlist, not a receipt π
π¦ LINKS π¦
Project using python-ptrace
- Fusil the fuzzer
http://fusil.readthedocs.io
python-ptrace announces
- fuzzing mailing list
http://www.whitestar.linuxbox.org/pipermail/fuzzing/2008-February/000474.html - reverse-engineering.net
http://www.reverse-engineering.net/viewtopic.php?f=10&t=6656
ptrace usage
- Sandboxing: Plash
http://plash.beasts.org/
Similar projects
- vtrace
http://kenshoto.com/vtrace/: Python library (Windows and Linux) supporting threads - subterfuge
http://subterfugue.org/by Mike Coleman: Python library (Linux): contains Python binding of ptrace written in C for Python 2.1/2.2. It doesn't work with Python 2.5 (old project, not maintained since 2002) π - strace
http://sourceforge.net/projects/strace/program (Linux, BSD) - ltrace program (Linux)
- truss program (Solaris and BSD)
- pytstop
http://www.secdev.org/projects/pytstop/by Philippe Biondi: debugger similar to gdb but in very alpha stage (e.g. no disassembler), using ptrace Python binding written in C (from subterfuge) - strace.py
http://www.secdev.org/articles/reverse/strace.pyby Philippe Biondi - Fenris
http://lcamtuf.coredump.cx/fenris/: suite of tools suitable for code analysis, debugging, protocol analysis, reverse engineering, forensics, diagnostics, security audits, vulnerability research - PyDBG
http://pedram.redhive.com/PaiMei/docs/: Windows debugger written in pure Python
Interesting articles
- (fr) Surveiller les connexions avec auditd
http://devloop.lyua.org/blog/index.php?2007/12/26/488-surveiller-les-connexions-avec-auditd(2007) - Playing with ptrace() for fun and profit
http://actes.sstic.org/SSTIC06/Playing_with_ptrace/SSTIC06-Bareil-Playing_with_ptrace.pdf(2006) - PTRACE_SETOPTIONS tests
http://kerneltrap.org/node/5644(2005) - Process Tracing Using Ptrace
http://linuxgazette.net/issue81/sandeep.html(2002)
πΈ Author πΈ
Victor Stinner β the main character who wrote all of this π
π Copyright π
2014, Victor Stinner
okay that's the whole page bestie, you made it to the end π this little beauty is version 0.9.9, dated Dec 14, 2025, and you can find it filed under PYTHON-PTRACE(1) β the way that it's still serving looks after all these years, we love a legacy icon π«Άβ¨ go forth and trace some processes fr fr π
π¦ where this page comes from
- arch rolling: python-ptrace 0.9.9-5 Β· GPL-2.0-only
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms