Beispiel #1
0
 def _challenge_event(cls, old, new):
     context = Context(elevated=True)
     if old is None:
         return
     if new is None:
         models.ChallengeClear.objects.filter(challenge=old['pk']).delete()
         models.FlagClear.objects.filter(challenge=old['pk']).delete()
         models.ChallengeFirst.objects.filter(challenge=old['pk']).delete()
         models.FlagFirst.objects.filter(challenge=old['pk']).delete()
         if old['enabled']:
             cls._regen_score()
         return
     if len(new['flags']) != len(old['flags']):
         models.FlagClear.objects.filter(challenge=old['pk'],
                                         flag__gte=len(
                                             new['flags'])).delete()
         cls._regen_challenge_clear(Challenge.get(context, old['pk']))
         models.ChallengeFirst.objects.filter(challenge=old['pk']).delete()
         models.FlagFirst.objects.filter(challenge=old['pk']).delete()
         cls._refill_first()
     if not old['enabled'] and not new['enabled']:
         return
     if new['enabled'] != old['enabled']:
         cls._regen_score()
         return
     if new['category'] != old['category']:
         cls._regen_score()
         return
     old_flag_scores = [i['score'] for i in old['flags']]
     new_flag_scores = [i['score'] for i in new['flags']]
     if new_flag_scores != old_flag_scores:
         cls._regen_score()
         return
Beispiel #2
0
 def regen_all(cls, context):
     """重算所有缓存,只有通过命令行提权后才能调用"""
     User.test_permission(context)
     for obj in models.Submission.objects.all():
         try:
             obj.group = User.get(context, obj.user).group
             obj.save()
         except NotFound:
             pass
     for obj in models.FlagClear.objects.all():
         try:
             user = User.get(context, obj.user)
             obj.group = user.group
             challenge = Challenge.get(context, obj.challenge)
             if obj.flag not in range(len(challenge.flags)):
                 raise NotFound
             obj.save()
         except NotFound:
             obj.delete()
     for challenge in Challenge.get_all(context):
         cls._regen_challenge_clear(challenge)
     models.ChallengeFirst.objects.all().delete()
     models.FlagFirst.objects.all().delete()
     cls._refill_first()
     cls._regen_score()
Beispiel #3
0
 def submit(cls, context, user, challenge, text):
     if context.user.pk != user:
         User.test_permission(context)
     if len(text) > 200:
         raise WrongFormat('Flag 不应超过 200 个字符')
     user = User.get(context, user)
     challenge = Challenge.get(context, challenge)
     try:
         latest = (models.Submission.objects.filter(
             user=user.pk, challenge=challenge.pk).latest('time'))
     except models.Submission.DoesNotExist:
         pass
     else:
         if latest.time + timedelta(seconds=10) > context.time:
             raise SlowDown('提交过于频繁,请 10 秒后再试')
     obj = models.Submission.objects.create(
         user=user.pk,
         group=user.group,
         challenge=challenge.pk,
         text=text,
         time=context.time,
     )
     matches, violations = challenge.check_flag_with_violations(text)
     queryset = models.FlagClear.objects.filter(user=user.pk,
                                                challenge=challenge.pk)
     flags = {i.flag for i in queryset}
     match_flags = {i['index'] for i in matches}
     for flag in match_flags - flags:
         models.FlagClear.objects.create(
             submission=obj,
             user=user.pk,
             group=user.group,
             challenge=challenge.pk,
             flag=flag,
             time=context.time,
         )
         if user.group not in User.no_score_groups:
             models.FlagFirst.objects.get_or_create(
                 challenge=challenge.pk,
                 flag=flag,
                 group=None,
                 defaults={
                     'user': user.pk,
                     'time': context.time
                 },
             )
         models.FlagFirst.objects.get_or_create(
             challenge=challenge.pk,
             flag=flag,
             group=user.group,
             defaults={
                 'user': user.pk,
                 'time': context.time
             },
         )
     for f, u in violations:
         models.FlagViolation.objects.create(
             submission=obj,
             violation_flag=f['index'],
             violation_user=u,
         )
     if match_flags - flags:
         if (flags | match_flags).issuperset(range(len(challenge.flags))):
             models.ChallengeClear.objects.create(
                 user=user.pk,
                 group=user.group,
                 challenge=challenge.pk,
                 time=context.time,
             )
             if user.group not in User.no_score_groups:
                 models.ChallengeFirst.objects.get_or_create(
                     challenge=challenge.pk,
                     group=None,
                     defaults={
                         'user': user.pk,
                         'time': context.time
                     },
                 )
             models.ChallengeFirst.objects.get_or_create(
                 challenge=challenge.pk,
                 group=user.group,
                 defaults={
                     'user': user.pk,
                     'time': context.time
                 },
             )
         score = sum(i['score'] for i in matches if i['index'] not in flags)
         cls._add_score(user.pk, user.group, context.time, score,
                        challenge.category)
     return matches
