Skip to content

Commit

Permalink
Validate feature added, bug fixes, and more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Bhargava Shastry committed Oct 6, 2016
1 parent d763ddf commit 3d15209
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 58 deletions.
41 changes: 18 additions & 23 deletions conf/orthrus.conf
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,26 @@
directory = .orthrus

##
## Joern configuration
## Dependencies: Marked True (required) or False (not required)
##
[joern]
joern_path = ~/work/github/joern-0.3.1/bin/
[dependencies]

##
## Neo4j configuration
##
[neo4j]
neo4j_path = ~/software/neo4j-community-2.1.8
# Instrumentation
clang = on
gcc = on

##
## american fuzzy lop (afl) configuration
##
[afl]
afl_path = ~/software/afl-2.10b
# Fuzz
afl-fuzz = on
afl-clang = on
afl-clang++ = on

##
## american fuzzy lop (afl) configuration
##
[afl-utils]
afl_utils_path = ~/software/afl-utils
# Fuzz management and triage
afl-collect = on
afl-multicore = on
afl-minimize = on
gdb = on

##
## AFL Fuzzing Code Coverage (afl-cov) configuration
##
[afl-cov]
afl_cov_path = ~/work/github/afl-cov
# Coverage
afl-cov = on
lcov = on
genhtml = on
41 changes: 35 additions & 6 deletions orthrus/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,10 +393,14 @@ def _start_fuzzers(self, jobId, available_cores):

cmd = ["cat /proc/sys/kernel/core_pattern"]
util.color_print_singleline(util.bcolors.OKGREEN, "Checking core_pattern...")
if "core" not in subprocess.check_output(" ".join(cmd), shell=True, stderr=subprocess.STDOUT):
util.color_print(util.bcolors.FAIL, "failed")
util.color_print(util.bcolors.FAIL, "\t\t\t[-] Please do echo core | "
"sudo tee /proc/sys/kernel/core_pattern")
try:
if "core" not in subprocess.check_output(" ".join(cmd), shell=True, stderr=subprocess.STDOUT):
util.color_print(util.bcolors.FAIL, "failed")
util.color_print(util.bcolors.FAIL, "\t\t\t[-] Please do echo core | "
"sudo tee /proc/sys/kernel/core_pattern")
return False
except subprocess.CalledProcessError as e:
print e.output
return False
util.color_print(util.bcolors.OKGREEN, "okay")

Expand Down Expand Up @@ -453,7 +457,6 @@ def _start_fuzzers(self, jobId, available_cores):

if not util.run_cmd(" ".join(cmd), env, asan_file):
util.color_print(util.bcolors.FAIL, "failed")
util.printfile(asan_file)
return False

util.color_print(util.bcolors.OKGREEN, "done")
Expand Down Expand Up @@ -673,7 +676,11 @@ def run(self):

for jobId in job_config.sections():
syncDir = self._config['orthrus']['directory'] + "/jobs/" + jobId + "/afl-out/"
output = subprocess.check_output(["afl-whatsup", "-s", syncDir])
try:
output = subprocess.check_output(["afl-whatsup", "-s", syncDir])
except subprocess.CalledProcessError as e:
print e.output
return False
output = output[output.find("==\n\n") + 4:]

util.color_print(util.bcolors.OKBLUE, "\tJob [" + jobId + "] " + "for target '" + job_config.get(jobId, "target") + "':")
Expand Down Expand Up @@ -853,4 +860,26 @@ def run(self):
else:
util.color_print(util.bcolors.FAIL, "failed")
return False
return True

class OrthrusValidate(object):

def __init__(self, args, config):
self._args = args
self._config = config

def get_on(self):
return [item for item in self._config['dependencies'] if item[1] == 'on']

def run(self):
util.color_print(util.bcolors.BOLD + util.bcolors.HEADER, "[+] Validating Orthrus dependencies")
util.color_print(util.bcolors.OKGREEN, "\t\t[+] The following programs have been marked as required in " \
"~/.orthrus/orthrus.conf")
for prog, _ in self.get_on():
util.color_print(util.bcolors.OKGREEN, "\t\t\t[+] {}".format(prog))

