def memoryFaultInstr(self, instr, fault_address):
        asm = instr.text

        # Invalid write (eg. "MOV [...], value")
        match = re.search(r"^(?:MOV|TEST)[A-Z]* %s," % DEREF_REGEX, asm)
        if match:
            if fault_address is None:
                fault_address = evalFaultAddress(self.process, match)
            self.reason = InvalidWrite(fault_address, size=findDerefSize(match),
                instr=instr, process=self.process)
            return

        # Invalid read (eg. "CMP BYTE [EAX+EDX-0x1], 0x0")
        match = re.search(r"^%s %s," % (INSTR_REGEX, DEREF_REGEX), asm)
        if match:
            if fault_address is None:
                fault_address = evalFaultAddress(self.process, match)
            self.reason = InvalidRead(fault_address, size=findDerefSize(match),
                instr=instr, process=self.process)
            return

        # Invalid read (eg. "MOV reg, [...]")
        match = re.match(r"%s [^,]+, %s" % (INSTR_REGEX, DEREF_REGEX), asm)
        if match:
            if fault_address is None:
                fault_address = evalFaultAddress(self.process, match)
            self.reason = InvalidRead(fault_address, size=findDerefSize(match),
                instr=instr, process=self.process)
            return

        # MOVS* and SCAS* instructions (eg. "MOVSB" or "REP SCASD")
        match = re.search(r"^(?:REP(?:NZ)? )?(?P<operator>MOVS|SCAS)(?P<suffix>[BWD])?", asm)
        if match:
            self.reason = self.movsInstr(fault_address, instr, match)
            return
 def childExit(self):
     siginfo = self.getSignalInfo()
     if siginfo:
         child = siginfo._sigchld
         self.reason = ChildExit(child.pid, child.status, child.uid)
     else:
         self.reason = ChildExit()
 def childExit(self):
     siginfo = self.getSignalInfo()
     if siginfo:
         child = siginfo._sigchld
         self.reason = ChildExit(child.pid, child.status, child.uid)
     else:
         self.reason = ChildExit()
    def memoryFaultInstr(self, instr, fault_address):
        asm = instr.text

        # Invalid write (eg. "MOV [...], value")
        match = re.search(r"^(?:MOV|TEST)[A-Z]* %s," % DEREF_REGEX, asm)
        if match:
            if fault_address is None:
                fault_address = evalFaultAddress(self.process, match)
            self.reason = InvalidWrite(fault_address, size=findDerefSize(match),
                instr=instr, process=self.process)
            return

        # Invalid read (eg. "CMP BYTE [EAX+EDX-0x1], 0x0")
        match = re.search(r"^%s %s," % (INSTR_REGEX, DEREF_REGEX), asm)
        if match:
            if fault_address is None:
                fault_address = evalFaultAddress(self.process, match)
            self.reason = InvalidRead(fault_address, size=findDerefSize(match),
                instr=instr, process=self.process)
            return

        # Invalid read (eg. "MOV reg, [...]")
        match = re.match(r"%s [^,]+, %s" % (INSTR_REGEX, DEREF_REGEX), asm)
        if match:
            if fault_address is None:
                fault_address = evalFaultAddress(self.process, match)
            self.reason = InvalidRead(fault_address, size=findDerefSize(match),
                instr=instr, process=self.process)
            return

        # MOVS* and SCAS* instructions (eg. "MOVSB" or "REP SCASD")
        match = re.search(r"^(?:REP(?:NZ)? )?(?P<operator>MOVS|SCAS)(?P<suffix>[BWD])?", asm)
        if match:
            self.reason = self.movsInstr(fault_address, instr, match)
            return
 def mathError(self):
     instr = self.getInstruction()
     if not instr:
         return
     match = re.match(r"I?DIV (.*)", instr.text)
     if not match:
         return
     self.reason = DivisionByZero(instr=instr, process=self.process)
 def mathError(self):
     instr = self.getInstruction()
     if not instr:
         return
     match = re.match(r"I?DIV (.*)", instr.text)
     if not match:
         return
     self.reason = DivisionByZero(instr=instr, process=self.process)
