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 run(self): """A run() method. Happy now pylint?""" cgc_polls = self._get_feedback('poll') Feedback.update_or_create(self._round, polls=cgc_polls, povs=self._get_feedback('pov'), cbs=self._get_feedback('cb')) fielded = { c.name: c for c in ChallengeSet.fielded_in_round(self._round) } for c in cgc_polls: cs = fielded[c['csid']] fieldings = cs.fieldings.where( (ChallengeSetFielding.available_round == self._round) & (ChallengeSetFielding.team == Team.get_our())) if fieldings: fielding = fieldings.get() if fielding.poll_feedback is None: fnct, perf = c['functionality'], c['performance'] pf = PollFeedback.create( cs=cs, round=self._round, success=float(fnct['success']) / 100.0, timeout=float(fnct['timeout']) / 100.0, connect=float(fnct['connect']) / 100.0, function=float(fnct['function']) / 100.0, time_overhead=float(perf['time']) / 100.0 - 1, memory_overhead=float(perf['memory']) / 100.0 - 1) fielding.poll_feedback = pf fielding.save()
def challenge_sets(self, round_=None): """Return the list of challenge sets that are active in a round. :keyword round_: The round number for which the binaries should be returned (default: current round). """ return ChallengeSet.fielded_in_round(round_)
def cbns(self, round_=None): """Return the list of binaries that are active in a round. :keyword round_: The round instance for which the binaries should be returned (default: current round). """ for cs in ChallengeSet.fielded_in_round(round_): for cbn in cs.cbns_original: LOG.debug("Found cbid: %s", cbn.name) yield cbn
def run(self, current_round=None, random_submit=False): # pylint:disable=no-self-use,unused-argument return if current_round == 0: return # As ambassador will take care of actually submitting the binary. for cs in ChallengeSet.fielded_in_round(): #if not self.should_submit(cs): # continue CBSubmitter.process_patch_submission(cs)
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 list_patches(args): wanted_fields = (CBN.name, CBN.size, CBN.sha256, CBN.patch_type, CBN.is_blacklisted) q = CBN.select(*wanted_fields) if args.cs is not None: cs = CS.select().where(CS.name == args.cs) for patch in q.where(CBN.cs == cs): print format_patch(patch) else: for cs in CS.fielded_in_round(): print "CS {}:".format(cs.name) for patch in q.where(CBN.cs == cs): print format_patch(patch) print ""
def _jobs(self): for cs in ChallengeSet.fielded_in_round(): # For each of patch types create Tester Jobs for patch_type in cs.cbns_by_patch_type(): # Get only polls for which scores have not been computed. for poll in CBPollPerformance.get_untested_polls( cs, patch_type): curr_cb_tester_job = CBTesterJob(cs=poll.cs, payload={ 'poll_id': poll.id, 'cs_id': poll.cs.id, 'patch_type': patch_type.name }, request_cpu=10, request_memory=4096 * 2) num_tested_polls = CBPollPerformance.num_tested_polls( poll.cs, patch_type) priority = 100 if num_tested_polls < CBTesterCreator.MIN_TESTED_POLLS else 50 LOG.debug("Yielding CBTesterJob for poll %s (patched %s)", poll.id, patch_type.name) yield (curr_cb_tester_job, priority) # Create jobs for unpatched binary for untested polls for poll in CBPollPerformance.get_untested_polls(cs, None): # Create job for unpatched binary curr_cb_tester_job = CBTesterJob(cs=poll.cs, payload={ 'poll_id': poll.id, 'cs_id': poll.cs.id }, request_cpu=10, request_memory=4096 * 2) # get number of successful polls tested against unpatched binary num_tested_polls = CBPollPerformance.num_tested_polls( poll.cs, None) priority = 100 if num_tested_polls < CBTesterCreator.MIN_TESTED_POLLS else 50 LOG.debug("Yielding CBTesterJob for poll %s (unpatched)", poll.id) yield (curr_cb_tester_job, priority)
def run(self): """Amazing docstring""" fielded_cses = ChallengeSet.fielded_in_round() most_recent = ExploitSubmissionCable.most_recent() for cable in most_recent.where( ExploitSubmissionCable.cs << fielded_cses): pov = cable.exploit LOG.info("Submitting POV %d for challenge %s", pov.id, pov.cs.name) try: result = self._cgc.uploadPOV(str(pov.cs.name), str(cable.team.name), str(cable.throws), str(pov.blob)) LOG.debug("Submitted POV! Response: %s", result) 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) pov.submit_to(team=cable.team, throws=cable.throws, round=submission_round) except TiError as err: LOG.error("POV Submission error: %s", err.message) cable.process()
def _jobs(self): # iterate only for currently active ChallengeSets for curr_cs in ChallengeSet.fielded_in_round(): for curr_test in Test.select().where((Test.poll_created == False) & (Test.cs == curr_cs)): job = PollCreatorJob(cs=curr_test.cs, payload={'test_id': curr_test.id}, request_cpu=10, request_memory=4096*2) priority = 20 # Set high priority only, if there are less polls num_poll_available = ValidPoll.select() \ .where(ValidPoll.cs == curr_test.cs) \ .count() if num_poll_available < PollCreatorCreator.SAFE_NUM_POLLS: priority = ((PollCreatorCreator.SAFE_NUM_POLLS - num_poll_available) * 100) / \ (PollCreatorCreator.SAFE_NUM_POLLS - PollCreatorCreator.RESONABLE_NUM_POLLS) # sanity, bound priority values if priority < 0: priority = 0 if priority > 100: priority = 100 LOG.debug("Creating PollJob for cs %s with test %s ", curr_test.cs.name, curr_test.id) yield (job, priority)
def fieldings(args): for cs in CSF.select().join(CS.fielded_in_round(round_=args.round)).where( CSF.submission_round): pass
def patch_decision_simple(target_cs, round_): """ Determines the CBNs to submit. Returns None if no submission should be made. We only submit 1 patch type per CS. """ LOG.info("CB SUBMISSION START: %s (round %d)", target_cs.name, round_.num) # make sure that this binary is not new this round if not (target_cs.id in [cs.id for cs in ChallengeSet.fielded_in_round(round_)] and Round.prev_round() is not None and target_cs.id in [ cs.id for cs in ChallengeSet.fielded_in_round(Round.prev_round()) ]): LOG.info("%s - not patching in the first round", target_cs.name) return current_fielding = ChallengeSetFielding.latest(cs=target_cs, team=Team.get_our(), round=round_) # Fielding should always be not None, or we are in a # race condition and do not want to do anything right # now, we will be run again, at which point fieldings # should be set. if current_fielding is None: LOG.warning( "%s - hit the race condition for latest fielding being None", target_cs.name) return LOG.info("%s - current patch type: %s", target_cs.name, (current_fielding.cbns[0].patch_type.name if current_fielding.cbns[0].patch_type is not None else "None")) # if we just submitted, wait a round before making any decisions if current_fielding.poll_feedback is not None and ( current_fielding.poll_feedback.timeout + current_fielding.poll_feedback.success + current_fielding.poll_feedback.function + current_fielding.poll_feedback.connect == 0): LOG.warning("%s - skipping 'downed' round", target_cs.name) return # if we don't have any patches ready, let's wait all_patches = target_cs.cbns_by_patch_type() if len(all_patches) == 0: return best_patch_type = sorted(all_patches.keys(), key=lambda pt: pt.exploitability)[0] has_feedback = { k: v for k, v in all_patches.iteritems() if len(v[0].poll_feedbacks) > 0 } pull_back = any(cbns[0].min_cb_score is not None and cbns[0].min_cb_score < MIN_CB_SCORE for cbns in all_patches.values()) for k, v in has_feedback.items(): LOG.info("%s - minimum score of patch %s is %s", target_cs.name, k.name, v[0].min_cb_score) if pull_back: LOG.info("%s - pulling back the patch :-(", target_cs.name) new_cbns = target_cs.cbns_original else: # if we've already patched, and we're not pulling back, forget about it if best_patch_type.name != 'manual' and not CBSubmitter.same_cbns( current_fielding.cbns, target_cs.cbns_original): LOG.info("%s - already patched -- aborting!", target_cs.name) return LOG.info("%s - chose %s patch type!", target_cs.name, best_patch_type.name) new_cbns = all_patches[best_patch_type] # Check if we have submitted in this round? submitted_fielding = ChallengeSetFielding.submissions( cs=target_cs, team=Team.get_our(), round=round_) if submitted_fielding is not None: LOG.info("%s - we have an earlier submission this round...", target_cs.name) prior_submission = list(submitted_fielding.cbns) else: LOG.info("%s - submitting for the first time this round...", target_cs.name) prior_submission = list(current_fielding.cbns) # if we submitted an exploit for the first time this round, let's not patch if not pull_back and ExploitSubmissionCable.select( ).join(Exploit).where( (ExploitSubmissionCable.cs == target_cs) & (ExploitSubmissionCable.processed_at != None) & (ExploitSubmissionCable.processed_at >= round_.created_at) & (Exploit.method != "backdoor")).exists( ) and not ExploitSubmissionCable.select().join(Exploit).where( (ExploitSubmissionCable.cs == target_cs) & (ExploitSubmissionCable.processed_at != None) & (ExploitSubmissionCable.processed_at < round_.created_at) & (Exploit.method != "backdoor")).exists(): LOG.info( "%s - not submitting because we first found an exploit last round", target_cs.name) new_cbns = list(current_fielding.cbns) if CBSubmitter.same_cbns(new_cbns, prior_submission): LOG.info("%s - nothing to do, this would be a resubmission", target_cs.name) return else: LOG.info("%s - we have not yet submitted these CBNs this round!", target_cs.name) return new_cbns