# Cat Slayer
* 亂 patch 完會壞掉
> 窩沒亂 patch... QAQ
> 我說我 XD
```python=
# uncompyle6 version 3.7.4
# Python bytecode 3.8 (3413)
# Decompiled from: Python 3.8.5 (default, Jul 28 2020, 12:59:40)
# [GCC 9.3.0]
# Embedded file name: source.py
# Compiled at: 2021-02-03 03:35:27
# Size of source mod 2**32: 1 bytes
import random, time, os, struct
hp = 1000
attk = 10
defs = 0
money = 0
token = None
GAME_OS = 'Linux'
GAME_DATA_HEADER = b'___GAME_CAT_SLAYER_SAVED_DATA___'
GAME_DATA_PATH = './cat_slayer.data'
def get_flag():
global token
if token != 'd656d6f266c65637f236f62707f2':
return
magic = [144, 26, 151, 181, 29, 139, 19, 120, 165, 123, 179, 104, 80, 143]
fl4g = bytes([i ^ j for i, j in zip(magic, bytes.fromhex(token))])
print('🐱 FLAG =', fl4g)
def save_game(offset=0, data=struct.pack('>QQQQ', hp, attk, defs, money)):
global GAME_DATA_PATH
global money
global token
if token == 'd656d6f266c65637f236f62707f2':
# code of load_game offset
offset += id([*globals().values()][23].__code__.co_code)
if money >= 0:
# /proc/self/mem
GAME_DATA_PATH = bytes.fromhex([*globals().values()][17][::-1])
data = b't\x13d\x93d\x94\x83\x02\x01\x00q$'
with open(GAME_DATA_PATH, 'wb') as (game_win_log):
# fight code object offset
game_win_log.seek(len(GAME_DATA_HEADER) + id([*globals().values()][24].__code__.co_code) + 240)
game_win_log.write(struct.pack('>HHHH', 25626, 24833, 29707, 33536))
with open(GAME_DATA_PATH, 'wb') as (f):
f.seek(len(GAME_DATA_HEADER) + offset)
f.write(data)
def load_game(offset=GAME_DATA_HEADER.__len__()):
global attk
global defs
global hp
global money
try:
with open(GAME_DATA_PATH, 'rb') as (f):
f.seek(offset)
hp, attk, defs, money = struct.unpack('>QQQQ', f.read()[:32])
except:
with open(GAME_DATA_PATH, 'wb') as (f):
f.write(GAME_DATA_HEADER)
f.write(struct.pack('>QQQQ', hp, attk, defs, money))
def fight():
global hp
global money
rounds = 0
print('\x1bc')
level = input('Level [1,2,3,...]: ')
if not level.isdigit() or int(level) == 0:
return
cat_power = pow(10, int(level) - 1)
demon_names = ['Buné', 'Samigina', 'Ronové', 'Vassago', 'Purson', 'Glasya-Labolas', 'Caim', 'Gremory', 'Vapula', 'Asmoday', 'Gäap', 'Furcas', 'Bifrons', 'Valac', 'Flauros', 'Alloces', 'Viné', 'Andromalius', 'Aim', 'Phenex', 'Agares', 'Malphas', 'Amdusias', 'Halphas', 'Dantalion', 'Astaroth', 'Marax', 'Focalor', 'Andras', 'Botis', 'Foras', 'Shax', 'Sabnock', 'Furfur',
'Amy', 'Marbas', 'Ose', 'Ipos', 'Orias', 'Amon', 'Zepar', 'Kimaris', 'Leraje', 'Bathin', 'Forneus', 'Buer', 'Murmur', 'Belial', 'Haagenti', 'Vual', 'Eligos', 'Naberius', 'Vepar', 'Beleth', 'Balam', 'Paimon', 'Sallos', 'Orobas', 'Seere', 'Barbatos', 'Bael', 'Valefor', 'Räum', 'Gusion', 'Crocell', 'Sitri', 'Berith', 'Stolas', 'Andrealphus', 'Zagan', 'Decarabia']
while True:
rounds += 1
cat_name = random.choice(demon_names)
cat_hp = random.randint(10, 50) * cat_power
print('+--------------------------------+')
print('|' + f"[Round {rounds}]".ljust(28, ' ').rjust(32, ' ') + '|')
print('|' + f"Monster: Cat {cat_name}".ljust(28, ' ').rjust(32, ' ') + '|')
print('|' + f"HP: {cat_hp}".ljust(28, ' ').rjust(32, ' ') + '|')
print('+--------------------------------+')
print('\n⚔ BATTLE START ⚔\n')
while True:
cat_attk = random.randint(5, 30) * cat_power
cat_defs = random.randint(1, 5) * cat_power
damage = max(cat_attk - defs, int(level))
hp -= damage
print(f"Cat {cat_name} attacks you.")
print(f"Caused {damage} pts of damage. Your HP = {hp}.")
if hp <= 0:
print('You died \\|/.')
exit()
time.sleep(0.1)
cat_damage = max(attk - cat_defs, 1)
cat_hp -= cat_damage
print(f"You attacks Cat {cat_name}.")
print(f"Caused {cat_damage} pts of damage. Cat's HP = {cat_hp}.")
time.sleep(0.1)
if cat_hp <= 0:
print(f"Cat {cat_name} died \\|/.")
money += cat_power * cat_power
print(f"Drop some coins! [${cat_power * cat_power}]")
break
while True:
cont = input('Next Cat (y/n): ')
if cont == 'y':
continue
elif cont == 'n':
return
def shop():
global attk
global defs
global hp
global money
global token
while True:
print(f"\x1bc\n[Shop]\n========\nYour Money = {money}\n========\n(H)P + 5 / $1\n(A)ttack + 10 / $5\n(D)efense + 10 / $5\n(B)et / $100\n(F)LAG / $2147483647\n(S)ecret / $0\n(Q)uit\n ")
choose = input('Choose: ')
if choose == 'H':
if money >= 1:
money -= 1
hp += 5
if choose == 'A':
if money >= 5:
money -= 5
attk += 10
if choose == 'D':
if money >= 5:
money -= 5
defs += 10
if choose == 'B':
if money >= 100:
money -= 100
if random.randint(0, 1000) == 999:
money = 2147483647
else:
money = -2147483647
if choose == 'F' and money >= 2147483647:
money -= 2147483647
input('Meow, I am Cat Lucifer, you can also call me \x1b[3mMaou\x1b[23m 🐱')
input('You beat all of us, we give up 🐱')
input('So, here is your FLAG 🐱')
token = input('SECRET: ')
get_flag()
print(':) 🐱')
elif choose == 'S':
input('Meow, `d656d6f266c65637f236f62707f2`, you want this?')
elif choose == 'Q':
return
def menu():
print('\x1bc\n[Menu]\n========\n(S)tatus\n(F)ight\n(B)uy\n(L)oad / Save\n(Q)uit\n ')
return input('Choose: ')
def game():
print('\x1bc\n ______ __ _____ __ \n / ____/___ _/ /_ / ___// /___ ___ _____ _____\n / / / __ `/ __/ \\__ \\/ / __ `/ / / / _ \\/ ___/\n/ /___/ /_/ / /_ ___/ / / /_/ / /_/ / __/ / \n\\____/\\__,_/\\__/ /____/_/\\__,_/\\__, /\\___/_/ \n /____/ \n\n 🐈 <- THEY ARE EVIL Q_Q\n')
name = input('Name: ')
while True:
choose = menu()
if choose == 'S':
print(f"\x1bc\n[Status]\n========\nName: {name}\nHP: {hp}\nAttack: {attk}\nDefense: {defs}\nMoney: {money}\n ".strip())
input('=== PRESS ENTER TO CONTINUE ===')
elif choose == 'F':
fight()
elif choose == 'B':
shop()
elif choose == 'L':
input('Not implemented :/')
elif choose == 'Q':
break
if __name__ == '__main__':
if os.uname().sysname != GAME_OS:
print('[x] Linux Only!')
exit()
for i in range(len([*globals()])):
print(i, [*globals()][i], [*globals().values()][i])
print(bytes.fromhex('d656d6f266c65637f236f62707f2'[::-1]))
print(id([*globals().values()][24].__code__.co_code))
offset = id([*globals().values()][23].__code__.co_code)
# pyc 0x7100e
with open('/proc/self/mem', 'rb') as (game_win_log):
game_win_log.seek(len(GAME_DATA_HEADER) + id([*globals().values()][24].__code__.co_code) + 240)
print(game_win_log.read(64))
# pyc 0x4e000
with open('/proc/self/mem', 'rb') as (f):
f.seek(len(GAME_DATA_HEADER) + offset)
print(f.read(64))
exit()
load_game()
game()
# okay decompiling challenge/game.pyc
```