Exemple #7
0
    def memoryFault(self):
        # Get fault
        siginfo = self.getSignalInfo()
        if siginfo:
            fault_address = siginfo._sigfault._addr
            if not fault_address:
                fault_address = 0
        else:
            fault_address = None

        # Get current instruction
        instr = self.getInstruction()

        # Call to invalid address?
        if fault_address is not None:
            try:
                ip = self.process.getInstrPointer()
                if ip == fault_address:
                    self.reason = InstructionError(ip, process=self.process)
                    return
            except PtraceError:
                pass

        # Stack overflow?
        stack = self.process.findStack()
        if stack:
            sp = self.process.getStackPointer()
            if not (stack.start <= sp <= stack.end):
                self.reason = StackOverflow(sp,
                                            stack,
                                            instr=instr,
                                            process=self.process)
                return

        # Guess error type using the assembler instruction
        if instr:
            self.memoryFaultInstr(instr, fault_address)
            if self.reason:
                return

        # Last chance: use generic invalid memory access error
        self.reason = InvalidMemoryAccess(fault_address,
                                          instr=instr,
                                          process=self.process)
 def _analyze(self):
     if self.signum in (SIGSEGV, SIGBUS):
         self.memoryFault()
     elif self.signum == SIGFPE:
         self.mathError()
     elif self.signum == SIGCHLD:
         self.childExit()
     elif self.signum == SIGABRT:
         self.reason = Abort()
     return self.reason
 def _analyze(self):
     if self.signum in (SIGSEGV, SIGBUS):
         self.memoryFault()
     elif self.signum == SIGFPE:
         self.mathError()
     elif self.signum == SIGCHLD:
         self.childExit()
     elif self.signum == SIGABRT:
         self.reason = Abort()
     return self.reason
Exemple #10
0
    def memoryFault(self):
        # Get fault
        siginfo = self.getSignalInfo()
        if siginfo:
            fault_address = siginfo._sigfault._addr
            if not fault_address:
                fault_address = 0
        else:
            fault_address = None

        # Get current instruction
        instr = self.getInstruction()

        # Call to invalid address?
        if fault_address is not None:
            try:
                ip = self.process.getInstrPointer()
                if ip == fault_address:
                    self.reason = InstructionError(ip, process=self.process)
                    return
            except PtraceError:
                pass

        # Stack overflow?
        stack = self.process.findStack()
        if stack:
            sp = self.process.getStackPointer()
            if not (stack.start <= sp <= stack.end):
                self.reason = StackOverflow(
                    sp, stack, instr=instr, process=self.process)
                return

        # Guess error type using the assembler instruction
        if instr:
            self.memoryFaultInstr(instr, fault_address)
            if self.reason:
                return

        # Last chance: use generic invalid memory access error
        self.reason = InvalidMemoryAcces(
            fault_address, instr=instr, process=self.process)
