# Visit https://www.lddgo.net/string/pyc-compile-d...
作成日: 2026年1月25日
使用モデル GPT-5.2 Thinking by Chat01
作成日: 2026年1月25日
使用モデル GPT-5.2 Thinking by Chat01
import dis
import struct
def MX(y, z, sum, k, p, e):
return (z >> 5 ^ y >> 2) + (y << 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z)
def btea(v, n, k):
textu32 = lambda x: x & 0xFFFFFFFFL y = v[0] sum = 0 DELTA = 1163219540 if n > 1: z = v[n - 1] q = 6 + 52 // n if q > 0: q -= 1 sum = u32(sum + DELTA) e = u32(sum >> 2) & 3 p = 0 if p < n - 1: y = v[p + 1] z = v[p] = u32(v[p] + MX(y, z, sum, k, p, e)) p += 1 continue y = v[0] z = v[n - 1] = u32(v[n - 1] + MX(y, z, sum, k, p, e)) continue return True
if name == 'main':
print('WOW')
import struct
from crypto import *
from sys import *
import base64
import myalgo
welcome_msg = 'V2VsYzBtMyBUbyBUaGUgV29ybGQgb2YgTDFsYWMgPDM='
input_msg = ':i(G#8T&KiF<F_)F`JToCggs;'
right_msg = 'UmlnaHQsIGNvbmdyYXR1bGF0aW9ucyE='
wrong_msg = 'V3JvbmcgRmxhZyE='
print(b64decode(welcome_msg).decode())
flag = input(a85decode(input_msg).decode())
if not flag.startswith('LilacCTF{') and flag.endswith('}') or len(flag) == 26:
print(b64decode(wrong_msg).decode())
else:
flag = flag[9:25]
res = [
761104570,
1033127419,
0xDE446C05L,
795718415]
key = struct.unpack('<IIII', b'1111222233334444')
input = list(struct.unpack('<IIII', flag.encode()))
myalgo.btea(input, 4, key)
if input[0] == res[0] and input[1] == res[1] and input[2] == res[2] and input[3] == res[3]:
print(b64decode(right_msg).decode())
else:
print(b64decode(wrong_msg).decode())
flag是LilacCTF{}包裹的,给我脚本得到flag
pythondef MX(y,z,sum_,k,p,e): return ((z >> 5 ^ y >> 2) + (y << 3 ^ z << 4)) ^ ((sum_ ^ y) + (k[(p & 3) ^ e] ^ z)) def btea(v, n, k, DELTA=1163219540): # v list of unsigned 32-bit ints, modified in place, return v def u32(x): return x & 0xFFFFFFFF if n > 1: rounds = 6 + 52 // n sum_ = 0 z = v[n-1] for _ in range(rounds): sum_ = u32(sum_ + DELTA) e = (sum_ >> 2) & 3 for p in range(n-1): y = v[p+1] v[p] = u32(v[p] + MX(y,z,sum_,k,p,e)) z = v[p] y = v[0] v[n-1] = u32(v[n-1] + MX(y,z,sum_,k,n-1,e)) z = v[n-1] return v elif n < -1: n = -n rounds = 6 + 52 // n sum_ = u32(rounds * DELTA) y = v[0] for _ in range(rounds): e = (sum_ >> 2) & 3 for p in range(n-1, 0, -1): z = v[p-1] v[p] = u32(v[p] - MX(y,z,sum_,k,p,e)) y = v[p] z = v[n-1] v[0] = u32(v[0] - MX(y,z,sum_,k,0,e)) y = v[0] sum_ = u32(sum_ - DELTA) return v else: return v key = struct.unpack('<IIII', b'1111222233334444') key (825307441, 842150450, 858993459, 875836468)
pythonres = [761104570, 1033127419, 0xDE446C05, 795718415] res [761104570, 1033127419, 3729026053, 795718415]
pythonv = res.copy() btea(v, -4, list(key)) v [1227042847, 2879229022, 1054597645, 2882160295]
pythonplaintext_bytes = struct.pack('<IIII', *v) plaintext_bytes, len(plaintext_bytes), plaintext_bytes.hex() (b'\x1f0#I^\x8c\x9d\xab\r\xe2\xdb>\xa7F\xca\xab', 16, '1f3023495e8c9dab0de2db3ea746caab')
pythontest = list(struct.unpack('<IIII', plaintext_bytes)) enc = test.copy() btea(enc, 4, list(key)) enc, res, enc==res ([761104570, 1033127419, 3729026053, 795718415], [761104570, 1033127419, 3729026053, 795718415], True)
pythondef solve_for_delta(delta): v=res.copy() btea(v,-4,list(key),DELTA=delta) pt=struct.pack('<IIII',*v) return pt for delta in [0x9E3779B9, 1163219540, 0x9E3779B8, 0x61C88647, 0x7F4A7C15]: pt=solve_for_delta(delta) print(hex(delta), pt, pt.hex(), all(32<=b<127 for b in pt))
下面是可直接跑的解密脚本(把 res 用同一套 btea/XXTEA 反向运算解出来),会同时打印 raw bytes、hex、以及用 latin1 强行显示的版本。
按你贴的逻辑,程序对
flag[9:25]这 16 字节做struct.unpack('<IIII', ...),然后btea(input, 4, key)再和res比较;所以我们要做的是对res执行btea(res, -4, key)得到那 16 字节明文。
python# solve_flag.py import struct import base64 DELTA = 1163219540 def MX(y, z, sum_, k, p, e): # 按你给的 myalgo.MX 公式(注意 Python 运算符优先级) return ((z >> 5 ^ y >> 2) + (y << 3 ^ z << 4)) ^ ((sum_ ^ y) + (k[(p & 3) ^ e] ^ z)) def btea(v, n, k): def u32(x): return x & 0xFFFFFFFF if n > 1: # encrypt rounds = 6 + 52 // n sum_ = 0 z = v[n - 1] for _ in range(rounds): sum_ = u32(sum_ + DELTA) e = (sum_ >> 2) & 3 for p in range(n - 1): y = v[p + 1] v[p] = u32(v[p] + MX(y, z, sum_, k, p, e)) z = v[p] y = v[0] v[n - 1] = u32(v[n - 1] + MX(y, z, sum_, k, n - 1, e)) z = v[n - 1] return v if n < -1: # decrypt n = -n rounds = 6 + 52 // n sum_ = u32(rounds * DELTA) y = v[0] for _ in range(rounds): e = (sum_ >> 2) & 3 for p in range(n - 1, 0, -1): z = v[p - 1] v[p] = u32(v[p] - MX(y, z, sum_, k, p, e)) y = v[p] z = v[n - 1] v[0] = u32(v[0] - MX(y, z, sum_, k, 0, e)) y = v[0] sum_ = u32(sum_ - DELTA) return v return v def main(): res = [761104570, 1033127419, 0xDE446C05, 795718415] key = list(struct.unpack("<IIII", b"1111222233334444")) v = res[:] btea(v, -4, key) # 反向解出明文 4*32bit pt = struct.pack("<IIII", *v) # 16 bytes flag_bytes = b"LilacCTF{" + pt + b"}" print("[+] inner raw bytes repr:", repr(pt)) print("[+] inner hex:", pt.hex()) print("[+] inner base64:", base64.b64encode(pt).decode()) # 如果你需要“显示出来”而不是 bytes,可以用 latin1 保持 0-255 一一映射 print("[+] inner latin1:", pt.decode("latin1")) print("[+] full flag bytes repr:", repr(flag_bytes)) if __name__ == "__main__": main()
用这份脚本解出来的 16 字节内层数据是:
1f3023495e8c9dab0de2db3ea746caabb'\x1f0#I^\x8c\x9d\xab\r\xe2\xdb>\xa7F\xca\xab'如果你是要“能提交的平台字符串”,要看题目平台是否接受非 ASCII(很多平台只接受可见字符)。这份解密结果本质上是 16 个任意字节;若平台只收可见字符,通常题目还会再包一层编码(比如 hex/base64)——但你贴的校验代码里没有这一步。你如果把题目服务端/原始附件(尤其是实际的 myalgo 文件)再贴出来,我可以按真实行为把“可提交形式”的 flag 也还原成纯可见字符。