util.color_print(util.bcolors.OKGREEN, "\t\t[+] Checking if requirements are met.")
if not util.validate_inst(self._config):
return False
util.color_print(util.bcolors.OKGREEN, "\t\t[+] All requirements met. Orthrus is ready for use!")
return True
88 changes: 61 additions & 27 deletions orthrusutils/orthrusutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@
CREATE_HELP = """Create an orthrus workspace"""
ADD_HELP = """Add a fuzzing job"""
REMOVE_HELP = """Remove a fuzzing job"""
START_HELP = """Start the fuzzing jobs"""
STOP_HELP = """Stop the fuzzing jobs"""
SHOW_HELP = """Show whats currently going on"""
TRIAGE_HELP = """Triage crash samples"""
START_HELP = """Start a fuzzing jobs"""
STOP_HELP = """Stop a fuzzing jobs"""
SHOW_HELP = """Show what's currently going on"""
TRIAGE_HELP = """Triage crash corpus"""
# DATABASE_HELP = """Joern database operations"""
# CLEAN_HELP = """Clean up the workspace"""
COVERAGE_HELP = """Run afl-cov on existing AFL corpus"""
DESTROY_HELP = """Destroy the orthrus workspace"""
DESTROY_HELP = """Destroy an orthrus workspace"""
VALIDATE_HELP = """Check if all Orthrus dependencies are met"""

class bcolors:
HEADER = '\033[95m'
Expand Down Expand Up @@ -77,7 +78,7 @@ def copy_binaries(dest):

def parse_cmdline(description, args, createfunc=None, addfunc=None, removefunc=None,
startfunc=None, stopfunc=None, showfunc=None, triagefunc=None,
coveragefunc=None, destroyfunc=None):
coveragefunc=None, destroyfunc=None, validatefunc=None):
argParser = ArgumentParser(description)

argParser.add_argument('-v', '--verbose',
Expand Down Expand Up @@ -189,6 +190,10 @@ def parse_cmdline(description, args, createfunc=None, addfunc=None, removefunc=N
# create_parser.add_argument('-x', type=int, default=1)
destroy_parser.set_defaults(func=destroyfunc)

# Command 'validate'
validate_parser = subparsers.add_parser('validate', help=VALIDATE_HELP)
validate_parser.set_defaults(func=validatefunc)

return argParser.parse_args(args)

def parse_config(configfile=None):
Expand All @@ -202,22 +207,24 @@ def parse_config(configfile=None):
config['orthrus'] = {}
config['orthrus']['directory'] = configparser.get("orthrus", "directory")

config['dependencies'] = configparser.items("dependencies")

# config['joern'] = {}
# config['joern']['joern_path'] = os.path.abspath(os.path.expanduser((configparser.get("joern", "joern_path"))))
#
# config['neo4j'] = {}
# config['neo4j']['neo4j_path'] = os.path.abspath(os.path.expanduser((configparser.get("neo4j", "neo4j_path"))))

config['afl'] = {}
config['afl']['afl_path'] = os.path.abspath(os.path.expanduser((configparser.get("afl", "afl_path"))))

config['afl-utils'] = {}
config['afl-utils']['afl_utils_path'] = os.path.abspath(
os.path.expanduser((configparser.get("afl-utils", "afl_utils_path"))))

config['afl-cov'] = {}
config['afl-cov']['afl_cov_path'] = os.path.abspath(
os.path.expanduser((configparser.get("afl-cov", "afl_cov_path"))))
# config['afl'] = {}
# config['afl']['afl_path'] = os.path.abspath(os.path.expanduser((configparser.get("afl", "afl_path"))))
#
# config['afl-utils'] = {}
# config['afl-utils']['afl_utils_path'] = os.path.abspath(
# os.path.expanduser((configparser.get("afl-utils", "afl_utils_path"))))
#
# config['afl-cov'] = {}
# config['afl-cov']['afl_cov_path'] = os.path.abspath(
# os.path.expanduser((configparser.get("afl-cov", "afl_cov_path"))))

return config

Expand Down Expand Up @@ -280,31 +287,58 @@ def minimize_sync_dir(config, jobId):

def is64bit():
cmd = 'uname -m'
if 'x86_64' in subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT):
return True
try:
if 'x86_64' in subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT):
return True
except subprocess.CalledProcessError as e:
print e.output
return False

