Exemplo n.º 1
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))
Exemplo n.º 2
0
    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()
Exemplo n.º 3
0
    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_)
Exemplo n.º 4
0
    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
Exemplo n.º 5
0
    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)
Exemplo n.º 6
0
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)
Exemplo n.º 7
0
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 ""
Exemplo n.º 8
0
    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)
Exemplo n.º 9
0
    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()
Exemplo n.º 10
0
    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)
Exemplo n.º 11
0
def fieldings(args):
    for cs in CSF.select().join(CS.fielded_in_round(round_=args.round)).where(
            CSF.submission_round):
        pass
Exemplo n.º 12
0
    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