Skip to content

Commit de6d711

Browse files
committed
Participate in Codegate 2024 Quals
1 parent 3813225 commit de6d711

File tree

14 files changed

+1401
-0
lines changed

14 files changed

+1401
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class Character:
2+
def __init__(self, nickname='', day=0, stamina=0, intelligence=0, friendship=0):
3+
self.nickname = nickname
4+
self.day = day
5+
self.stamina = stamina
6+
self.intelligence = intelligence
7+
self.friendship = friendship
8+
Loading
+280
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
import Character
2+
import credential
3+
import messages
4+
5+
import pygame
6+
from pygame.locals import QUIT
7+
import random
8+
import string
9+
import sys
10+
import socket
11+
import time
12+
import hashlib
13+
import os
14+
from Crypto.Util.Padding import pad
15+
from Crypto.Cipher import AES
16+
17+
EAT_COMMAND = 1
18+
PWN_COMMAND = 2
19+
SLEEP_COMMAND = 3
20+
DATE_COMMAND = 4
21+
SAVE_COMMAND = 5
22+
23+
SAVE_SUCCESS = 11
24+
SAVE_FAIL = 12
25+
26+
DEBUG = True
27+
28+
def alert(s):
29+
if DEBUG:
30+
print(s)
31+
else:
32+
return
33+
34+
def get_random_str():
35+
return ''.join(random.sample(string.ascii_lowercase + string.ascii_uppercase + string.digits, k = 20)) + os.urandom(10).hex()
36+
37+
def get_credential():
38+
status, ID, PW, nickname = credential.load_credential()
39+
if status == credential.LOAD_SUCCESS:
40+
alert("[+] Load credential.. success")
41+
42+
else:
43+
ID = get_random_str()
44+
PW = get_random_str()
45+
nickname = "You"
46+
status = credential.save_credential(ID, PW, nickname)
47+
if status == credential.SAVE_SUCCESS:
48+
alert("[+] Save a new credential.. success")
49+
else:
50+
alert("[-] Save a new credential.. failed")
51+
exit(-1)
52+
53+
return ID, PW, nickname
54+
55+
def encrypt_data(ID, PW, character):
56+
id_hash = hashlib.sha256(ID.encode()).digest()
57+
pw_hash = hashlib.sha256(PW.encode()).digest()
58+
nonce = id_hash[:12]
59+
file_name = id_hash[16:24].hex()
60+
key = pw_hash[:16]
61+
cipher = AES.new(key, AES.MODE_GCM, nonce)
62+
63+
file_data = b''
64+
file_data += len(character.nickname).to_bytes(2, 'little')
65+
file_data += character.nickname.encode()
66+
file_data += character.day.to_bytes(4, 'little')
67+
file_data += character.stamina.to_bytes(4, 'little')
68+
file_data += character.intelligence.to_bytes(4, 'little')
69+
file_data += character.friendship.to_bytes(4, 'little')
70+
71+
file_data = pad(file_data, 16)
72+
file_data_enc, tag = cipher.encrypt_and_digest(file_data)
73+
return file_data_enc, tag
74+
75+
def put_script(font, screen, writer, msg, sleep_time = 0):
76+
pygame.draw.rect(screen, (0,0,0), pygame.Rect(0, 768, 1024, 100))
77+
script = font.render(f"{writer}: {msg}", True, (0, 255, 0))
78+
screen.blit(script, [10, 768 + 20])
79+
pygame.display.flip()
80+
if sleep_time:
81+
time.sleep(sleep_time)
82+
83+
def put_character_status(font, screen, character):
84+
pygame.draw.rect(screen, (0,0,0), pygame.Rect(512, 0, 300, 200))
85+
status = font.render(f"day : {character.day}", True, (0, 255, 0))
86+
screen.blit(status, [520, 10])
87+
88+
status = font.render(f"stamina : {character.stamina}", True, (0, 255, 0))
89+
screen.blit(status, [520, 50])
90+
91+
status = font.render(f"intelligence : {character.intelligence}", True, (0, 255, 0))
92+
screen.blit(status, [520, 90])
93+
94+
status = font.render(f"friendship : {character.friendship} / 34", True, (0, 255, 0))
95+
screen.blit(status, [520, 130])
96+
97+
pygame.display.flip()
98+
99+
100+
def GUI(ID, PW, character, sock, is_new_game):
101+
#### GUI INIT ####
102+
pygame.init()
103+
screen = pygame.display.set_mode([1024, 868])
104+
pygame.display.set_caption('Cogechan Dating Game')
105+
106+
# load cogechan image
107+
cogechan_img = pygame.image.load("assets/cogechan.png").convert()
108+
screen.blit(cogechan_img, (0,0))
109+
110+
# Set font
111+
fontname = 'couriernew'
112+
if fontname not in pygame.font.get_fonts():
113+
fontname = pygame.font.get_fonts()[0]
114+
font = pygame.font.SysFont(fontname, 25, True, False)
115+
116+
# Set Eat/Pwn/Sleep/Date buttons
117+
pygame.draw.rect(screen, (225,125,206), pygame.Rect(550, 250, 170, 50))
118+
btn = font.render("Eat", True, (255, 255, 255))
119+
screen.blit(btn, [570, 260])
120+
pygame.draw.rect(screen, (225,125,206), pygame.Rect(550, 350, 170, 50))
121+
btn = font.render("Pwn", True, (255, 255, 255))
122+
screen.blit(btn, [570, 360])
123+
pygame.draw.rect(screen, (225,125,206), pygame.Rect(550, 450, 170, 50))
124+
btn = font.render("Sleep", True, (255, 255, 255))
125+
screen.blit(btn, [570, 460])
126+
pygame.draw.rect(screen, (225,125,206), pygame.Rect(550, 550, 170, 50))
127+
btn = font.render("Date", True, (255, 255, 255))
128+
screen.blit(btn, [570, 560])
129+
130+
# Set save buttons
131+
pygame.draw.rect(screen, (225,0,206), pygame.Rect(850, 70, 170, 50))
132+
btn = font.render("Game save", True, (255, 255, 255))
133+
screen.blit(btn, [870, 80])
134+
pygame.display.flip()
135+
136+
put_character_status(font, screen, character)
137+
if is_new_game:
138+
put_script(font, screen, 'System', f'A saved game is loaded from server.')
139+
else:
140+
put_script(font, screen, 'System', f'A new game is started.')
141+
142+
last_click = None
143+
while True:
144+
for event in pygame.event.get():
145+
if event.type == QUIT:
146+
pygame.quit()
147+
sock.close()
148+
exit()
149+
150+
if event.type == pygame.MOUSEBUTTONUP:
151+
if last_click != None and (time.time() - last_click) < 0.4:
152+
continue
153+
mouse = pygame.mouse.get_pos()
154+
155+
# Eat
156+
if 550 <= mouse[0] <= 550+170 and 250 <= mouse[1] <= 250+50:
157+
sock.send(EAT_COMMAND.to_bytes(1, 'little'))
158+
rnd = int.from_bytes(sock.recv(1), 'little')
159+
if rnd == 0:
160+
put_script(font, screen, 'System', f'Server connection broken.. bye..', 1)
161+
exit()
162+
character.stamina += rnd
163+
character.day += 1
164+
put_script(font, screen, character.nickname, random.choice(messages.EAT_MESSAGE), 1)
165+
put_script(font, screen, 'System', f'stamina +{rnd}')
166+
put_character_status(font, screen, character)
167+
168+
# Pwn
169+
elif 550 <= mouse[0] <= 550+170 and 350 <= mouse[1] <= 350+50:
170+
sock.send(PWN_COMMAND.to_bytes(1, 'little'))
171+
rnd = int.from_bytes(sock.recv(1), 'little')
172+
if rnd == 0:
173+
put_script(font, screen, 'System', f'Server connection broken.. bye..', 1)
174+
exit()
175+
if character.stamina >= 10:
176+
character.stamina -= 10
177+
character.intelligence += rnd
178+
character.day += 1
179+
put_script(font, screen, character.nickname, random.choice(messages.PWN_SUCCESS_MESSAGE), 1)
180+
put_script(font, screen, 'System', f'stamina -10, intelligence +{rnd}')
181+
182+
else:
183+
put_script(font, screen, character.nickname, random.choice(messages.PWN_FAIL_MESSAGE), 1)
184+
185+
# Sleep
186+
elif 550 <= mouse[0] <= 550+170 and 450 <= mouse[1] <= 450+50:
187+
sock.send(SLEEP_COMMAND.to_bytes(1, 'little'))
188+
rnd = int.from_bytes(sock.recv(1), 'little')
189+
if rnd == 0:
190+
put_script(font, screen, 'System', f'Server connection broken.. bye..', 1)
191+
exit()
192+
character.stamina += rnd
193+
character.day += 1
194+
put_script(font, screen, character.nickname, random.choice(messages.SLEEP_MESSAGE), 1)
195+
put_script(font, screen, 'System', f'stamina +{rnd}')
196+
put_character_status(font, screen, character)
197+
198+
# Date
199+
elif 550 <= mouse[0] <= 550+170 and 550 <= mouse[1] <= 550+50:
200+
sock.send(DATE_COMMAND.to_bytes(1, 'little'))
201+
rnd = int.from_bytes(sock.recv(1), 'little')
202+
if rnd == 0:
203+
put_script(font, screen, 'System', f'Server connection broken.. bye..', 1)
204+
exit()
205+
put_script(font, screen, character.nickname, messages.DATE_REQUEST_MESSAGE[min(character.friendship, 33)], 1)
206+
if character.stamina >= 10 and character.intelligence.bit_length() >= character.friendship:
207+
character.stamina -= 10
208+
character.friendship += 1
209+
character.day += 1
210+
if character.friendship == 34:
211+
flag_len = int.from_bytes(sock.recv(2), 'little')
212+
flag = sock.recv(flag_len).decode()
213+
put_script(font, screen, "Cogechan", "Not only that, I want to spend my whole life with you.", 1)
214+
put_script(font, screen, 'System', flag)
215+
216+
else:
217+
put_script(font, screen, "Cogechan", random.choice(messages.DATE_SUCCESS_MESSAGE), 1)
218+
put_script(font, screen, 'System', f'stamina -10, friendship +1')
219+
220+
else:
221+
put_script(font, screen, "Cogechan", random.choice(messages.DATE_FAIL_MESSAGE), 1)
222+
223+
224+
# Game save
225+
elif 850 <= mouse[0] <= 850+170 and 70 <= mouse[1] <= 70+50:
226+
sock.send(SAVE_COMMAND.to_bytes(1, 'little'))
227+
file_data_enc, tag = encrypt_data(ID, PW, character)
228+
sock.send(len(file_data_enc).to_bytes(2, 'little') + file_data_enc)
229+
sock.send(tag)
230+
status = int.from_bytes(sock.recv(1), 'little')
231+
if status == 0:
232+
put_script(font, screen, 'System', f'Server connection broken.. bye..', 1)
233+
exit()
234+
elif status == SAVE_SUCCESS:
235+
put_script(font, screen, "System", "Save success")
236+
else:
237+
put_script(font, screen, "System", "Save failed")
238+
239+
last_click = time.time()
240+
241+
put_character_status(font, screen, character)
242+
243+
def main():
244+
if len(sys.argv) != 3:
245+
print(f"usage : {sys.argv[0]} ip port")
246+
return
247+
248+
ip = sys.argv[1]
249+
port = int(sys.argv[2])
250+
251+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
252+
try:
253+
sock.connect((ip, port))
254+
except:
255+
alert("[-] failed to connect a server")
256+
return
257+
258+
ID, PW, nickname = get_credential()
259+
sock.send(len(ID).to_bytes(2, 'little') + ID.encode())
260+
sock.send(len(PW).to_bytes(2, 'little') + PW.encode())
261+
status = sock.recv(1)
262+
character = Character.Character()
263+
264+
if status[0] == 1: # LOAD_SUCCESS
265+
nickname_len = int.from_bytes(sock.recv(2), 'little')
266+
character.nickname = sock.recv(nickname_len).decode()
267+
character.day = int.from_bytes(sock.recv(4), 'little')
268+
character.stamina = int.from_bytes(sock.recv(4), 'little')
269+
character.intelligence = int.from_bytes(sock.recv(4), 'little')
270+
character.friendship = int.from_bytes(sock.recv(4), 'little')
271+
272+
else:
273+
sock.send(len(nickname).to_bytes(2, 'little') + nickname.encode())
274+
character.nickname = nickname
275+
character.stamina = 100
276+
277+
GUI(ID, PW, character, sock, status[0] == 1)
278+
279+
if __name__ == "__main__":
280+
main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"ID": "TheDuck_1234567890abcdefg", "PW": "Qwaz_1234567890abcdefgi8s2", "nickname": "You"}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import json
2+
3+
LOAD_SUCCESS = 1
4+
LOAD_ERROR1 = 2 # credential file does not exist or file corrupted
5+
6+
SAVE_SUCCESS = 11
7+
SAVE_ERROR1 = 12 # cannot save credential
8+
9+
def load_credential():
10+
try:
11+
with open("credential", 'r') as f:
12+
info = json.loads(f.read())
13+
14+
ID = info["ID"]
15+
PW = info["PW"]
16+
nickname = info["nickname"]
17+
assert type(ID) == str and type(PW) == str and type(nickname) == str
18+
19+
return LOAD_SUCCESS, ID, PW, nickname
20+
21+
except:
22+
return LOAD_ERROR1, None, None, None
23+
24+
def save_credential(ID, PW, nickname):
25+
try:
26+
info = {}
27+
info["ID"] = ID
28+
info["PW"] = PW
29+
info["nickname"] = nickname
30+
with open("credential", 'w') as f:
31+
json.dump(info, f)
32+
return SAVE_SUCCESS
33+
except:
34+
return SAVE_ERROR1
35+
36+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
EAT_MESSAGE = ["Yummy!", "Life is uncertain. Eat dessert first.", "I live to eat!", "Time to eat!"]
2+
3+
PWN_SUCCESS_MESSAGE = ["Haaaaacking is so fun!", "My crime is that of curiosity.", "Hacking is not a crime.", "Be a Godlike-level Hacker"]
4+
5+
PWN_FAIL_MESSAGE = ["hmm... tooooo tired today..", "I need a rest", "I don't want to study today"]
6+
7+
SLEEP_MESSAGE = ["So sweet", "Good night, good dream", "Happiness is a nice long nap", "When I wake up, I am reborn."]
8+
9+
DATE_REQUEST_MESSAGE = [
10+
"Shall we register CODEGATE 2024?",
11+
"Let's learn buffer overflow!",
12+
"Let's learn about cryptography!",
13+
"Shall we contribute to open-source projects?",
14+
"Would you like to develop a mobile app?",
15+
"Would you like to participate in a bug bounty program?",
16+
"Shall we organize a tech meetup?",
17+
"Let's learn about format string vulnerabilities!",
18+
"How about a weekend hackathon?",
19+
"Let's learn about shellcode injection!",
20+
"Shall we explore new programming languages?",
21+
"Let's learn about integer overflows!",
22+
"Would you like to participate in a coding bootcamp?",
23+
"Let's learn about cross-site scripting!",
24+
"Shall we read a book on software engineering?",
25+
"Let's learn about directory traversal!",
26+
"How about we develop an app together?",
27+
"Let's learn about SQL injection!",
28+
"Shall we work on our coding skills this summer?",
29+
"Let's learn about code injection!",
30+
"Would you like to write a research paper on cybersecurity?",
31+
"Let's learn about fuzz testing!",
32+
"Shall we attend a machine learning workshop?",
33+
"Let's learn about side-channel attacks!",
34+
"How about we join a startup incubator?",
35+
"Let's learn about malware analysis!",
36+
"Shall we build a home automation system?",
37+
"Let's learn about network sniffing!",
38+
"Let's learn about man-in-the-middle attacks!",
39+
"Shall we study quantum computing?",
40+
"Let's learn about password cracking!",
41+
"Would you like to participate in a bug bounty program?",
42+
"Let's learn about sandbox evasion!",
43+
"Would you like to go DEF CON Conference together?",
44+
]
45+
46+
DATE_SUCCESS_MESSAGE = ["Yes, I love it!", "With pleasure.", "Whatever you want.", "How can I say no to you?"]
47+
48+
DATE_FAIL_MESSAGE = ["Sorry, I'm tired today.", "...(No response at all...)", "Go away", "Umm.. Maybe another time."]

0 commit comments

Comments
 (0)