from random import choice as c from random import randint, shuffle import socketserver import signal import string import random import os class Task(socketserver.BaseRequestHandler): def _recvall(self): BUFF_SIZE = 2048 data = b'' while True: part = self.request.recv(BUFF_SIZE) data += part if len(part) < BUFF_SIZE: break return data.strip() def send(self, msg, newline=True): try: if newline: msg += b'\n' self.request.sendall(msg) except: pass def recv(self, prompt=b'[-] '): self.send(prompt, newline=False) return self._recvall() # 定义一个函数 calc,用于计算问题的结果 def calc(self, ans, chests, expr): try: C0, C1, C2, C3, C4, C5, C6 = chests r = eval(expr) except Exception as e: self.send(b"Shannon fails to understand your words.\n") self.send(e) exit(0) return ans(r) # 定义一个游戏回合函数 do_round def do_round(self): # 定义两个函数 truth 和 lie,用于判断 Shannon 的回答是否为真或假 truth = lambda r: not not r lie = lambda r: not r chests = [] for i in range(7): # 随机生成 7 个 True 或 False,表示每个箱子是宝藏还是怪物 chests.append(c((True, False))) self.send(b"Seven chests lie here, with mimics or treasure hidden inside.\nBut don't worry. Trusty Shannon knows what to do.") # 随机选择 Shannon 的回答策略,包括多少次 lie lie_count = c((1, 2)) Shannon = [truth] * (15 - lie_count) + [lie] * lie_count # 猜猜第几次是在说谎 :-) shuffle(Shannon) for i in range(15): self.send(b"Ask Shannon:") question = self.recv().decode().strip() # 输入问题 for word in question.split(" "): if word not in white_list: # 检查问题中是否包含白名单以外的关键词或符号 self.send("({}) No treasure for dirty hacker!".format(word).encode()) exit(0) res = str(self.calc(Shannon[i], chests, question)) # 计算问题的结果 self.send('Shannon answers: {}!\n'.format(res).encode()) self.send(b"Now open the chests:") # 输入0或1表示每个宝箱的真假,用空格隔开 chests_string = self.recv().decode() return chests == list(map(int, chests_string.strip().split(" "))) def handle(self): signal.alarm(60) # 游戏开始 self.send(b"The Unbreakable Shannon has returned, with some suspicious chests and a far more complicated strategy -- he MAY LIE ONCE OR TWICE! Can you still get all the treasure without losing your head?") for i in range(1): if not self.do_round(): # 执行游戏回合 self.send(b"A chest suddenly comes alive and BITE YOUR HEAD OFF.\n") return self.send("You've found all the treasure! {}\n".format(flag).encode()) # 赢得游戏,获得flag class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer): pass class ForkedServer(socketserver.ForkingMixIn, socketserver.TCPServer): pass if __name__ == "__main__": flag = bytes(os.getenv("FLAG"),"utf-8") # type: ignore # 白名单列表,包含允许在问题中使用的关键词和符号 white_list = ['==', '(', ')', 'C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', '0', '1', 'and', 'or', 'not'] HOST, PORT = '0.0.0.0', 10011 server = ForkedServer((HOST, PORT), Task) server.allow_reuse_address = True print(HOST, PORT) server.serve_forever()