add flare-on 2020
This commit is contained in:
5
2020/flare-on/1_-_fidler/Message.txt
Normal file
5
2020/flare-on/1_-_fidler/Message.txt
Normal file
@ -0,0 +1,5 @@
|
||||
Welcome to the Seventh Flare-On Challenge!
|
||||
|
||||
This is a simple game. Win it by any means necessary and the victory screen will reveal the flag. Enter the flag here on this site to score and move on to the next level.
|
||||
|
||||
This challenge is written in Python and is distributed as a runnable EXE and matching source code for your convenience. You can run the source code directly on any Python platform with PyGame if you would prefer.
|
160
2020/flare-on/1_-_fidler/controls.py
Normal file
160
2020/flare-on/1_-_fidler/controls.py
Normal file
@ -0,0 +1,160 @@
|
||||
import pygame as pg
|
||||
COLOR_INACTIVE = pg.Color('lightskyblue3')
|
||||
COLOR_ACTIVE = pg.Color('dodgerblue2')
|
||||
DEFAULT_FONT = pg.font.Font('fonts/arial.ttf', 22)
|
||||
|
||||
class Label:
|
||||
def __init__(self, x, y, text='', color=None, font=None):
|
||||
self.color = color if color else COLOR_INACTIVE
|
||||
self.coords = (x, y)
|
||||
self.text = text
|
||||
self.font = font if font else DEFAULT_FONT
|
||||
self.txt_surface = self.font.render(text, True, self.color)
|
||||
|
||||
def handle_event(self, event):
|
||||
return
|
||||
|
||||
def update(self):
|
||||
return
|
||||
|
||||
def draw(self, screen):
|
||||
# Blit the text.
|
||||
screen.blit(self.txt_surface, self.coords)
|
||||
|
||||
def change_text(self, text):
|
||||
self.txt_surface = self.font.render(text, True, self.color)
|
||||
|
||||
class InputBox:
|
||||
def __init__(self, x, y, w, h, text=''):
|
||||
self.rect = pg.Rect(x, y, w, h)
|
||||
self.color = COLOR_INACTIVE
|
||||
self.text = text
|
||||
self.txt_surface = DEFAULT_FONT.render(text, True, self.color)
|
||||
self.active = False
|
||||
self.submitted = False
|
||||
|
||||
def handle_event(self, event):
|
||||
if event.type == pg.MOUSEBUTTONDOWN:
|
||||
# If the user clicked on the input_box rect.
|
||||
if self.rect.collidepoint(event.pos):
|
||||
# Set active control or not, depending on click location.
|
||||
self.active = True
|
||||
else:
|
||||
self.active = False
|
||||
# Change the current color of the input box.
|
||||
if event.type == pg.KEYDOWN:
|
||||
if self.active:
|
||||
if event.key == pg.K_RETURN:
|
||||
self.submitted = True
|
||||
elif event.key == pg.K_BACKSPACE:
|
||||
self.text = self.text[:-1]
|
||||
else:
|
||||
self.text += event.unicode
|
||||
# Re-render the text.
|
||||
self.txt_surface = DEFAULT_FONT.render(self.text, True, self.color)
|
||||
|
||||
def update(self):
|
||||
# Change the current color of the input box.
|
||||
self.color = COLOR_ACTIVE if self.active else COLOR_INACTIVE
|
||||
|
||||
def draw(self, screen):
|
||||
# Blit the text.
|
||||
displayable_txt_surface = self.txt_surface.subsurface(
|
||||
(0,
|
||||
0,
|
||||
min(self.rect.w-10, self.txt_surface.get_width()),
|
||||
self.txt_surface.get_height())
|
||||
)
|
||||
screen.blit(displayable_txt_surface, (self.rect.x+5, self.rect.y+5))
|
||||
# Blit the rect.
|
||||
pg.draw.rect(screen, self.color, self.rect, 2)
|
||||
|
||||
class Button:
|
||||
def __init__(self, x, y, w, h, text='', color=COLOR_ACTIVE, font=DEFAULT_FONT, callback=None):
|
||||
self.rect = pg.Rect(x, y, w, h)
|
||||
self.text = text
|
||||
self.color = color
|
||||
self.font = font
|
||||
self.txt_surface = font.render(text, True, self.color)
|
||||
self.down_img = pg.transform.scale2x(pg.image.load('img/btndown.png'))
|
||||
self.up_img = pg.transform.scale2x(pg.image.load('img/btnup.png'))
|
||||
self.pressed = False
|
||||
self.callback = callback
|
||||
|
||||
def handle_event(self, event):
|
||||
if event.type == pg.MOUSEBUTTONDOWN:
|
||||
# If the user clicked on the input_box rect.
|
||||
if self.rect.collidepoint(event.pos):
|
||||
self.pressed = True
|
||||
if self.callback:
|
||||
self.callback()
|
||||
|
||||
elif event.type == pg.MOUSEBUTTONUP:
|
||||
if self.rect.collidepoint(event.pos):
|
||||
self.pressed = False
|
||||
elif event.type == pg.MOUSEMOTION:
|
||||
if self.pressed and not self.rect.collidepoint(event.pos):
|
||||
self.pressed = False
|
||||
|
||||
def update(self):
|
||||
return
|
||||
|
||||
def draw(self, screen):
|
||||
# Blit the button image
|
||||
btn_image = self.down_img if self.pressed else self.up_img
|
||||
screen.blit(btn_image, self.rect)
|
||||
width = self.txt_surface.get_width()
|
||||
height = self.txt_surface.get_height()
|
||||
text_offset_x = (self.rect.w - width) / 2
|
||||
text_offset_y = (self.rect.h - height) / 2
|
||||
text_x = self.rect.x + text_offset_x
|
||||
text_y = self.rect.y + text_offset_y
|
||||
# Center button text on button surface
|
||||
screen.blit(self.txt_surface, (text_x, text_y))
|
||||
|
||||
class ImageButton:
|
||||
def __init__(self, x, y, w, h, up_img, down_img=None, callback=None):
|
||||
self.rect = pg.Rect(x, y, w, h)
|
||||
self.down_img = down_img if down_img else up_img
|
||||
self.up_img = up_img
|
||||
self.pressed = False
|
||||
self.callback = callback
|
||||
|
||||
def handle_event(self, event):
|
||||
if event.type == pg.MOUSEBUTTONDOWN:
|
||||
# If the user clicked on the input_box rect.
|
||||
if self.rect.collidepoint(event.pos):
|
||||
self.pressed = True
|
||||
if self.callback:
|
||||
self.callback()
|
||||
|
||||
elif event.type == pg.MOUSEBUTTONUP:
|
||||
if self.rect.collidepoint(event.pos):
|
||||
self.pressed = False
|
||||
elif event.type == pg.MOUSEMOTION:
|
||||
if self.pressed and not self.rect.collidepoint(event.pos):
|
||||
self.pressed = False
|
||||
|
||||
def update(self):
|
||||
return
|
||||
|
||||
def draw(self, screen):
|
||||
# Blit the button image
|
||||
btn_image = self.down_img if self.pressed else self.up_img
|
||||
screen.blit(btn_image, self.rect)
|
||||
|
||||
class Image:
|
||||
def __init__(self, x, y, img):
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.img = img
|
||||
|
||||
def handle_event(self, event):
|
||||
return
|
||||
|
||||
def update(self):
|
||||
return
|
||||
|
||||
def draw(self, screen):
|
||||
screen.blit(self.img, (self.x, self.y))
|
||||
return
|
BIN
2020/flare-on/1_-_fidler/fidler.exe
Normal file
BIN
2020/flare-on/1_-_fidler/fidler.exe
Normal file
Binary file not shown.
252
2020/flare-on/1_-_fidler/fidler.py
Normal file
252
2020/flare-on/1_-_fidler/fidler.py
Normal file
@ -0,0 +1,252 @@
|
||||
import pygame as pg
|
||||
pg.init()
|
||||
from controls import *
|
||||
|
||||
current_coins = 0
|
||||
current_autoclickers = 0
|
||||
buying = False
|
||||
|
||||
def password_check(input):
|
||||
altered_key = 'hiptu'
|
||||
key = ''.join([chr(ord(x) - 1) for x in altered_key])
|
||||
return input == key
|
||||
|
||||
def password_screen():
|
||||
screen = pg.display.set_mode((640, 160))
|
||||
clock = pg.time.Clock()
|
||||
heading = Label(20, 20, 'This program is protected by Flare-On TURBO Nuke v55.7')
|
||||
prompt = Label(20, 105, 'Password:')
|
||||
input_box = InputBox(140, 100, 470, 32)
|
||||
controls = [heading, prompt, input_box]
|
||||
done = False
|
||||
input_box.active = True
|
||||
|
||||
while not done:
|
||||
for event in pg.event.get():
|
||||
if event.type == pg.QUIT:
|
||||
done = True
|
||||
for control in controls:
|
||||
control.handle_event(event)
|
||||
|
||||
if input_box.submitted:
|
||||
if password_check(input_box.text):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
for control in controls:
|
||||
control.update()
|
||||
|
||||
screen.fill((30, 30, 30))
|
||||
for control in controls:
|
||||
control.draw(screen)
|
||||
|
||||
pg.display.flip()
|
||||
clock.tick(30)
|
||||
|
||||
def password_fail_screen():
|
||||
screen = pg.display.set_mode((640, 480))
|
||||
clock = pg.time.Clock()
|
||||
heading = Label(40, 20, 'You done goofed. Don\'t pirate this game.',
|
||||
color=pg.Color('firebrick1'),
|
||||
font=pg.font.Font('fonts/arial.ttf', 32))
|
||||
warning_color = pg.Color('lightgray')
|
||||
warning_font = pg.font.Font('fonts/arial.ttf', 14)
|
||||
warning_text1 = Label(60, 300,
|
||||
"What did you say to me, you little hacker? I'll have you know I graduated top of my",
|
||||
color=warning_color, font=warning_font)
|
||||
warning_text2 = Label(60, 320,
|
||||
"class in the DoD Cyber Command, and I've been involved in numerous secret raids on",
|
||||
color=warning_color, font=warning_font)
|
||||
warning_text3 = Label(60, 340,
|
||||
"the dark web, and I have over 300 confirmed death row convictions for software piracy.",
|
||||
color=warning_color, font=warning_font)
|
||||
warning_text4 = Label(60, 360,
|
||||
"I am trained in capture the flag and am the top reverser in the entire government.",
|
||||
color=warning_color, font=warning_font)
|
||||
warning_text5 = Label(60, 380,
|
||||
"As we speak I am contacting my secret network of spies across the USA and your IP is",
|
||||
color=warning_color, font=warning_font)
|
||||
warning_text6 = Label(60, 400,
|
||||
"being traced right now so you better prepare for the storm, maggot. The storm that",
|
||||
color=warning_color, font=warning_font)
|
||||
warning_text7 = Label(60, 420,
|
||||
"wipes out the pathetic little thing you call your life. You done goofed.",
|
||||
color=warning_color, font=warning_font)
|
||||
controls = [heading,
|
||||
warning_text1,
|
||||
warning_text2,
|
||||
warning_text3,
|
||||
warning_text4,
|
||||
warning_text5,
|
||||
warning_text6,
|
||||
warning_text7]
|
||||
done = False
|
||||
|
||||
fbi_logo = pg.image.load('img/fbi.png')
|
||||
|
||||
while not done:
|
||||
for event in pg.event.get():
|
||||
if event.type == pg.QUIT:
|
||||
done = True
|
||||
for control in controls:
|
||||
control.handle_event(event)
|
||||
|
||||
for control in controls:
|
||||
control.update()
|
||||
|
||||
screen.fill(pg.Color('darkblue'))
|
||||
for control in controls:
|
||||
control.draw(screen)
|
||||
|
||||
screen.blit(fbi_logo, (220, 80))
|
||||
pg.display.flip()
|
||||
clock.tick(30)
|
||||
|
||||
def game_screen():
|
||||
global current_coins, current_autoclickers, buying
|
||||
screen = pg.display.set_mode((640, 480))
|
||||
clock = pg.time.Clock()
|
||||
heading = Label(10, 10, 'Click on Kitty to send her out to catch mice to earn money',
|
||||
color=pg.Color('green'),
|
||||
font=pg.font.Font('fonts/arial.ttf', 20))
|
||||
heading2 = Label(10, 30, 'Earn about 100 Billion coins to win and reveal the flag.',
|
||||
color=pg.Color('green'),
|
||||
font=pg.font.Font('fonts/arial.ttf', 20))
|
||||
|
||||
cat_image = pg.transform.scale2x(pg.image.load('img/kittyelaine.png'))
|
||||
cat_button = ImageButton(20, 80, 300, 300,
|
||||
cat_image,
|
||||
down_img = pg.transform.rotate(cat_image, -5),
|
||||
callback=cat_clicked)
|
||||
coin_img = Image(360, 70, pg.transform.scale2x(pg.image.load('img/coin.png')))
|
||||
coins_label = Label(400, 75, '0', color=pg.Color('gold'), font=pg.font.Font('fonts/courbd.ttf', 20))
|
||||
clock_img = Image(360, 110, pg.transform.scale2x(pg.image.load('img/clock.png')))
|
||||
clickers_label = Label(400, 115, '0', color=pg.Color('lightgray'), font=pg.font.Font('fonts/courbd.ttf', 20))
|
||||
buy_autoclickers_label = Label(320, 200, 'Buy Autoclickers (price: 10 each):',
|
||||
color=pg.Color('lightgray'),
|
||||
font=pg.font.Font('fonts/arial.ttf', 18))
|
||||
autoclickers_input = InputBox(320, 235, 180, 32, text='1')
|
||||
button = Button(510, 225, 128, 64, text='Buy', color=pg.Color('black'),
|
||||
font=pg.font.Font('fonts/courbd.ttf', 50), callback=buy_click)
|
||||
controls = [heading,
|
||||
heading2,
|
||||
button,
|
||||
cat_button,
|
||||
coin_img,
|
||||
clock_img,
|
||||
coins_label,
|
||||
clickers_label,
|
||||
buy_autoclickers_label,
|
||||
autoclickers_input]
|
||||
|
||||
last_second = pg.time.get_ticks()
|
||||
done = False
|
||||
|
||||
while not done:
|
||||
target_amount = (2**36) + (2**35)
|
||||
if current_coins > (target_amount - 2**20):
|
||||
while current_coins >= (target_amount + 2**20):
|
||||
current_coins -= 2**20
|
||||
victory_screen(int(current_coins / 10**8))
|
||||
return
|
||||
current_ticks = pg.time.get_ticks()
|
||||
passed_time = current_ticks - last_second
|
||||
if passed_time >= 1000:
|
||||
last_second = current_ticks
|
||||
current_coins += current_autoclickers
|
||||
|
||||
if buying:
|
||||
try:
|
||||
amount_to_buy = int(autoclickers_input.text)
|
||||
except:
|
||||
amount_to_buy = 1
|
||||
autoclickers_input.text = '1'
|
||||
if amount_to_buy > 0 and current_coins >= amount_to_buy * 10:
|
||||
current_coins -= amount_to_buy * 10
|
||||
current_autoclickers += amount_to_buy
|
||||
buying = False
|
||||
for event in pg.event.get():
|
||||
if event.type == pg.QUIT:
|
||||
done = True
|
||||
for control in controls:
|
||||
control.handle_event(event)
|
||||
|
||||
for control in controls:
|
||||
coins_label.change_text("%d" % current_coins)
|
||||
clickers_label.change_text("%d" % current_autoclickers)
|
||||
control.update()
|
||||
|
||||
screen.fill((30, 30, 30))
|
||||
for control in controls:
|
||||
control.draw(screen)
|
||||
|
||||
pg.display.flip()
|
||||
clock.tick(30)
|
||||
|
||||
|
||||
def decode_flag(frob):
|
||||
last_value = frob
|
||||
encoded_flag = [1135, 1038, 1126, 1028, 1117, 1071, 1094, 1077, 1121, 1087, 1110, 1092, 1072, 1095, 1090, 1027,
|
||||
1127, 1040, 1137, 1030, 1127, 1099, 1062, 1101, 1123, 1027, 1136, 1054]
|
||||
decoded_flag = []
|
||||
|
||||
for i in range(len(encoded_flag)):
|
||||
c = encoded_flag[i]
|
||||
val = (c - ((i%2)*1 + (i%3)*2)) ^ last_value
|
||||
decoded_flag.append(val)
|
||||
last_value = c
|
||||
|
||||
return ''.join([chr(x) for x in decoded_flag])
|
||||
|
||||
|
||||
def victory_screen(token):
|
||||
screen = pg.display.set_mode((640, 160))
|
||||
clock = pg.time.Clock()
|
||||
heading = Label(20, 20, 'If the following key ends with @flare-on.com you probably won!',
|
||||
color=pg.Color('gold'), font=pg.font.Font('fonts/arial.ttf', 22))
|
||||
flag_label = Label(20, 105, 'Flag:', color=pg.Color('gold'), font=pg.font.Font('fonts/arial.ttf', 22))
|
||||
flag_content_label = Label(120, 100, 'the_flag_goes_here',
|
||||
color=pg.Color('red'), font=pg.font.Font('fonts/arial.ttf', 32))
|
||||
|
||||
controls = [heading, flag_label, flag_content_label]
|
||||
done = False
|
||||
|
||||
flag_content_label.change_text(decode_flag(token))
|
||||
|
||||
while not done:
|
||||
for event in pg.event.get():
|
||||
if event.type == pg.QUIT:
|
||||
done = True
|
||||
for control in controls:
|
||||
control.handle_event(event)
|
||||
|
||||
for control in controls:
|
||||
control.update()
|
||||
|
||||
screen.fill((30, 30, 30))
|
||||
for control in controls:
|
||||
control.draw(screen)
|
||||
|
||||
pg.display.flip()
|
||||
clock.tick(30)
|
||||
|
||||
def buy_click():
|
||||
global buying
|
||||
buying = True
|
||||
return
|
||||
|
||||
def cat_clicked():
|
||||
global current_coins
|
||||
current_coins += 1
|
||||
return
|
||||
|
||||
def main():
|
||||
if password_screen():
|
||||
game_screen()
|
||||
else:
|
||||
password_fail_screen()
|
||||
pg.quit()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
BIN
2020/flare-on/1_-_fidler/fonts/arial.ttf
Normal file
BIN
2020/flare-on/1_-_fidler/fonts/arial.ttf
Normal file
Binary file not shown.
BIN
2020/flare-on/1_-_fidler/fonts/courbd.ttf
Normal file
BIN
2020/flare-on/1_-_fidler/fonts/courbd.ttf
Normal file
Binary file not shown.
BIN
2020/flare-on/1_-_fidler/img/btndown.png
Normal file
BIN
2020/flare-on/1_-_fidler/img/btndown.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 219 B |
BIN
2020/flare-on/1_-_fidler/img/btnup.png
Normal file
BIN
2020/flare-on/1_-_fidler/img/btnup.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 222 B |
BIN
2020/flare-on/1_-_fidler/img/clock.png
Normal file
BIN
2020/flare-on/1_-_fidler/img/clock.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 192 B |
BIN
2020/flare-on/1_-_fidler/img/coin.png
Normal file
BIN
2020/flare-on/1_-_fidler/img/coin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 249 B |
BIN
2020/flare-on/1_-_fidler/img/fbi.png
Normal file
BIN
2020/flare-on/1_-_fidler/img/fbi.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
BIN
2020/flare-on/1_-_fidler/img/kittyelaine.png
Normal file
BIN
2020/flare-on/1_-_fidler/img/kittyelaine.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
Reference in New Issue
Block a user