TheZZAZZGlitch's April Fools Event 2022
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

464 lines
9.9 KiB

#!/usr/bin/env python3
import json
from urllib.request import Request, urlopen
from base64 import b64encode, b64decode
from binascii import hexlify, unhexlify
from random import randrange
from os.path import isfile, isdir
from os import mkdir
from time import time
charmap = {
' ': 0x00,
'é': 0x1B,
'0': 0xA1,
'1': 0xA2,
'2': 0xA3,
'3': 0xA4,
'4': 0xA5,
'5': 0xA6,
'6': 0xA7,
'7': 0xA8,
'8': 0xA9,
'9': 0xAA,
'!': 0xAB,
'?': 0xAC,
'.': 0xAD,
'-': 0xAE,
'': 0xB0,
'': 0xB1,
'': 0xB2,
'': 0xB3,
'': 0xB4,
'': 0xB5,
'': 0xB6,
',': 0xB8,
'/': 0xBA,
'A': 0xBB,
'B': 0xBC,
'C': 0xBD,
'D': 0xBE,
'E': 0xBF,
'F': 0xC0,
'G': 0xC1,
'H': 0xC2,
'I': 0xC3,
'J': 0xC4,
'K': 0xC5,
'L': 0xC6,
'M': 0xC7,
'N': 0xC8,
'O': 0xC9,
'P': 0xCA,
'Q': 0xCB,
'R': 0xCC,
'S': 0xCD,
'T': 0xCE,
'U': 0xCF,
'V': 0xD0,
'W': 0xD1,
'X': 0xD2,
'Y': 0xD3,
'Z': 0xD4,
'a': 0xD5,
'b': 0xD6,
'c': 0xD7,
'd': 0xD8,
'e': 0xD9,
'f': 0xDA,
'g': 0xDB,
'h': 0xDC,
'i': 0xDD,
'j': 0xDE,
'k': 0xDF,
'l': 0xE0,
'm': 0xE1,
'n': 0xE2,
'o': 0xE3,
'p': 0xE4,
'q': 0xE5,
'r': 0xE6,
's': 0xE7,
't': 0xE8,
'u': 0xE9,
'v': 0xEA,
'w': 0xEB,
'x': 0xEC,
'y': 0xED,
'z': 0xEE,
'$': 0xFF,
}
charmap_rev = {}
for x, y in charmap.items():
charmap_rev[y] = x
def translate(str):
d = bytearray()
for x in str:
d.append(charmap[x])
d.append(0xff)
return d
def translate_rev(bytes):
s = ""
for c in bytes:
if c == 0xff:
break
s += charmap_rev[c]
return s
class BitstreamReader():
def __init__(self, bytes, bytesize=8):
self.bytes = bytes
self.bytesize = bytesize
self.pos = 0
self.bits = 0
self.value = 0
def remaining(self):
if self.pos < len(self.bytes):
return True
if self.bits > 0:
return True
return False
def read(self, count):
while self.bits < count:
if self.pos >= len(self.bytes):
break
self.value |= (self.bytes[self.pos] & ((1 << self.bytesize) - 1)) << self.bits
self.bits += self.bytesize
self.pos += 1
ret = self.value & ((1 << count) - 1)
self.value >>= count
self.bits -= count
return ret
def bitpack(code, origbits, destbits):
newcode = []
reader = BitstreamReader(code, origbits)
while reader.remaining():
newcode.append(reader.read(destbits))
return newcode
def ror(val, bits):
return val >> bits | ((val << (32 - bits)) & (2 ** 32 - 1))
class Client:
def __init__(self, user, pwd):
self.token = None
self.uid = None
self.login(user, pwd)
def makereq(self, endpoint, *args, **kwargs):
req = Request("https://fools2022.online/%s" % endpoint, *args, **kwargs)
req.add_header("User-Agent", "fools2022-client/1.1.0")
req.add_header("Content-Type", "application/x-www-form-urlencoded")
req.add_header("Accept-Encoding", "identity")
if self.token:
req.add_header("X-Foolssessiontoken", self.token)
return req
def makepkt(self, cmd, data):
data = bitpack(data, 8, 32)
rnd = randrange(256)
pkt = [rnd << 8 | cmd] + data
magic = 0xf0dbeb15
for x in pkt:
magic = ror(magic, 5)
magic ^= x
magic += x * 2
pkt[0] = (magic & (2**16-1)) << 16 | pkt[0]
pkt = b64encode(bytes(bitpack(pkt, 32, 8)))
return self.makereq("packet/%s" % self.uid, data=pkt)
def login(self, user, pwd):
data = {"u": user, "p": pwd}
data = json.dumps(data).encode()
req = self.makereq("login", data=data)
res = json.loads(urlopen(req).read().decode())
self.token = res["data"]["session"]
self.uid = res["data"]["uid"]
def getmap(self, mapid, pos=(0,0)):
data = [mapid >> 0, mapid >> 8, pos[0], pos[1]]
req = self.makepkt(0x01, data)
rev = b64decode(urlopen(req).read().decode())
print(hexlify(rev).decode())
return rev
def trendset(self, text):
data = bytearray()
for i, x in enumerate(text):
data.append(x)
data.append(0xff)
req = self.makepkt(0x04, data)
rev = b64decode(urlopen(req).read().decode()).decode()
print(rev)
def cave3(self, text):
data = bytearray(unhexlify("ffffffffffffffffffff"))
for i, x in enumerate(text):
data[i] = x
req = self.makepkt(0x06, data)
print(urlopen(req).read().decode())
def cave4gen(self, text):
data = bytearray()
for i, x in enumerate(text):
data.append(ord(x))
data.append(0xff)
req = self.makepkt(0x07, data)
rev = b64decode(urlopen(req).read().decode())[:-1].decode()
print(rev)
def cave4chk(self, cert):
data = cert.encode() + b"\xff"
req = self.makepkt(0x08, data)
rev = b64decode(urlopen(req).read().decode())
print(rev)
rev = rev[4:-1]
for x in range(0, len(rev), 16):
print(rev[x:x+16])
def lotto(self):
data = b""
req = self.makepkt(0x05, data)
rev = b64decode(urlopen(req).read().decode())
print(hexlify(rev).decode())
def complete(self):
data = bytearray(unhexlify("ef7fffff7fe0ffff000000000000000000000000000000000000000000000000"))
data = bytearray(unhexlify("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))
req = self.makepkt(0x02, data)
rev = b64decode(urlopen(req).read().decode()).decode()
print(rev)
maps = [
0x0000,
0x0100,
0x0110,
0x0210,
0x0327,
0x0364,
0x043A,
0x0523,
0x0565,
0x0566,
0x062F,
0x0667,
0x0668,
0x0669,
0x066A,
0x0734,
0x0824,
0x0932,
0x096B,
0x098A,
0x0A32,
0x0B2D,
0x0C2C,
0x0D3E,
0x0E3C,
0x0E6C,
0x0F3B,
0x103B,
0x106D,
0x113D,
0x116E,
0x123D,
0x1321,
0x1337,
0x1432,
0x146F,
0x152D,
0x1631,
0x1639,
0x1670,
0x1671,
0x1672,
0x1720,
0x1730,
0x1731,
0x1732,
0x182A,
0x1927,
0x1A3C,
0x1A73,
0x1B37,
0x1C2C,
0x1D3B,
0x1E33,
0x1E92,
0x1F3A,
0x1F79,
0x1F7A,
0x2001,
0x202F,
0x207B,
0x2125,
0x2174,
0x223A,
0x2275,
0x2276,
0x2277,
0x232D,
0x2435,
0x2478,
0x2536,
0x2632,
0x2725,
0x2731,
0x2791,
0x2833,
0x2939,
0x2B29,
0x2B7C,
0x2B7D,
0x2B7E,
0x2C29,
0x2D27,
0x2E2B,
0x2F38,
0x2F7F,
0x2F80,
0x2F81,
0x302C,
0x3120,
0x318B,
0x318C,
0x318D,
0x318E,
0x318F,
0x3190,
0x3191,
0x323F,
0x3336,
0x3420,
0x3482,
0x353C,
0x3621,
0x3724,
0x3828,
0x3920,
0x3A3E,
0x3B22,
0x3B30,
0x3B31,
0x3B32,
0x3C36,
0x3D20,
0x3D83,
0x3E31,
0x3E90,
0x3F3D,
0x4026,
0x412E,
0x423A,
0x432A,
0x4384,
0x4430,
0x4528,
0x4530,
0x4585,
0x472B,
0x4786,
0x4787,
0x4788,
0x482B,
0x4889,
0x4933,
0x4A34,
0x4B3A,
0x4C21,
0x4C93,
0x4D3A,
0x4E22,
0x4F21,
0x506F,
0x5133,
0x5134,
0x5135,
0x5136,
0x5137,
0x5160,
0x5211,
]
maps_skip = [
# YEET maps (not always accessible)
0x5133,
0x5134,
0x5135,
0x5136,
0x5137,
0x5160
]
if __name__ == "__main__":
from time import sleep
from sys import argv
c = Client(open(".user").read().strip(), open(".pass").read().strip())
sleep(1)
if argv[1] == "map":
c.getmap(int(argv[2], 0))
if argv[1] == "maps":
fun_map = c.getmap(0x1670)
fun_value = int(translate_rev(fun_map[0x25b:0x260]))
print("Fun value:", fun_value)
fdir = "maps_%03d" % fun_value
if not isdir(fdir):
mkdir(fdir)
sleep(1)
# fdir = "maps"
# for x in range(0x10000):
for x in maps:
fname = "%s/%04X.map" % (fdir, x)
if isfile(fname):
continue
if x in maps_skip:
continue
print("Getting map %s..." % fname)
m = c.getmap(x)
open(fname, "wb").write(m)
sleep(1)
if argv[1] == "trend":
c.trendset(translate(argv[2]))
if argv[1] == "cave3":
c.cave3(translate(argv[2]))
if argv[1] == "cave4gen":
c.cave4gen(argv[2])
if argv[1] == "cave4chk":
c.cave4chk(argv[2])
if argv[1] == "complete":
c.getmap(int(argv[2], 0))
sleep(1)
c.complete()
if argv[1] == "lotto":
c.lotto()
if argv[1] == "yeet":
game_corner_map = c.getmap(0x1A73)
sleep(1)
yeet_map_id = game_corner_map[0x8B0] << 0
yeet_map_id |= game_corner_map[0x8B1] << 8
yeet_map = c.getmap(yeet_map_id)
game_corner_map_fname = "maps_changing/1A73_%04X.map" % yeet_map_id
if not isfile(game_corner_map_fname):
open(game_corner_map_fname, "wb").write(game_corner_map)
yeet_map_fname = "maps/%04X.map" % yeet_map_id
if not isfile(yeet_map_fname):
open(yeet_map_fname, "wb").write(yeet_map)
sleep(1)
results_map = c.getmap(0x5160)
results_map_fname = "maps_changing/5160_%d.map" % time()
open(results_map_fname, "wb").write(results_map)
if argv[1] == "funroll":
fun_map = c.getmap(0x472b, (15, 10))
if argv[1] == "funcheck":
fun_map = c.getmap(0x1670)
fun_value = int(translate_rev(fun_map[0x25b:0x260]))
print(fun_value)