class ProcessSignal(ProcessEvent):
    def __init__(self, signum, process):
        # Initialize attributes
        self.name = signalName(signum)
        ProcessEvent.__init__(self, process, "Signal %s" % self.name)
        self.signum = signum
        self.reason = None

    def _analyze(self):
        if self.signum in (SIGSEGV, SIGBUS):
            self.memoryFault()
        elif self.signum == SIGFPE:
            self.mathError()
        elif self.signum == SIGCHLD:
            self.childExit()
        elif self.signum == SIGABRT:
            self.reason = Abort()
        return self.reason

    def getInstruction(self):
        if not HAS_DISASSEMBLER:
            return None
        try:
            return self.process.disassembleOne()
        except PtraceError:
            return None

    def memoryFaultInstr(self, instr, fault_address):
        asm = instr.text

        # Invalid write (eg. "MOV [...], value")
        match = re.search(r"^(?:MOV|TEST)[A-Z]* %s," % DEREF_REGEX, asm)
        if match:
            if fault_address is None:
                fault_address = evalFaultAddress(self.process, match)
            self.reason = InvalidWrite(fault_address, size=findDerefSize(match),
                instr=instr, process=self.process)
            return

        # Invalid read (eg. "CMP BYTE [EAX+EDX-0x1], 0x0")
        match = re.search(r"^%s %s," % (INSTR_REGEX, DEREF_REGEX), asm)
        if match:
            if fault_address is None:
                fault_address = evalFaultAddress(self.process, match)
            self.reason = InvalidRead(fault_address, size=findDerefSize(match),
                instr=instr, process=self.process)
            return

        # Invalid read (eg. "MOV reg, [...]")
        match = re.match(r"%s [^,]+, %s" % (INSTR_REGEX, DEREF_REGEX), asm)
        if match:
            if fault_address is None:
                fault_address = evalFaultAddress(self.process, match)
            self.reason = InvalidRead(fault_address, size=findDerefSize(match),
                instr=instr, process=self.process)
            return

        # MOVS* and SCAS* instructions (eg. "MOVSB" or "REP SCASD")
        match = re.search(r"^(?:REP(?:NZ)? )?(?P<operator>MOVS|SCAS)(?P<suffix>[BWD])?", asm)
        if match:
            self.reason = self.movsInstr(fault_address, instr, match)
            return

    def movsInstr(self, fault_address, instr, match):
        operator = match.group("operator")
        suffix = match.group("suffix")
        size = {'B': 1, 'W': 2, 'D': 4}.get(suffix)
        error_cls = InvalidMemoryAcces
        try:
            process = self.process
            if CPU_64BITS:
                source_reg = 'rsi'
                dest_reg = 'rdi'
            else:
                source_reg = 'esi'
                dest_reg = 'edi'
            source_addr = process.getreg(source_reg)
            registers = {source_reg: source_addr}
            write = (operator == 'MOVS')
            if write:
                dest_addr = process.getreg(dest_reg)
                registers[dest_reg] = dest_addr

            if fault_address is not None:
                if fault_address == source_addr:
                    error_cls = InvalidRead
                if write and fault_address == dest_addr:
                    error_cls = InvalidWrite
            else:
                if write:
                    fault_address = (source_addr, dest_addr)
                else:
                    fault_address = (source_addr,)
        except PtraceError:
            registers = {}
        return error_cls(fault_address, size=size, instr=instr,
            registers=registers, process=self.process)

    def getSignalInfo(self):
        if RUNNING_LINUX:
            return self.process.getsiginfo()
        else:
            return None

    def memoryFault(self):
        # Get fault
        siginfo = self.getSignalInfo()
        if siginfo:
            fault_address = siginfo._sigfault._addr
            if not fault_address:
                 fault_address = 0
        else:
             fault_address = None

        # Get current instruction
        instr = self.getInstruction()

        # Call to invalid address?
        if fault_address is not None:
            try:
                ip = self.process.getInstrPointer()
                if ip == fault_address:
                    self.reason = InstructionError(ip, process=self.process)
                    return
            except PtraceError:
                pass

        # Stack overflow?
        stack = self.process.findStack()
        if stack:
            sp = self.process.getStackPointer()
            if not (stack.start <= sp <= stack.end):
                self.reason = StackOverflow(sp, stack, instr=instr, process=self.process)
                return

        # Guess error type using the assembler instruction
        if instr:
            self.memoryFaultInstr(instr, fault_address)
            if self.reason:
                return

        # Last chance: use generic invalid memory access error
        self.reason = InvalidMemoryAcces(fault_address, instr=instr, process=self.process)

    def mathError(self):
        instr = self.getInstruction()
        if not instr:
            return
        match = re.match(r"I?DIV (.*)", instr.text)
        if not match:
            return
        self.reason = DivisionByZero(instr=instr, process=self.process)

    def childExit(self):
        siginfo = self.getSignalInfo()
        if siginfo:
            child = siginfo._sigchld
            self.reason = ChildExit(child.pid, child.status, child.uid)
        else:
            self.reason = ChildExit()

    def display(self, log=None):
        self._analyze()
        if not log:
            log = error
        log("-" * 60)
        log("PID: %s" % self.process.pid)
        log("Signal: %s" % self.name)
        if self.reason:
            self.reason.display(log)
        log("-" * 60)
class ProcessSignal(ProcessEvent):
    def __init__(self, signum, process):
        # Initialize attributes
        self.name = signalName(signum)
        ProcessEvent.__init__(self, process, "Signal %s" % self.name)
        self.signum = signum
        self.reason = None

    def _analyze(self):
        if self.signum in (SIGSEGV, SIGBUS):
            self.memoryFault()
        elif self.signum == SIGFPE:
            self.mathError()
        elif self.signum == SIGCHLD:
            self.childExit()
        elif self.signum == SIGABRT:
            self.reason = Abort()
        return self.reason

    def getInstruction(self):
        if not HAS_DISASSEMBLER:
            return None
        try:
            return self.process.disassembleOne()
        except PtraceError:
            return None

    def memoryFaultInstr(self, instr, fault_address):
        asm = instr.text

        # Invalid write (eg. "MOV [...], value")
        match = re.search(r"^(?:MOV|TEST)[A-Z]* %s," % DEREF_REGEX, asm)
        if match:
            if fault_address is None:
                fault_address = evalFaultAddress(self.process, match)
            self.reason = InvalidWrite(fault_address, size=findDerefSize(match),
                instr=instr, process=self.process)
            return

        # Invalid read (eg. "CMP BYTE [EAX+EDX-0x1], 0x0")
        match = re.search(r"^%s %s," % (INSTR_REGEX, DEREF_REGEX), asm)
        if match:
            if fault_address is None:
                fault_address = evalFaultAddress(self.process, match)
            self.reason = InvalidRead(fault_address, size=findDerefSize(match),
                instr=instr, process=self.process)
            return

        # Invalid read (eg. "MOV reg, [...]")
        match = re.match(r"%s [^,]+, %s" % (INSTR_REGEX, DEREF_REGEX), asm)
        if match:
            if fault_address is None:
                fault_address = evalFaultAddress(self.process, match)
            self.reason = InvalidRead(fault_address, size=findDerefSize(match),
                instr=instr, process=self.process)
            return

        # MOVS* and SCAS* instructions (eg. "MOVSB" or "REP SCASD")
        match = re.search(r"^(?:REP(?:NZ)? )?(?P<operator>MOVS|SCAS)(?P<suffix>[BWD])?", asm)
        if match:
            self.reason = self.movsInstr(fault_address, instr, match)
            return

    def movsInstr(self, fault_address, instr, match):
        operator = match.group("operator")
        suffix = match.group("suffix")
        size = {'B': 1, 'W': 2, 'D': 4}.get(suffix)
        error_cls = InvalidMemoryAcces
        try:
            process = self.process
            if CPU_64BITS:
                source_reg = 'rsi'
                dest_reg = 'rdi'
            else:
                source_reg = 'esi'
                dest_reg = 'edi'
            source_addr = process.getreg(source_reg)
            registers = {source_reg: source_addr}
            write = (operator == 'MOVS')
            if write:
                dest_addr = process.getreg(dest_reg)
                registers[dest_reg] = dest_addr

            if fault_address is not None:
                if fault_address == source_addr:
                    error_cls = InvalidRead
                if write and fault_address == dest_addr:
                    error_cls = InvalidWrite
            else:
                if write:
                    fault_address = (source_addr, dest_addr)
                else:
                    fault_address = (source_addr,)
        except PtraceError:
            registers = {}
        return error_cls(fault_address, size=size, instr=instr,
            registers=registers, process=self.process)

    def getSignalInfo(self):
        if RUNNING_LINUX:
            return self.process.getsiginfo()
        else:
            return None

    def memoryFault(self):
        # Get fault
        siginfo = self.getSignalInfo()
        if siginfo:
            fault_address = siginfo._sigfault._addr
            if not fault_address:
                 fault_address = 0
        else:
             fault_address = None

        # Get current instruction
        instr = self.getInstruction()

        # Call to invalid address?
        if fault_address is not None:
            try:
                ip = self.process.getInstrPointer()
                if ip == fault_address:
                    self.reason = InstructionError(ip, process=self.process)
                    return
            except PtraceError:
                pass

        # Stack overflow?
        stack = self.process.findStack()
        if stack:
            sp = self.process.getStackPointer()
            if not (stack.start <= sp <= stack.end):
                self.reason = StackOverflow(sp, stack, instr=instr, process=self.process)
                return

        # Guess error type using the assembler instruction
        if instr:
            self.memoryFaultInstr(instr, fault_address)
            if self.reason:
                return

        # Last chance: use generic invalid memory access error
        self.reason = InvalidMemoryAcces(fault_address, instr=instr, process=self.process)

    def mathError(self):
        instr = self.getInstruction()
        if not instr:
            return
        match = re.match(r"I?DIV (.*)", instr.text)
        if not match:
            return
        self.reason = DivisionByZero(instr=instr, process=self.process)

    def childExit(self):
        siginfo = self.getSignalInfo()
        if siginfo:
            child = siginfo._sigchld
            self.reason = ChildExit(child.pid, child.status, child.uid)
        else:
            self.reason = ChildExit()

    def display(self, log=None):
        self._analyze()
        if not log:
            log = error
        log("-" * 60)
        log("PID: %s" % self.process.pid)
        log("Signal: %s" % self.name)
        if self.reason:
            self.reason.display(log)
        log("-" * 60)