def test_has_submissions_in_round(self): r0 = Round.create(num=0) r1 = Round.create(num=1) cs = ChallengeSet.create(name="foo") cbn = ChallengeBinaryNode.create(name="foo1", cs=cs, blob="aaa") our_team = Team.create(name=Team.OUR_NAME) other_team = Team.create(name="enemy") ChallengeSetFielding.create(cs=cs, cbns=[cbn], team=our_team, submission_round=r1) assert_false(cs.has_submissions_in_round(r0)) assert_true(cs.has_submissions_in_round(r1)) ChallengeSetFielding.create(cs=cs, cbns=[cbn], team=other_team, submission_round=r0) assert_false(cs.has_submissions_in_round(r0)) ChallengeSetFielding.create(cs=cs, cbns=[cbn], team=our_team, submission_round=r0) assert_true(cs.has_submissions_in_round(r0))
def should_submit(target_cs): # FIXME: this should be generalized per challenge set introduction # don't submit on the first round if Round.current_round().num == 0: LOG.info("Not submitting on round 0.") return False # don't submit if we haven't submitted an exploit before this round if ExploitSubmissionCable.select().join( Exploit).where((ExploitSubmissionCable.cs == target_cs) & (ExploitSubmissionCable.processed_at != None) & (ExploitSubmissionCable.processed_at <= Round.current_round().created_at) & (Exploit.method != "backdoor")).exists(): LOG.info("There's an exploit that's over a round old!.") return True # don't submit if we haven't found an crash before the last round prev_round = Round.prev_round() if prev_round is not None and Crash.select().where( (Crash.cs == target_cs) & (Crash.created_at <= prev_round.created_at)).exists(): LOG.info("There's a crash that's over two rounds old!") return True LOG.info("Patch conditions not met!") return False
def upload_cbns(args): cs = CS.select().where(CS.name == args.cs) patch_type, _ = PT.get_or_create(name="manual", functionality_risk=1.0, exploitability=0.0) cbns = [] for patched_file in args.patched_files: with open(patched_file) as f: content = f.read() try: cbn = CBN.create(cs=cs, blob=content, name=patched_file, patch_type=patch_type) except peewee.IntegrityError: print "CBN already exists. Fetching." cbn = CBN.select().where(CBN.name == args.patched_file, CBN.cs == cs, CBN.blob == content) cbns.append(cbn) if args.field: ids = IDSRule.get_or_create(cs=target_cs, rules='') CSSubmissionCable.get_or_create(cs=target_cs, cbns=cbns, ids=ids, round=Round.current_round()) if args.eF is not None and args.eT is not None and args.eM is not None and cbn.patch_type is not None: perf_score = { 'score': { 'ref': { 'task_clock': 1.0, 'rss': 1.0, 'flt': 1.0, 'file_size': 1.0 }, 'rep': { 'task_clock': args.eT, 'file_size': args.size_overhead, 'rss': args.eM, 'flt': args.eM, } } } PS.create(cs=cs, perf_score=perf_score, patch_type=cbn.patch_type, has_failed_polls=args.eF != 0, failed_polls=args.eF) if args.pT is not None and args.pM is not None and args.pS is not None: csf.poll_feedback = PF.create(cs=cs, round_id=Round.current_round().id, success=args.pS, time_overhead=args.pT, memory_overhead=args.pM, size_overhead=args.size_overhead) csf.save()
def create_round(args): if not len(args.challenge_sets): fielded = [cs.name for cs in CS.fielded_in_round()] else: fielded = args.challenge_sets new_round = Round.create( num=args.number if args.number is not None else Round.current_round() + 1) for f in fielded: cs = CS.select().where(CS.name == f).get() CSF.create(cs=cs, team=Team.get_our(), available_round=new_round)
def main(args=None): submitters = [POVSubmitter(), CBSubmitter()] while True: wait_for_ambassador() LOG.info("Round #%d", Round.current_round().num) for submitter in submitters: submitter.run(Round.current_round().num) return 0
def test_fielded_in_round(self): now = datetime.now() r1 = Round.create(num=0) r2 = Round.create(num=1) cs1 = ChallengeSet.create(name="foo") cs1.rounds = [r1, r2] cs2 = ChallengeSet.create(name="bar") cs2.rounds = [r1] assert_equals(len(ChallengeSet.fielded_in_round(r1)), 2) assert_in(cs1, ChallengeSet.fielded_in_round(r1)) assert_in(cs2, ChallengeSet.fielded_in_round(r1))
def test_seen_in_round(self): r0 = Round.create(num=0) r1 = Round.create(num=1) cs = ChallengeSet.create(name="foo") cs.seen_in_round(r0) assert_equals(len(cs.rounds), 1) cs.seen_in_round(r0) assert_equals(len(cs.rounds), 1) cs.seen_in_round(r1) assert_equals(len(cs.rounds), 2)
def test_prev_round(self): assert_equals(Round.prev_round(), None) Round.create(num=0) assert_equals(Round.prev_round(), None) r1 = Round.create(num=1) Round.create(num=2) assert_equals(Round.prev_round(), r1)
def test_prev_round_on_new_game(self): Round.create(num=99) assert_equals(Round.prev_round(), None) r0 = Round.create(num=0) assert_equals(Round.prev_round(), None) Round.create(num=1) assert_equals(Round.prev_round(), r0)
def test_get_or_create(self): r = Round.create(num=0) cs = ChallengeSet.create(name="foo") cbn1 = ChallengeBinaryNode.create(name="foo1", cs=cs, blob="aaa1") cbn2 = ChallengeBinaryNode.create(name="foo1", cs=cs, blob="aaa2") ids = IDSRule.create(cs=cs, rules="aaa", sha256="sum") cbl1, crtd1 = CSSubmissionCable.get_or_create(cs=cs, ids=ids, cbns=[cbn1], round=r) assert_true(crtd1) cbl2, crtd2 = CSSubmissionCable.get_or_create(cs=cs, ids=ids, cbns=[cbn1], round=r) assert_false(crtd2) assert_equals(cbl1.id, cbl2.id) cbl3, crtd3 = CSSubmissionCable.get_or_create(cs=cs, ids=ids, cbns=[cbn1, cbn2], round=r) assert_true(crtd3) cbl4, crtd4 = CSSubmissionCable.get_or_create(cs=cs, ids=ids, cbns=[cbn1, cbn2], round=r) assert_false(crtd4) assert_equals(cbl3.id, cbl4.id)
def rotator_submission(target_cs): global NEXT_PATCH_ORDER round_ = Round.current_round() if target_cs.name not in ORDERS or len(ORDERS[target_cs.name]) == 0: ORDERS[target_cs.name] = list(NEXT_PATCH_ORDER) #print target_cs.name, NEXT_PATCH_ORDER NEXT_PATCH_ORDER = NEXT_PATCH_ORDER[1:] + NEXT_PATCH_ORDER[:1] all_patches = target_cs.cbns_by_patch_type() for n in ORDERS[target_cs.name]: pt = PatchType.get(name=n) if pt not in all_patches: continue ORDERS[target_cs.name].remove(n) cbns = all_patches[pt] print "SUBMITTING", target_cs.name, cbns[0].name, cbns[ 0].patch_type.name c, _ = CSSubmissionCable.get_or_create(cs=target_cs, cbns=cbns, ids=cbns[0].ids_rule, round=round_) print "...", c.id break
def main(args=None): """Run the meister.""" if args is None: args = [] brain = ElephantBrain() creators = [DrillerCreator(), RexCreator(), PovFuzzer1Creator(), PovFuzzer2Creator(), ColorGuardCreator(), AFLCreator(), BackdoorSubmitterCreator(), CacheCreator(), RopCacheCreator(), PatcherexCreator(), FunctionIdentifierCreator(), NetworkPollCreatorCreator(), ShowmapSyncCreator(), #PatchPerformanceCreator(), # VM jobs #PollCreatorCreator(), #NetworkPollSanitizerCreator(), #CBTesterCreator(), PovTesterCreator()] scheduler = PriorityScheduler(brain, creators) while True: wait_for_ambassador() LOG.info("Round #%d", Round.current_round().num) scheduler.run() return 0
def _submit_ids_rule(self, cable): if cable.cbns and (cable.cbns[0].ids_rule is not None): ids_rule = cable.cbns[0].ids_rule result = self._cgc.uploadIDS(str(cable.cs.name), str(ids_rule.rules)) submission_round, status = Round.get_or_create_latest( num=result['round']) if status == Round.FIRST_GAME: LOG.error( "Submission in first round of first game (round #%d)", submission_round.num) elif status == Round.NEW_GAME: LOG.info("Submission in first round of new game (round #%d)", submission_round.num) elif status == Round.NEW_ROUND: LOG.info("Submission beginning of new round #%d", submission_round.num) irf, _ = IDSRuleFielding.get_or_create( ids_rule=ids_rule, submission_round=submission_round, team=Team.get_our()) return irf
def test_submitted_and_unsubmitted_patches(self): r0 = Round.create(num=0) team = Team.create(name=Team.OUR_NAME) cs = ChallengeSet.create(name="foo") cs.rounds = [r0] cbn = ChallengeBinaryNode.create(name="cbn", cs=cs, blob="aaa1") patchtype1 = PatchType.create(name="PatchType1", functionality_risk=0, exploitability=0) patchtype2 = PatchType.create(name="PatchType2", functionality_risk=0, exploitability=0) patch1 = ChallengeBinaryNode.create(name="patch1", patch_type=patchtype1, cs=cs, root=cbn, blob="aaa2") patch2 = ChallengeBinaryNode.create(name="patch2", patch_type=patchtype2, cs=cs, root=cbn, blob="aaa3") assert_equals(len(cbn.unsubmitted_patches), 2) assert_in(patch1, cbn.unsubmitted_patches) assert_in(patch2, cbn.unsubmitted_patches) assert_equals(len(cbn.submitted_patches), 0) ChallengeSetFielding.create_or_update_submission(team=team, cbns=[patch1, patch2], round=r0) assert_equals(len(cbn.submitted_patches), 2) assert_equals(len(cbn.unsubmitted_patches), 0)
def test_is_multi_cbn(self): r0 = Round.create(num=0) our_team = Team.create(name=Team.OUR_NAME) # CS single binary cs = ChallengeSet.create(name="single") cs.rounds = [r0] cbn = ChallengeBinaryNode.create(name="foo", cs=cs, blob="aaa1") # CS multi binary cs_multi = ChallengeSet.create(name="multi") cs_multi.rounds = [r0] cbn1 = ChallengeBinaryNode.create(name="foo1", cs=cs_multi, blob="aaa2") cbn2 = ChallengeBinaryNode.create(name="foo2", cs=cs_multi, blob="aaa3") # create fielding entries ChallengeSetFielding.create(cs=cs, cbns=[cbn], team=our_team, available_round=r0) ChallengeSetFielding.create(cs=cs_multi, cbns=[cbn1, cbn2], team=our_team, available_round=r0) assert_false(cs.is_multi_cbn) assert_true(cs_multi.is_multi_cbn)
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 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 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_all(self): r1 = Round.create(num=0) cs = ChallengeSet.create(name="foo") cs.rounds = [r1] cbn1 = ChallengeBinaryNode.create(name="foo", cs=cs, blob="blob1") cbn2 = ChallengeBinaryNode.create(name="bar", cs=cs, blob="blob2") assert_equals(len(ChallengeBinaryNode.all()), 2) assert_equals(ChallengeBinaryNode.all()[0], cbn1) assert_equals(ChallengeBinaryNode.all()[1], cbn2)
def test_at_timestamp(self): round0 = Round.create(num=0, created_at=(NOW + timedelta(seconds=10))) round1 = Round.create(num=1, created_at=(NOW + timedelta(seconds=20))) round2 = Round.create(num=2, created_at=(NOW + timedelta(seconds=30))) assert_is_none(Round.at_timestamp(NOW + timedelta(seconds=5))) assert_equals(Round.at_timestamp(NOW + timedelta(seconds=15)).num, 0) assert_equals(Round.at_timestamp(NOW + timedelta(seconds=25)).num, 1) assert_equals(Round.at_timestamp(NOW + timedelta(seconds=35)).num, 2)
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 test_save(self): r1 = Round.create(num=0) cs = ChallengeSet.create(name="foo") cs.rounds = [r1] cbn = ChallengeBinaryNode.create(name="foo", cs=cs, blob="asdf") job = Job(cbn=cbn, worker='basemodel') updated_at = job.updated_at job.worker = '#aftersave' job.save() assert_greater(job.updated_at, updated_at)
def field_cbns(args): cs = CS.select().where(CS.name == args.cs) # i know i could use one query for this, but then we might get duplicate CBNs and more than we want cbns = [ CBN.get(CBN.cs == cs, CBN.sha256 == sha) for sha in args.patched_shas ] ids, _ = IDSRule.get_or_create(cs=cs, rules='') CSSubmissionCable.get_or_create(cs=cs, cbns=cbns, ids=ids, round=Round.current_round())
def test_unprocessed_submission_cables(self): r = Round.create(num=0) cs = ChallengeSet.create(name="foo") cbn = ChallengeBinaryNode.create(name="foo1", cs=cs, blob="aaa") ids = IDSRule.create(cs=cs, rules="aaa", blob="aaa") cable1 = CSSubmissionCable.create(cs=cs, ids=ids, cbns=[cbn], round=r) cable2 = CSSubmissionCable.create(cs=cs, ids=ids, cbns=[], round=r) assert_equals(len(cs.unprocessed_submission_cables()), 2) assert_equals(cable1, cs.unprocessed_submission_cables()[0]) assert_equals(cable2, cs.unprocessed_submission_cables()[1]) cable1.process() assert_equals(len(cs.unprocessed_submission_cables()), 1)
def _jobs(self): # get all current valid ChallengeSets and schedule them. # passing round id takes care of not generating duplicates in a round for a cs. for curr_cs in self.challenge_sets(): curr_round = Round.current_round() job = PatchPerformanceJob(cs=curr_cs, request_cpu=1, request_memory=2048, payload={'round_id': curr_round.id}) # we want the patch performance to be computed soon for every round. priority = 100 LOG.debug( "Creating PatchPerformanceCreator for CS %s and Round %s ", curr_cs.name, curr_round.num) yield (job, priority)
def test_cbns_original(self): r0 = Round.create(num=0) r1 = Round.create(num=1) our_team = Team.create(name=Team.OUR_NAME) other_team = Team.create(name="opponent") cs = ChallengeSet.create(name="foo") cs.rounds = [r0, r1] cbn = ChallengeBinaryNode.create(name="foo", cs=cs, blob="aaa1") cbn_patched = ChallengeBinaryNode.create(name="foo", cs=cs, patch_type=PatchType.create( name="patch1", functionality_risk=0, exploitability=1, ), blob="aaa2") cbn_other_team = ChallengeBinaryNode.create(name="foo", cs=cs, blob="aaa3") ChallengeSetFielding.create(cs=cs, cbns=[cbn], team=our_team, available_round=r0) ChallengeSetFielding.create(cs=cs, cbns=[cbn_patched], team=our_team, submission_round=r0).save() ChallengeSetFielding.create(cs=cs, cbns=[cbn_other_team], team=other_team, available_round=r0).save() assert_equals(len(cs.cbns_original), 1) assert_in(cbn, cs.cbns_original) assert_not_in(cbn_patched, cs.cbns_original) assert_not_in(cbn_other_team, cs.cbns_original)
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 process_patch_submission(target_cs): """ Process a patch submission request for the provided ChallengeSet :param target_cs: ChallengeSet for which the request needs to be processed. """ round_ = Round.current_round() cbns_to_submit = CBSubmitter.patch_decision_simple(target_cs, round_) if cbns_to_submit is not None: if cbns_to_submit[0].ids_rule is None: ids = IDSRule.create(cs=target_cs, rules='') else: ids = cbns_to_submit[0].ids_rule CSSubmissionCable.get_or_create(cs=target_cs, cbns=cbns_to_submit, ids=ids, round=round_) else: LOG.info("%s - leaving old CBNs in place for", target_cs.name)
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_get_or_create(self): assert_equals(len(ChallengeSet.select()), 0) r1 = Round.create(num=0) cs1, _ = ChallengeSet.get_or_create(name="foo") cs2, _ = ChallengeSet.get_or_create(name="foo") cs3, _ = ChallengeSet.get_or_create(name="bar") for cs in [cs1, cs2, cs3]: cs.rounds = [r1.id] assert_equals(len(ChallengeSet.select()), 2) assert_equals(cs2.id, cs1.id) assert_not_equals(cs3.id, cs1.id) cs3.delete_instance(recursive=True) cs2.delete_instance(recursive=True) cs1.delete_instance(recursive=True) r1.delete_instance(recursive=True) ChallengeSet._meta.database.commit()