Skip to content

Commit

Permalink
fixed verifier
Browse files Browse the repository at this point in the history
  • Loading branch information
dobin committed Oct 12, 2017
1 parent 4e205aa commit 9344c6c
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 87 deletions.
3 changes: 2 additions & 1 deletion printpickle.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import pprint
import sys

#from verifier import verifierresult


def printpickle():
pp = pprint.PrettyPrinter(indent=4)
Expand All @@ -12,6 +14,5 @@ def printpickle():
p = pickle.load(f)
pp.pprint(p)


if __name__ == '__main__':
printpickle()
9 changes: 3 additions & 6 deletions verifier/debugservermanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,15 @@
import logging
import signal
import os
import subprocess
import serverutils

from ptrace.debugger.debugger import PtraceDebugger
from ptrace.debugger.child import createChild
from ptrace.debugger.process_event import ProcessExit
from ptrace.debugger.ptrace_signal import ProcessSignal


import serverutils
import verifycrashdata
from servermanager import ServerManager, StdoutQueue
from servermanager import ServerManager


class DebugServerManager(ServerManager):
Expand Down Expand Up @@ -163,8 +161,7 @@ def _getCrashDetails(self):
print("GetCrashDetails exception: " + str(e))


vCrashData = verifycrashdata.VerifyCrashData()
vCrashData.setData(
vCrashData = verifycrashdata.VerifyCrashData(
faultAddress=faultAddress,
faultOffset=faultOffset,
module=module,
Expand Down
5 changes: 2 additions & 3 deletions verifier/gdbservermanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,9 @@ def _getCrashDetails(self):
res.append(backtraceFrames[i].rstrip("\n\r"))
i += 1

crashData = verifycrashdata.VerifyCrashData()
crashData.setData(
crashData = verifycrashdata.VerifyCrashData(
backtrace=res,
output=ret,
analyzerOutput=ret,
cause="GDBSERVERMANAGER: n/a"
)
gdbOutput = serverutils.getAsanOutput(self.config, self.pid)
Expand Down
109 changes: 63 additions & 46 deletions verifier/verifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
import logging
import signal
import pickle
import copy

import debugservermanager
import gdbservermanager
import networkmanager
import utils
import asanparser
import verifierresult

"""
Crash Verifier
Expand Down Expand Up @@ -53,12 +55,8 @@ def __init__(self, config):
self.p = None # serverManager


def handleNoCrash(self):
logging.info("Verifier: Waited long enough, NO crash. ")


def startChild(self):
p = multiprocessing.Process(target=self.debugServerManager.startAndWait, args=())
def startChild(self, debugServerManager):
p = multiprocessing.Process(target=debugServerManager.startAndWait, args=())
p.start()
self.p = p

Expand All @@ -84,7 +82,7 @@ def stopChild(self):
def verifyFile(self, filename):
"""Verify a single file."""
targetPort = self.config["baseport"] + 100
self.verifyOutcome(targetPort, filename)
self._verifyOutcome(targetPort, filename)


def verifyOutDir(self):
Expand All @@ -103,7 +101,7 @@ def verifyOutDir(self):
for outcomeFile in outcomesFiles:
print("Now processing: " + str(n) + ": " + outcomeFile)
targetPort = self.config["baseport"] + n + 100
self.verifyOutcome(targetPort, outcomeFile)
self._verifyOutcome(targetPort, outcomeFile)
n += 1

except KeyboardInterrupt:
Expand All @@ -120,20 +118,17 @@ def verifyOutDir(self):
print "Number of no crashes: " + str(noCrash)


def verifyOutcome(self, targetPort, outcomeFile):
def _verifyOutcome(self, targetPort, outcomeFile):
outcome = utils.readPickleFile(outcomeFile)

crashData = None
crashDataDebug = None
crashDataGdb = None
crashDataAsan = None

outputAsan = ""
outputGdb = ""

# get normal PTRACE / ASAN output
self.debugServerManager = debugservermanager.DebugServerManager(self.config, self.queue_sync, self.queue_out, targetPort)
crashDataDebug = self.ver(outcome, targetPort)
debugServerManager = debugservermanager.DebugServerManager(self.config, self.queue_sync, self.queue_out, targetPort)
crashDataDebug = self._verify(outcome, targetPort, debugServerManager)
crashDataDebug.printMe("CrashDataDebug")

# get ASAN (if available), and CORE (if available)
Expand All @@ -146,39 +141,46 @@ def verifyOutcome(self, targetPort, outcomeFile):
crashDataAsan.printMe("CrashDataAsan")

# get GDB output
self.debugServerManager = gdbservermanager.GdbServerManager(self.config, self.queue_sync, self.queue_out, targetPort)
crashDataGdb = self.ver(outcome, targetPort)
gdbServerManager = gdbservermanager.GdbServerManager(self.config, self.queue_sync, self.queue_out, targetPort)
crashDataGdb = self._verify(outcome, targetPort, gdbServerManager)
if crashDataGdb is not None:
crashDataGdb.printMe("CrashDataGdb")

# Default: Lets use crashDataDebug
logging.info("V: Use crashDataDebug")
crashData = crashDataDebug
crashData = copy.copy(crashDataDebug)

# add backtrace from Gdb
if crashDataGdb and crashDataGdb.backtrace is not None:
logging.info("V: BT: Use crashDataGdb")
crashData.backtrace = crashDataGdb.backtrace
crashData.cause = crashDataGdb.cause
outputGdb = crashDataGdb.output

# add backtrace from ASAN if exists
if crashDataAsan and crashDataAsan.backtrace is not None:
logging.info("V: BT: Use crashDataAsan")
crashData.backtrace = crashDataAsan.backtrace
crashData.cause = crashDataAsan.cause
outputAsan = crashDataAsan.output

self.handleCrash(outcome, crashData, outputAsan, outputGdb)
verifierResult = verifierresult.VerifierResult(
crashDataDebug,
crashDataAsan,
crashDataGdb,
crashData
)

outcome["verifierResult"] = verifierResult

def ver(self, outcome, targetPort):
self._handleCrash(outcome)


def _verify(self, outcome, targetPort, debugServerManager):
# start server in background
# TODO move this to verifyOutDir (more efficient?)

#self.debugServerManager = debugservermanager.DebugServerManager(self.config, self.queue_sync, self.queue_out, targetPort)
self.networkManager = networkmanager.NetworkManager(self.config, targetPort)
self.startChild()
self.startChild(debugServerManager)

# wait for ok (pid) from child that the server has started
data = self.queue_sync.get()
Expand All @@ -202,69 +204,84 @@ def ver(self, outcome, targetPort):
# empty result. has to be handled.
if crashData:
logging.info("Verifier: I've got a crash: ")
crashData.setStdOutput(serverStdout)
crashData.setProcessStdout(serverStdout)
else:
logging.error("Verifier: Some server error:")
logging.error("Verifier: Output: " + serverStdout)

return crashData
except Queue.Empty:
self.handleNoCrash()
self._handleNoCrash()
self.stopChild()
return None

return None


def handleCrash(self, outcome, vCrashData, outputAsan, outputGdb):
print "Handlecrash"

crashData = vCrashData.getData()
crashData["outputAsan"] = outputAsan
crashData["outputGdb"] = outputGdb

outcome["verifyCrashData"] = crashData
def _handleCrash(self, outcome):
logging.info("Handle a crash")
self._savePickle(outcome)
self._saveTxt(outcome)


def _savePickle(self, outcome):
# write pickle file
fileName = os.path.join(self.config["verified_dir"],
str(outcome["fuzzIterData"]["seed"]) + ".ffw")
with open(fileName, "w") as f:
pickle.dump(outcome, f)


def _saveTxt(self, outcome):
verifierResult = outcome["verifierResult"]
crashData = verifierResult.verifyCrashData
gdbVerifyCrashData = verifierResult.gdbVerifyCrashData
asanVerifyCrashData = verifierResult.asanVerifyCrashData


# write text file
fileName = os.path.join(self.config["verified_dir"],
str(outcome["fuzzIterData"]["seed"]) + ".txt")

# handle registers
if crashData["registers"] is not None:
registerStr = ''.join('{}={} '.format(key, val) for key, val in crashData["registers"].items())
if crashData.registers is not None:
registerStr = ''.join('{}={} '.format(key, val) for key, val in crashData.registers.items())
else:
registerStr = ""

# handle backtrace
if crashData["backtrace"] is not None:
backtraceStr = '\n'.join(map(str, crashData["backtrace"]))
if crashData.backtrace is not None:
backtraceStr = '\n'.join(map(str, crashData.backtrace))
else:
backtraceStr = ""

asanOutput = ""
gdbOutput = ""
if asanVerifyCrashData is not None:
asanOutput = asanVerifyCrashData.analyzerOutput
if gdbVerifyCrashData is not None:
gdbOutput = gdbVerifyCrashData.analyzerOutput

with open(fileName, "w") as f:
f.write("Address: %s\n" % hex(crashData["faultAddress"]))
f.write("Offset: %s\n" % hex(crashData["faultOffset"]))
f.write("Module: %s\n" % crashData["module"])
f.write("Signature: %s\n" % crashData["sig"])
f.write("Details: %s\n" % crashData["details"])
f.write("Stack Pointer: %s\n" % hex(crashData["stackPointer"]))
f.write("Stack Addr: %s\n" % crashData["stackAddr"])
f.write("Address: %s\n" % hex(crashData.faultAddress))
f.write("Offset: %s\n" % hex(crashData.faultOffset))
f.write("Module: %s\n" % crashData.module)
f.write("Signature: %s\n" % crashData.sig)
f.write("Details: %s\n" % crashData.details)
f.write("Stack Pointer: %s\n" % hex(crashData.stackPointer))
f.write("Stack Addr: %s\n" % crashData.stackAddr)
f.write("Registers: %s\n" % registerStr)
f.write("Time: %s\n" % time.strftime("%c"))

f.write("\n")
f.write("Child Output:\n %s\n" % crashData["stdOutput"])
f.write("Child Output:\n %s\n" % crashData.processStdout)
f.write("Backtrace: %s\n" % backtraceStr)
f.write("\n")
f.write("ASAN Output:\n %s\n" % outputAsan)
f.write("ASAN Output:\n %s\n" % asanOutput)
f.write("\n")
f.write("GDB Output:\n %s\n" % outputGdb)
f.write("GDB Output:\n %s\n" % gdbOutput)
f.close()


def _handleNoCrash(self):
logging.info("Verifier: Waited long enough, NO crash. ")
16 changes: 16 additions & 0 deletions verifier/verifierresult.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env python2

import logging


class VerifierResult(object):
def __init__(self,
debugVerifyCrashData,
asanVerifyCrashData,
gdbVerifyCrashData,
verifyCrashData):

self.debugVerifyCrashData = debugVerifyCrashData
self.asanVerifyCrashData = asanVerifyCrashData
self.gdbVerifyCrashData = gdbVerifyCrashData
self.verifyCrashData = verifyCrashData
Loading

0 comments on commit 9344c6c

Please sign in to comment.