-
-
[原创]第二题:巳时·绿光幽语 wp
-
发表于: 4天前 2
-
题目 WP
题目分析
程序是 PyInstaller 打包的 Python 3.13 程序,先用 pyinstxtractor.py 解包:
python pyinstxtractor.py 题目.exe
解包后看到:
main.pyc
python313.dll
PYZ.pyz
base_library.zip
但是 main.pyc 很小,反汇编后只有:
import sys
sys.exit(0)
说明 main.pyc 是干扰项,真正逻辑不在解包出来的入口文件中,而是在运行时动态加载或修改的代码里。
定位真实代码
运行程序后提示:
提示,需要还原的代码
def my_function():
print("恭喜成功!")
请输入key还原代码(请输入6个字符)
程序运行时会调用 Python 的 marshal 加载代码对象,因此可以用 Frida hook:
PyMarshal_ReadObjectFromString
将传入的 marshal 字节码 dump 出来,再用 xdis 反汇编 Python 3.13 字节码。
在 dump 出来的运行时代码对象中发现关键变量:
my_function
input
b_key
replace
succ
说明程序会读取 6 字符 key,然后动态替换 my_function.__code__。
核心逻辑
反汇编后还原出关键逻辑:
def my_function():
print(666)
key = input()
if len(key) != 6:
retry
b_key = key.encode()
c = b'\xecbmucryb6tcr*c\x03ucryb6tCr\x1eb'
buf = b''
for i in range(len(c)):
buf += (c[i] ^ b_key[i % len(b_key)]).to_bytes(1)
my = my_function.__code__
my = my.replace(co_code=buf)
succ = b'\x9f\xe3\x9b\x91\xf5\xee\x9f\xea\xa6\x91\xe9\xed\x96\xde\xb7'
buf = b''
for i in range(len(succ)):
buf += (succ[i] ^ b_key[i % len(b_key)]).to_bytes(1)
my = my.replace(co_consts=(None, buf.decode("utf-8")))
my_function.__code__ = my
my_function()
也就是说,输入的 key 会作为循环异或密钥,用来解密:
1. my_function 的 co_code
2. 成功字符串
求解 key
原始 my_function 是:
def my_function():
print(666)
它的原始 co_code 为:
95005b0100000000000000005301350100000000000020006700
密文 c 为:
c = b'\xecbmucryb6tcr*c\x03ucryb6tCr\x1eb'
因此可以直接异或得到 key 流:
c = b'\xecbmucryb6tcr*c\x03ucryb6tCr\x1eb'
orig = bytes.fromhex(
"95005b0100000000000000005301350100000000000020006700"
)
ks = bytes(c[i] ^ orig[i] for i in range(len(c)))
print(ks)
输出:
b'yb6tcryb6tcryb6tcryb6tcryb'
可以看到 key 流以 6 字节为周期重复:
yb6tcr
验证
用 yb6tcr 解密成功字符串:
succ = bytes.fromhex("9fe39b91f5ee9feaa691e9ed96deb7")
key = b"yb6tcr"
print(bytes(succ[i] ^ key[i % 6] for i in range(len(succ))).decode())
输出:
恭喜成功!
将 yb6tcr 输入程序,也成功输出:
恭喜成功!
最终答案
yb6tcr
赞赏
赞赏
雪币:
留言: