Edit File: ptrace_syscall.py
from os import strerror from errno import errorcode from ptrace.cpu_info import CPU_X86_64, CPU_POWERPC, CPU_I386, CPU_ARM32, CPU_AARCH64 from ptrace.ctypes_tools import ulong2long, formatAddress, formatWordHex from ptrace.func_call import FunctionCall from ptrace.syscall import SYSCALL_NAMES, SYSCALL_PROTOTYPES, SyscallArgument from ptrace.syscall.socketcall import setupSocketCall from ptrace.os_tools import RUNNING_LINUX, RUNNING_BSD from ptrace.cpu_info import CPU_WORD_SIZE from ptrace.binding.cpu import CPU_INSTR_POINTER if CPU_POWERPC: SYSCALL_REGISTER = "gpr0" elif CPU_ARM32: SYSCALL_REGISTER = "r7" elif CPU_AARCH64: SYSCALL_REGISTER = "r8" elif RUNNING_LINUX: if CPU_X86_64: SYSCALL_REGISTER = "orig_rax" else: SYSCALL_REGISTER = "orig_eax" else: if CPU_X86_64: SYSCALL_REGISTER = "rax" else: SYSCALL_REGISTER = "eax" if CPU_ARM32: RETURN_VALUE_REGISTER = "r0" elif CPU_AARCH64: RETURN_VALUE_REGISTER = "r0" elif CPU_I386: RETURN_VALUE_REGISTER = "eax" elif CPU_X86_64: RETURN_VALUE_REGISTER = "rax" elif CPU_POWERPC: RETURN_VALUE_REGISTER = "result" else: raise NotImplementedError("Unsupported CPU architecture") PREFORMAT_ARGUMENTS = { "select": (1, 2, 3), "execve": (0, 1, 2), "clone": (0, 1), } class PtraceSyscall(FunctionCall): def __init__(self, process, options, regs=None): FunctionCall.__init__(self, "syscall", options, SyscallArgument) self.process = process self.restype = "long" self.result = None self.result_text = None self.instr_pointer = None if not regs: regs = self.process.getregs() self.readSyscall(regs) def enter(self, regs=None): if not regs: regs = self.process.getregs() argument_values = self.readArgumentValues(regs) self.readArguments(argument_values) if self.name == "socketcall" and self.options.replace_socketcall: setupSocketCall(self, self.process, self[0], self[1].value) # Some arguments are lost after the syscall, so format them now if self.name in PREFORMAT_ARGUMENTS: for index in PREFORMAT_ARGUMENTS[self.name]: argument = self.arguments[index] argument.format() if self.options.instr_pointer: self.instr_pointer = getattr(regs, CPU_INSTR_POINTER) def readSyscall(self, regs): # Read syscall number self.syscall = getattr(regs, SYSCALL_REGISTER) # Get syscall variables self.name = SYSCALL_NAMES.get( self.syscall, "syscall<%s>" % self.syscall) def readArgumentValues(self, regs): if CPU_X86_64: return (regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9) if CPU_ARM32: return (regs.r0, regs.r1, regs.r2, regs.r3, regs.r4, regs.r5, regs.r6) if CPU_AARCH64: return (regs.r0, regs.r1, regs.r2, regs.r3, regs.r4, regs.r5, regs.r6, regs.r7) if RUNNING_BSD: sp = self.process.getStackPointer() return [self.process.readWord(sp + index * CPU_WORD_SIZE) for index in range(1, 6 + 1)] if CPU_I386: return (regs.ebx, regs.ecx, regs.edx, regs.esi, regs.edi, regs.ebp) if CPU_POWERPC: return (regs.gpr3, regs.gpr4, regs.gpr5, regs.gpr6, regs.gpr7, regs.gpr8) raise NotImplementedError() def readArguments(self, argument_values): if self.name in SYSCALL_PROTOTYPES: self.restype, formats = SYSCALL_PROTOTYPES[self.name] for value, format in zip(argument_values, formats): argtype, argname = format self.addArgument(value=value, name=argname, type=argtype) else: for value in argument_values: self.addArgument(value=value) def exit(self): if self.name in PREFORMAT_ARGUMENTS: preformat = set(PREFORMAT_ARGUMENTS[self.name]) else: preformat = set() # Data pointed by arguments may have changed during the syscall # e.g. uname() syscall for index, argument in enumerate(self.arguments): if index in preformat: # Don't lose preformatted arguments continue if argument.type and not argument.type.endswith("*"): continue argument.text = None self.result = self.process.getreg(RETURN_VALUE_REGISTER) if self.restype.endswith("*"): text = formatAddress(self.result) else: uresult = self.result self.result = ulong2long(self.result) if self.result < 0 and (-self.result) in errorcode: errcode = -self.result text = "%s %s (%s)" % ( self.result, errorcode[errcode], strerror(errcode)) elif not(0 <= self.result <= 9): text = "%s (%s)" % (self.result, formatWordHex(uresult)) else: text = str(self.result) self.result_text = text return text def __str__(self): return "<Syscall name=%r>" % self.name