1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
from ptrace.ctypes_tools import formatAddress, formatWordHex
from ptrace.error import PtraceError
from ptrace.cpu_info import CPU_I386, CPU_X86_64
from ptrace.process_tools import formatProcessStatus
import re
# Find all Intel registers (in upper case)
if CPU_I386:
regex = 'E[A-Z]{2}|[CDEFGS]S|[ABCD]L'
elif CPU_X86_64:
regex = '[ER][A-Z]{2}|[CDEFGS]S|[ABCD]L'
else:
regex = None
if regex:
REGISTER_REGEX = re.compile(r'\b(?:%s)\b' % regex)
else:
REGISTER_REGEX = None
def extractRegisters(process, instr):
registers = {}
if not process or not instr or not REGISTER_REGEX:
return registers
asm = instr.text
asm = asm.upper()
# Skip the operator ("MOV CL, [EAX]" => "CL, [EAX]")
asm = asm.split(" ", 1)[1]
for match in REGISTER_REGEX.finditer(asm):
name = match.group(0)
name = name.lower()
try:
value = process.getreg(name)
registers[name] = value
except PtraceError as err:
pass
return registers
def findMappings(addresses, process, size):
mappings = []
if addresses is None or not process:
return mappings
if not isinstance(addresses, (list, tuple)):
addresses = (addresses,)
if not size:
size = 0
process_mappings = process.readMappings()
if not process_mappings:
return mappings
for address in addresses:
address_str = formatAddress(address)
if 1 < size:
address_str += "..%s" % formatAddress(address + size - 1)
found = False
for map in process_mappings:
if (map.start <= address < map.end) \
or (map.start <= (address + size - 1) < map.end):
found = True
mappings.append("%s is part of %s" % (address_str, map))
if not found:
mappings.append("%s is not mapped in memory" % address_str)
return mappings
class SignalInfo(Exception):
def __init__(self, name, text,
address=None, size=None, instr=None,
process=None, registers=None):
Exception.__init__(self, text)
self.name = name
self.text = text
self.instr = instr
self.registers = extractRegisters(process, instr)
if registers:
self.registers.update(registers)
self.mappings = findMappings(address, process, size)
def display(self, log):
log(self.text)
self.displayExtra(log)
if self.instr:
log("- instruction: %s" % self.instr)
for mapping in self.mappings:
log("- mapping: %s" % mapping)
for name, value in self.registers.items():
log("- register %s=%s" % (name, formatWordHex(value)))
def displayExtra(self, log):
pass
class DivisionByZero(SignalInfo):
def __init__(self, instr=None, process=None):
SignalInfo.__init__(self, "div_by_zero",
"Division by zero", instr=instr, process=process)
class Abort(SignalInfo):
def __init__(self):
SignalInfo.__init__(self, "abort",
"Program received signal SIGABRT, Aborted.")
class StackOverflow(SignalInfo):
def __init__(self, stack_ptr, stack_map, instr=None, process=None):
text = "STACK OVERFLOW! Stack pointer is in %s" % stack_map
SignalInfo.__init__(self, "stack_overflow", text,
address=stack_ptr, registers={'<stack ptr>': stack_ptr},
instr=instr, process=process)
self.stack_ptr = stack_ptr
self.stack_map = stack_map
class InvalidMemoryAcces(SignalInfo):
NAME = "invalid_mem_access"
PREFIX = "Invalid memory access"
PREFIX_ADDR = "Invalid memory access to %s"
def __init__(self, address=None, size=None, instr=None, registers=None, process=None):
"""
address is an integer or a list of integer
"""
if address is not None:
if isinstance(address, (list, tuple)):
arguments = " or ".join( formatAddress(addr) for addr in address )
else:
arguments = formatAddress(address)
message = self.PREFIX_ADDR % arguments
else:
message = self.PREFIX
if size:
message += " (size=%s bytes)" % size
name = self.NAME
if address is not None:
name += "-" + formatAddress(address).lower()
SignalInfo.__init__(self, name, message,
address=address, size=size, instr=instr,
process=process, registers=registers)
class InvalidRead(InvalidMemoryAcces):
NAME = "invalid_read"
PREFIX = "Invalid read"
PREFIX_ADDR = "Invalid read from %s"
class InvalidWrite(InvalidMemoryAcces):
NAME = "invalid_write"
PREFIX = "Invalid write"
PREFIX_ADDR = "Invalid write to %s"
class InstructionError(SignalInfo):
def __init__(self, address, process=None):
SignalInfo.__init__(self, "instr_error",
"UNABLE TO EXECUTE CODE AT %s (SEGMENTATION FAULT)" % formatAddress(address),
address=address,
process=process,
registers={'<instr pointer>': address})
class ChildExit(SignalInfo):
def __init__(self, pid=None, status=None, uid=None):
if pid is not None and status is not None:
message = formatProcessStatus(status, "Child process %s" % pid)
else:
message = "Child process exited"
SignalInfo.__init__(self, "child_exit", message)
self.pid = pid
self.status = status
self.uid = uid
def displayExtra(self, log):
if self.uid is not None:
log("Signal sent by user %s" % self.uid)
|