I trying to make a program like strace, but I'm stuck with the syscall execve
, the registers rdi, rsi and rdx all contain 0 (I also tried with an assembler file that makes the hard-coded syscall), here's part of the code:
regs = Registers() # Registers is a ctypes version of user_regs_struct and works well with others syscalls
libc.ptrace(PtraceReq.PTRACE_GETREGS, pid, None, byref(regs))
print(regs.rdi, regs.rsi, regs.rdx)
# 0, 0, 0
How to get the pointer to the file name ?
EDIT: more complete code:
class Tracer:
def __init__(self):
pass
def trace_exec(self, command, *args):
child_pid = os.fork()
if child_pid == 0:
# PtraceReq is PTRACE_* enum
libc.ptrace(PtraceReq.PTRACE_TRACEME, 0, None, None)
exec(command, *args) # choose the best version of exec familly for passed args
else:
self._trace(child_pid)
def _trace(self, pid):
status = os.wait()[1]
libc.ptrace(PtraceReq.PTRACE_SETOPTIONS, pid, 0, 1 << 20) # PTRACE_O_EXITKILL
while status == 1407:
libc.ptrace(PtraceReq.PTRACE_SYSCALL, pid, None, None)
status = os.wait()[1]
self._get_syscall(pid) # before this was above os.wait and ptrace_syscall
def _get_syscall(self, pid):
regs = Registers()
# Enter syscall
libc.ptrace(PtraceReq.PTRACE_GETREGS, pid, None, byref(regs))
# list of all syscalls by ID, call them parse the arguments
syscall = syscalls[regs.orig_rax](regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9)
libc.ptrace(PtraceReq.PTRACE_SYSCALL, pid, None, None)
os.wait()
# Exit syscall
libc.ptrace(PtraceReq.PTRACE_GETREGS, pid, None, byref(regs))
syscall.returned(regs.rax)
#if (syscall.name == 'connect') or (syscall.name == 'execve'):
print(syscall.as_function())
if __name__ == '__main__':
Tracer().trace_exec(sys.argv[1], *sys.argv[2:])