Beispiel #4
0
 def do_delete(self, context, pk, **kwargs):
     return Challenge.get(context, pk).delete()
Beispiel #5
0
 def do_save(self, context, pk, **kwargs):
     kwargs = {k: kwargs[k] for k in kwargs if k in Challenge.update_fields}
     if pk is None:
         return Challenge.create(context, **kwargs).json
     else:
         return Challenge.get(context, pk).update(**kwargs)
Beispiel #6
0
    def handle(self, fake_complex_challenges, fake_simple_challenges,
               fake_users, fake_submissions, game_started_seconds,
               **options):
        root = User.create(
            Context(elevated=True),
            group='other',
            nickname='root',
        ).user
        root.is_staff = True
        root.is_superuser = True
        root.save()
        root.refresh_from_db()
        Account.objects.create(provider='debug', identity='root', user=root)

        c1 = Challenge.create(
            Context(root),
            name='签到题',
            category='checkin',
            detail='签到题描述',
            url='https://example.com/{token}',
            prompt='flag{hackergame}',
            index=-100,
            enabled=True,
            flags=[{
                'name': '',
                'score': 10,
                'type': 'text',
                'flag': 'flag{hackergame}',
            }],
        )
        Submission.submit(Context(root), root.pk, c1.pk, 'flag{hackergame}')

        for i in range(1, fake_complex_challenges + 1):
            Challenge.create(
                Context(root),
                name=f'复杂题 {i}',
                category='complex',
                detail='<code>flag{FLAG_INDEX}</code> 或 '
                       '<code>flag{FLAG_INDEX:USER_ID}</code>',
                url='',
                prompt='flag{...}',
                index=random.randrange(100),
                enabled=random.choice((False, True, True, True, True)),
                flags=[{
                    'name': f'flag {j}',
                    'score': random.randrange(100),
                    'type': ('expr', 'text')[j % 2],
                    'flag': ("f'flag{{%s:{token.partition(\":\")[0]}}}'" % j,
                             f'flag{{{j}}}')[j % 2],
                } for j in range(random.randrange(1, 4))],
            )

        for i in range(1, fake_simple_challenges + 1):
            Challenge.create(
                Context(root),
                name=f'简单题 {i}',
                category='simple',
                detail='',
                url='',
                prompt=('flag{0}', 'flag{0:USER_ID}')[i % 2],
                index=random.randrange(100),
                enabled=random.choice((False, True, True, True, True)),
                flags=[{
                    'name': '',
                    'score': random.randrange(100),
                    'type': ('text', 'expr')[i % 2],
                    'flag': ('flag{0}',
                             "'flag{0:'+token.partition(':')[0]+'}'")[i % 2],
                }],
            )

        terms = Terms.create(Context(root), name='条款', content='1 2 3 ...',
                             enabled=True)

        now = timezone.now()
        timestamps = []
        for i in range(fake_submissions):
            delta = random.randrange(game_started_seconds)
            timestamps.append(now - timezone.timedelta(seconds=delta))
        timestamps.sort()

        Trigger.create(Context(root), time=min(timestamps), state=True)

        groups = list(set(User.groups.keys()) - {'staff', 'banned'})
        for i in range(fake_users):
            print('user', i, end='\r')
            u = User.create(
                Context(elevated=True),
                group=random.choice(groups),
                nickname='用户 ' * 8 + str(i),
                name='姓名',
                sno='PB11111111',
                tel='123456789',
                email='*****@*****.**',
                gender=random.choice(('female', 'male')),
                qq='12345',
                school='foo',
                grade='1',
            )
            Terms.get(Context(u.user), terms.pk).agree(u.pk)
            Account.objects.create(provider='debug', identity=f'{i}',
                                   user=u.user)

        users = [i.pk for i in User.get_all(Context(root))]
        challenges = [i.pk for i in Challenge.get_all(Context(root))]

        for i in range(fake_submissions):
            print('submission', i, end='\r')
            try:
                u = random.choice(users)
                c = random.choice(challenges)
                fs = len(Challenge.get(Context(root), c).flags)
                Submission.submit(
                    Context(
                        User.get(Context(root), u).user,
                        timestamps[i]
                    ), u, c, f'flag{{{random.choice(range(fs))}:{u}}}'
                )
                Submission.submit(
                    Context(
                        User.get(Context(root), u).user,
                        timestamps[i] + timezone.timedelta(seconds=20)
                    ), u, c, f'flag{{{random.choice(range(fs))}}}'
                )
            except (NotFound, SlowDown):
                pass

        Challenge.create(
            Context(root),
            name='难题',
            category='hard',
            detail='难题描述',
            url='https://example.com/{token}',
            prompt='flag{hackergame}',
            index=100,
            enabled=True,
            flags=[{
                'name': '',
                'score': 100,
                'type': 'text',
                'flag': 'flag{hackergame}',
            }],
        )