classASTFilter(ast.NodeVisitor):# 继承 NodeVisitor,重写 visit_XXX 方法,对特定节点做检查 defvisit_Import(self, node):# 重写处理import的语句,一旦有 import 就拒绝 for alias in node.names: raise FilterError() self.generic_visit(node)
defvisit_ImportFrom(self, node):# 处理 from xxx import yyy 语句 raise FilterError()
defvisit_Attribute(self, node):# 处理属性访问,如 obj.attr if node.attr in DANGEROUS_ATTRIBUTES:# 如果访问的是危险魔术属性,拒绝 raise FilterError() if node.attr in BANNED_METHODS:# 如果访问的是禁止的方法名,拒绝 raise FilterError() if node.attr in BANNED_FUNCTIONS:# 如果访问的是禁止的函数名(作为属性),拒绝 raise FilterError() self.generic_visit(node)
defvisit_Subscript(self, node):# 处理下标访问,如 obj[key] ifisinstance(node.slice, ast.Constant) andisinstance(node.slice.value, str): key = node.slice.value if key in DANGEROUS_ATTRIBUTES or key in BANNED_METHODS \ or key in BANNED_FUNCTIONS or key in BANNED_MODULES:#禁用了一些模块、函数、魔术方法 raise FilterError() self.generic_visit(node)
def_sandbox_builtins(): b = dict(builtins.__dict__) #受限的沙箱,一些危险方法仍在! b.pop('breakpoint', None) b.pop('input', None) return b
for i in $(seq -w 0 999); do f="treasure_island/chest/box_${i}.txt" if [ -f "$f" ] && ! head -n 1 "$f" | grep -q "^Empty"; then echo"===== $f =====" cat"$f" echo fi done
done ===== treasure_island/chest/box_691.txt ===== 🏆 You found the real treasure chest!
The chest is empty. The gold was moved to /tmp/flag — but a keeper's heartbeat seals it.
Somewhere on this island a heart keeps beating, re-locking /tmp/flag with every beat. Silence the heart, and erase its mark, or it will never let the gold go.
(ps: the watcher below shows no mercy to half-done work.)
直接打开/tmp/flag提示权限不够,根据线索应该是要杀一个进程
1
ps auxww
找到/opt/.whisper/heartbeat.sh,看看内容
1 2 3 4 5 6 7
#!/bin/bash # The Keeper's heartbeat. While this heart beats, the watcher keeps # /tmp/flag sealed. Silence the heartbeat AND erase this script, # and the watcher will set the flag free. whiletrue; do sleep 2 done
for i inrange(100): data = io.recvuntil(b'Input your answer:').decode() print(data)
m = re.search(r'calculate:\s*(\d+)\s*(\S+)\s*(\d+)\s*=', data) ifnot m: print("解析失败") break
a = int(m.group(1)) op = m.group(2) b = int(m.group(3))
if op in ('+', '+'): ans = a + b elif op in ('-', '-', '一', '—', '–'): ans = a - b elif op in ('×', '*', '*', 'x', 'X'): ans = a * b elif op in ('÷', '/', '/'): ans = a // b else: raise ValueError(f"未知运算符: {op!r}")