-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchallenge.py
121 lines (98 loc) · 3.47 KB
/
challenge.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/usr/bin/env python3
#
# BlackHat MEA 2024 CTF Qualifiers
#
# [Medium] Crypto - Cheeky
#
# Native imports
import os, time, json
from hashlib import sha256
# Non-native imports
from Crypto.Cipher import AES
# Flag import
FLAG = os.environ.get('DYN_FLAG', 'BHFlagY{506f6c79-6d65726f-57617348-65726521}')
if isinstance(FLAG, str):
FLAG = FLAG.encode()
# Functions & Classes
class Database:
def __init__(self, passkey: bytes):
if isinstance(passkey, str):
passkey = passkey.encode()
self.key = sha256(b"::".join([b"KEY(_FLAG)", passkey, len(passkey).to_bytes(2, 'big')])).digest()
self.uiv = int(sha256(b"::".join([b"UIV(_KEY)", self.key, len(self.key).to_bytes(2, 'big')])).hexdigest()[:24], 16)
self.edb = {}
def _GetUIV(self, f: str, l: int, t: int = 0) -> bytes:
if not (0 < t < int(time.time())):
t = int(time.time()); time.sleep(2)
u = (self.uiv + t).to_bytes(12, 'big')
v = sha256(b"::".join([b"UIV(_FILE)", f.encode(), l.to_bytes(2, 'big')])).digest()
return t, bytes([i^j for i,j in zip(u, v)])
def _Encrypt(self, f: str, x: bytes) -> bytes:
if isinstance(x, str):
x = x.encode()
t, uiv = self._GetUIV(f, len(x))
aes = AES.new(self.key, AES.MODE_CTR, nonce=uiv)
return t.to_bytes(4, 'big') + aes.encrypt(x)
def _Decrypt(self, f: str, x: bytes) -> bytes:
t, x = int.from_bytes(x[:4], 'big'), x[4:]
_, uiv = self._GetUIV(f, len(x), t=t)
aes = AES.new(self.key, AES.MODE_CTR, nonce=uiv)
return aes.decrypt(x)
def Insert(self, f, i, j):
if isinstance(j, str):
j = j.encode()
if isinstance(j, int):
j = j.to_bytes(-(-len(bin(j)[:2])//8), 'big')
if f in self.edb:
x = self._Decrypt(f, self.edb[f])
else:
x = b""
y = x[:i] + j + x[i:]
z = self._Encrypt(f, y)
self.edb[f] = z
return z
def Delete(self, f, i, j):
if f not in self.edb:
return b""
x = self._Decrypt(f, self.edb[f])
y = x[:i] + x[i+j:]
z = self._Encrypt(f, y)
self.edb[f] = z
return z
# Challenge set-up
HDR = """|
| __________ __
| | _ |--.-----.-----| |--.--.--.
| | | -__ -__ < | |
| | |______|_________________|______ |
| | | | |_____|
| | |
| `-------'"""
print(HDR)
database = Database(FLAG)
database.Insert('flag', 0, FLAG)
# Server loop
TUI = "|\n| Menu:\n| [I]nsert\n| [D]elete\n| [Q]uit\n|"
while True:
try:
print(TUI)
choice = input("| > ").lower()
if choice == 'q':
raise KeyboardInterrupt
elif choice == 'i':
uin = json.loads(input("| > (JSON) "))
assert uin.keys() == {'f', 'i', 'j'}
ret = database.Insert(uin['f'], uin['i'], uin['j'])
print("| '{}' updated to 0x{}".format(uin['f'], ret.hex()))
elif choice == 'd':
uin = json.loads(input("| > (JSON) "))
assert uin.keys() == {'f', 'i', 'j'}
ret = database.Delete(uin['f'], uin['i'], uin['j'])
print("| '{}' updated to 0x{}".format(uin['f'], ret.hex()))
else:
print('| [!] Invalid choice.')
except KeyboardInterrupt:
print('\n|\n| [~] Goodbye ~ !\n|')
break
except Exception as e:
print('| [!] ERROR :: {}'.format(e))