def test_unsubmitted_exploits(self): r1 = Round.create(num=0) team = Team.create(name=Team.OUR_NAME) cs = ChallengeSet.create(name="foo") cs.rounds = [r1] job = RexJob.create(cs=cs) pov1 = Exploit.create(cs=cs, job=job, pov_type='type1', exploitation_method='rop', blob="exploit", c_code="exploit it") pov2 = Exploit.create(cs=cs, job=job, pov_type='type2', exploitation_method='rop', blob="exploit", c_code="exploit it") assert_equals(len(cs.unsubmitted_exploits), 2) assert_in(pov1, cs.unsubmitted_exploits) assert_in(pov2, cs.unsubmitted_exploits) pov1.submit_to(team, 10) assert_equals(len(cs.unsubmitted_exploits), 1) assert_not_in(pov1, cs.unsubmitted_exploits) assert_in(pov2, cs.unsubmitted_exploits) pov2.submit_to(team, 10) assert_equals(len(cs.unsubmitted_exploits), 0) assert_not_in(pov1, cs.unsubmitted_exploits) assert_not_in(pov2, cs.unsubmitted_exploits)
def _run(self, job): """Submit a backdoor POV""" LOG.debug("Submitting backdoor for challenge %s", self._cs.name) backdoor_blob = str(patcherex.get_backdoorpov()) Exploit.create(cs=self._cs, job=self._job, pov_type='type1', method='backdoor', blob=backdoor_blob, reliability=0)
def test_most_reliable_exploit(self): r1 = Round.create(num=0) team = Team.create(name=Team.OUR_NAME) cs = ChallengeSet.create(name="foo") cs.rounds = [r1] job1 = RexJob.create(cs=cs) job2 = RexJob.create(cs=cs) job3 = RexJob.create(cs=cs) job4 = RexJob.create(cs=cs) pov1 = Exploit.create(cs=cs, job=job1, pov_type='type1', exploitation_method='rop', blob="exploit1", c_code="exploit it", reliability=0.9) assert_equals(pov1, cs.most_reliable_exploit) pov2 = Exploit.create(cs=cs, job=job2, pov_type='type2', exploitation_method='rop', blob="exploit2", c_code="exploit it", reliability=0.5) assert_equals(pov1, cs.most_reliable_exploit) pov3 = Exploit.create(cs=cs, job=job3, pov_type='type2', exploitation_method='rop', blob="exploit3", c_code="exploit it", reliability=0.9) assert_equals(pov1, cs.most_reliable_exploit) pov4 = Exploit.create(cs=cs, job=job4, pov_type='type2', exploitation_method='rop', blob="exploit4", c_code="exploit it", reliability=1.0) assert_equals(pov4, cs.most_reliable_exploit)
def test_most_recent(self): cs = ChallengeSet.create(name="foo") cs2 = ChallengeSet.create(name="bar") team = Team.create(name="opponent") exploit = Exploit.create(cs=cs, job=RexJob.create(), pov_type="type1", blob="abc", c_code="exploit it") exploit2 = Exploit.create(cs=cs2, job=RexJob.create(), pov_type="type1", blob="def", c_code="delfino") Round.create(num=0) cable = ExploitSubmissionCable.create(team=team, cs=cs, exploit=exploit, throws=10, round=Round.current_round()) cable2 = ExploitSubmissionCable.create(team=team, cs=cs2, exploit=exploit2, throws=10, round=Round.current_round()) assert_equals(len(ExploitSubmissionCable.most_recent()), 2) assert_items_equal(ExploitSubmissionCable.most_recent(), [cable, cable2]) # assert we get back only the most recent exploit r1 = Round.create(num=1) new_exploit = Exploit.create(cs=cs, job=RexJob.create(), pov_type="type2", blob="def", c_code="don't exploit it") new_cable = ExploitSubmissionCable.create(team=team, cs=cs, exploit=new_exploit, throws=10, round=r1) assert_equals(len(ExploitSubmissionCable.most_recent()), 2) assert_items_equal(ExploitSubmissionCable.most_recent(), [new_cable, cable2])
def upload_exploit(args): cs = CS.select().where(CS.name == args.cs) exploit = args.exploit.read() source = args.source.read() if args.source is not None else None # first we have to make a fake job job = Job.create(cs=cs, completed_at=datetime.datetime.now(), worker="garbage") # now actually add the exploit Exploit.create(cs=cs, job=job, blob=exploit, pov_type=args.type, method=args.method, reliability=args.reliability, c_code=source)
def test_has_type1(self): from farnsworth.models.pov_test_result import PovTestResult pov_type = 'type1' cs = ChallengeSet.create(name="foo") job = AFLJob.create(cs=cs) Exploit.create(cs=cs, job=job, pov_type=pov_type, blob=BLOB, c_code="code", reliability=0) assert_false(cs.has_type1) Exploit.create(cs=cs, job=job, pov_type=pov_type, blob=BLOB, c_code="code", reliability=1) assert_true(cs.has_type1) # if not first condition is not met r2 = Round.create(num=2) cs2 = ChallengeSet.create(name="bar") job2 = AFLJob.create(cs=cs2) cbn2 = ChallengeBinaryNode.create(name="bar", cs=cs2, blob="aaa") team2 = Team.create(name=Team.OUR_NAME) exploit2 = Exploit.create(cs=cs2, job=job2, pov_type=pov_type, blob=BLOB, c_code="code", reliability=0) csf2 = ChallengeSetFielding.create_or_update_available(team=team2, cbn=cbn2, round=r2) pov_result2 = PovTestResult.create(exploit=exploit2, cs_fielding=csf2, num_success=0) assert_false(cs2.has_type1) pov_result2.num_success = 10 pov_result2.save() assert_true(cs2.has_type1)
def test_pov_type(self): cs = ChallengeSet.create(name="foo") job = AFLJob.create(cs=cs) exploit = Exploit.create(cs=cs, job=job, pov_type="type1", blob="exploit", c_code="exploit it") assert_equals(exploit.pov_type, "type1") def invalid_pov_type(): Exploit.create(cs=cs, job=job, pov_type="bar") assert_raises(Exception, invalid_pov_type)
def _save_exploit(self, exploit, crashing_test): LOG.info("Adding %s type %d", exploit.method_name, exploit.cgc_type) type_name = 'type%d' % exploit.cgc_type exploit = Exploit.create(cs=self._cs, job=self._job, pov_type=type_name, method=exploit.method_name, blob=exploit.dump_binary(), c_code=exploit.dump_c(), crash=crashing_test) return exploit
def test_submit_to(self): r0 = Round.create(num=0) r1 = Round.create(num=1) cs = ChallengeSet.create(name="foo") cs.rounds = [r1.id] job = AFLJob.create(cs=cs) exploit = Exploit.create(job=job, cs=cs, pov_type="type1", blob=BLOB, c_code="exploit it") team = Team.create(name="opponent") assert_equals(len(exploit.fieldings), 0) ef = exploit.submit_to(team=team, throws=10) assert_equals(len(exploit.fieldings), 1) assert_equals(ef.submission_round, Round.current_round()) ef = exploit.submit_to(team=team, throws=5, round=r0) assert_equals(len(exploit.fieldings), 2) assert_equals(ef.submission_round, r0)
def test_process_and_unprocessed(self): cs = ChallengeSet.create(name="foo") team = Team.create(name="opponent") exploit = Exploit.create(cs=cs, job=RexJob.create(), pov_type="type1", blob="abc", c_code="exploit it") Round.create(num=0) cable = ExploitSubmissionCable.create(team=team, cs=cs, exploit=exploit, throws=10, round=Round.current_round()) assert_equals(len(ExploitSubmissionCable.unprocessed()), 1) cable.process() assert_equals(len(ExploitSubmissionCable.unprocessed()), 0)
def _run(self, job): """Run colorguard on a testcase in an attempt to find leaks.""" if self._cs.is_multi_cbn: LOG.warning( "Colorguard scheduled on multicb, this is not yet supported") return LOG.debug("Invoking colorguard on challenge %s, job %s", self._cs.name, job.id) self._colorguard = colorguard.ColorGuard(self._cbn.path, str(job.input_blob)) exploit = self._colorguard.attempt_exploit() if exploit is not None: LOG.info("Job %d's testcase causes a leak of the flag page", job.id) e = Exploit.create(cs=self._cs, job=self._job, pov_type="type2", method=exploit.method_name, blob=exploit.dump_binary(), c_code=exploit.dump_c()) e.reliability = self._get_pov_score(exploit) LOG.info("Binary POV passed %d / 10 simulation tests", e.reliability * 10) e.save() else: LOG.debug("Unable to find leak or generate exploit for testcase") if not job.payload['crash']: LOG.debug("Marking test %s as by colorguard traced", job.payload['id']) t = Test.get(id=job.payload['id']) t.colorguard_traced = True t.save()
def _fixup_exploit(exploit, register): """ :param exploit: the peewee exploit object (should be type 1 only) :param register: the register we are actually setting :return: the new exploit object or None if we shouldn't create one """ # make compilerex executable bin_path = os.path.join(os.path.dirname(compilerex.__file__), "../bin") for f in os.listdir(bin_path): os.chmod(os.path.join(bin_path, f), 0777) os.chmod(os.path.join(bin_path, f), 0777) c_code = str(exploit.c_code) if c_code.startswith("//FIXED"): return None fixed_lines = ["//FIXED"] for line in c_code.split("\n"): # fix the line which sets the regnum if "enum register_t regnum" in line: fixed_lines.append(" enum register_t regnum = %s;" % register) else: fixed_lines.append(line) new_c = "\n".join(fixed_lines) compiled_blob = compilerex.compile_from_string(new_c) # we keep the reliability at 0.0, however the tester needs to make sure to mark # this exploit good for this fielding e = Exploit.create(cs=exploit.cs, job=exploit.job, pov_type='type1', method=exploit.method, c_code=new_c, blob=compiled_blob, crash=exploit.crash) e.save() return e
def invalid_pov_type(): Exploit.create(cs=cs, job=job, pov_type="bar")
def try_drilling(name, get_crashes): # set up the node cs = ChallengeSet.get_or_create(name=name.split('_')[0]) cbn = ChallengeBinaryNode.get_create(name=name, cs=cs) cbn.root = cbn cbn.save() Exploit.delete().where(Exploit.cbn == cbn).execute() if not cbn.crashes or get_crashes: # Delete the testcases Test.delete().where(Test.cbn == cbn).execute() Crash.delete().where(Crash.cbn == cbn).execute() assert len(cbn.tests) == 0 afl_job = AFLJob.create(cbn=cbn, limit_cpu=4, limit_memory=1, limit_time=80) afl_thread = AFLThread(afl_job) afl_thread.start() for _ in range(10): if len(cbn.tests) == 2: break time.sleep(1) assert len(cbn.tests) == 2 assert len(afl_thread._worker._seen) == 2 assert len(cbn.crashes) == 0 # schedule driller for i in cbn.tests: dj = DrillerJob.create(payload=i, cbn=cbn, limit_cpu=1, limit_memory=10) dw = worker.DrillerWorker() dw.run(dj) assert len(dj.tests) > 0 #pylint:disable=no-member for _ in range(80): if len(cbn.crashes) > 0: break time.sleep(1) assert len(afl_thread._worker._seen) > 2 assert len(cbn.tests) > 2 assert len(cbn.crashes) > 0 afl_thread.join() sorted_crashes = sorted(cbn.crashes, key=lambda x: -len(str(x.blob))) print "Chose crash of length %d" % len(sorted_crashes[0].blob) rj = RexJob.create(payload=sorted_crashes[0], cbn=cbn, limit_cpu=1, limit_memory=10) rw = worker.RexWorker() rw.run(rj) assert len(cbn.exploits) == 2
crash = job.input_crash crash_payload = str(crash.blob) time_limit = job.limit_time-10 l.info("Pov fuzzer 1 beginning to exploit crash %d for challenge %s", crash.id, job.cs.name) try: pov_fuzzer = pov_fuzzing.Type1CrashFuzzer(cbnp, crash=crash_payload, ids_rules=ids_rules, time_limit=time_limit) crashing_test = job.input_crash if pov_fuzzer.exploitable(): e = Exploit.create(cs=job.cs, job=job, pov_type='type1', method="fuzzer", c_code=pov_fuzzer.dump_c(), blob=pov_fuzzer.dump_binary(), crash=crashing_test) e.reliability = _get_pov_score(pov_fuzzer) # store a low reliability for the targeted ones if cs_fielding_id is not None: # store the pov test results num_success = round(e.reliability*10) PovTestResult.create(exploit=e, cs_fielding_id=cs_fielding_id, ids_fielding_id=ids_fielding_id, num_success=num_success) e.reliability = 0.01 * e.reliability e.save() l.info("crash was able to be exploited") else: