I'm trying to build a simple version of starce, which shows you the first x syscalls a process made. The problem is that currently it seems like every syscall appears twice (except execve and exit_group).
This is the code I use to get the syscalls:
import os
import ctypes
# Get libc:
libc = ctypes.CDLL('/lib/x86_64-linux-gnu/libc.so.6')
# Define Constants:
PTRACE_PEEKTEXT = 1
PTRACE_PEEKDATA = 2
PTRACE_POKETEXT = 4
PTRACE_POKEDATA = 5
PTRACE_CONT = 7
PTRACE_SINGLESTEP = 9
PTRACE_GETREGS = 12
PTRACE_SETREGS = 13
PTRACE_ATTACH = 16
PTRACE_DETACH = 17
PTRACE_TRACEME = 0
PTRACE_SYSCALL = 24
PTRACE_PEEKUSER = 32
class user_regs_struct(ctypes.Structure):
_fields_ = [
("r15", ctypes.c_ulonglong),
("r14", ctypes.c_ulonglong),
("r13", ctypes.c_ulonglong),
("r12", ctypes.c_ulonglong),
("rbp", ctypes.c_ulonglong),
("rbx", ctypes.c_ulonglong),
("r11", ctypes.c_ulonglong),
("r10", ctypes.c_ulonglong),
("r9", ctypes.c_ulonglong),
("r8", ctypes.c_ulonglong),
("rax", ctypes.c_ulonglong),
("rcx", ctypes.c_ulonglong),
("rdx", ctypes.c_ulonglong),
("rsi", ctypes.c_ulonglong),
("rdi", ctypes.c_ulonglong),
("orig_rax", ctypes.c_ulonglong),
("rip", ctypes.c_ulonglong),
("cs", ctypes.c_ulonglong),
("eflags", ctypes.c_ulonglong),
("rsp", ctypes.c_ulonglong),
("ss", ctypes.c_ulonglong),
("fs_base", ctypes.c_ulonglong),
("gs_base", ctypes.c_ulonglong),
("ds", ctypes.c_ulonglong),
("es", ctypes.c_ulonglong),
("fs", ctypes.c_ulonglong),
("gs", ctypes.c_ulonglong),
]
ptrace = libc.ptrace
ptrace.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p]
ptrace.restype = ctypes.c_int
pid = 123 # whatever PID you need
syscalls = []
while len(syscalls) < 1024:
try:
_, status = os.waitpid(pid, os.WUNTRACED)
if os.WIFEXITED(status):
break
except:
break
regs = user_regs_struct()
ptrace(PTRACE_GETREGS, pid, 0, ctypes.byref(regs))
syscalls.append(regs.orig_rax)
ptrace(PTRACE_SYSCALL, pid, 0, 0)
And the first 16 syscalls I get for example when running on ls are these:
execve, brk, brk, arch_prctl, arch_prctl, access, access, openat, openat, fstat, fstat, mmap, mmap, close, close, openat
While if I run strace, the first 16 are these:
execve, brk, arch_prctl, access, openat, fstat, mmap, close, openat, read, fstat, mmap, mmap, mprotect, mmap, mmap
As you can see, my code outputs each syscall twice.
What can cause this? And how can it be fixed?