def getnproc():
cmd = 'nproc'
nproc = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
try:
nproc = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError:
return 1
return nproc.rstrip()

def printfile(filename):
cmd = 'cat ' + filename
print subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
# def printfile(filename):
# cmd = 'cat ' + filename
# print subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)

def which(progname):
cmd = 'which ' + progname
try:
path = os.path.expanduser(subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT).rstrip())
except subprocess.CalledProcessError as e:
print e.output
return ''
return os.path.abspath(path)

def run_afl_cov(orthrus_root, jobId, target, params, livemode=False):
target = orthrus_root + "/binaries/coverage/bin/" + \
target + " " + params.replace("@@", "AFL_FILE")

if livemode:
cmd = ["nohup", "afl-cov", "-d", ".orthrus/jobs/" + jobId + \
"/afl-out", "--live", "--lcov-path", "/usr/bin/lcov", "--coverage-cmd", "'" + target + \
"'", "--code-dir", "."]
"/afl-out", "--live", "--lcov-path", which('lcov'), "--genhtml-path", which('genhtml'), "--coverage-cmd", \
"'" + target + "'", "--code-dir", "."]
else:
cmd = ["nohup", "afl-cov", "-d", ".orthrus/jobs/" + jobId + \
"/afl-out", "--lcov-path", "/usr/bin/lcov", "--coverage-cmd", "'" + target + \
"'", "--code-dir", "."]
"/afl-out", "--lcov-path", which('lcov'), "--genhtml-path", which('genhtml'), "--coverage-cmd", \
"'" + target + "'", "--code-dir", "."]
logfile = orthrus_root + "/logs/afl-coverage.log"
p = subprocess.Popen(" ".join(cmd), shell=True, executable="/bin/bash", stdout=open(logfile, 'w'),
stderr=subprocess.STDOUT)
stderr=subprocess.STDOUT)

def validate_inst(config):

if not config['dependencies']:
return False

for program, mode in config['dependencies']:
if mode == 'on' and not which(program):
color_print(bcolors.FAIL, "\t\t\t[-] Could not locate {}. Perhaps modifying the PATH variable helps?".
format(program))
return False
return True
28 changes: 28 additions & 0 deletions tests/test_validation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import unittest
from orthrusutils.orthrusutils import *
from orthrus.commands import *

class TestOrthrusValidate(unittest.TestCase):

description = 'Test harness'
orthrusdirname = '.orthrus'

def test_validate(self):
args = parse_cmdline(self.description, ['validate'])
cmd = OrthrusValidate(args, self.config_pass)
self.assertTrue(cmd.run())

def test_validate_false(self):
args = parse_cmdline(self.description, ['validate'])
cmd = OrthrusValidate(args, self.config_fail)
self.assertFalse(cmd.run())

def setUp(self):
# self.config_pass = {'dependencies': [('clang', 'on'), ('gcc', 'on'), ('afl-fuzz', 'on'),
# ('afl-clang', 'on'), ('afl-clang++', 'on'),
# ('afl-collect', 'on'), ('afl-minimize', 'on'),
# ('afl-multicore', 'on'), ('gdb', 'on'), ('afl-cov', 'on'),
# ('lcov', 'on'), ('genhtml', 'on')]}
self.config_pass = parse_config('../../conf/orthrus.conf')

self.config_fail = {'dependencies': [('joombaloomba', 'on')]}
9 changes: 7 additions & 2 deletions tool/orthrus
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ class OrthrusTool():
self._args = parse_cmdline(description, args, self._create,
self._add, self._remove,
self._start, self._stop, self._show,
self._triage, self._coverage, self._destroy)
self._triage, self._coverage, self._destroy,
self._validate)
self._config = parse_config()

def _create(self, args):
Expand Down Expand Up @@ -50,10 +51,14 @@ class OrthrusTool():
cmd = OrthrusDestroy(args, self._config)
cmd.run()

def _validate(self, args):
cmd = OrthrusValidate(args, self._config)
cmd.run()

def run(self):
sys.stdout.write(self._description + "\n\n")

self._args.func(self._args)
return self._args.func(self._args)

if __name__ == '__main__':
tool = OrthrusTool(DESCRIPTION, sys.argv[1:])
Expand Down

0 comments on commit 3d15209

Please sign in to comment.