TJCTF部分wp
01
c
解密逻辑简述
1. enc.py使用了培根密码(Baconian Cipher)将flag.txt中的字符转为二进制(5位),用大写/小写字母表示。
2. 再对结果的每个字符执行chr(ord(c)-13)加密,写入out.txt。
3. 因此我们需要:对out.txt中每个字符执行chr(ord(c)+13)还原出大小写编码,再解析出大小写序列,映射回原始的Baconian二进制,再解出明文。
baconian = {'00000': 'a', '00001': 'b','00010': 'c', '00011': 'd','00100': 'e', '00101': 'f','00110': 'g', '00111': 'h','01000': 'i', '01001': 'k','01010': 'l', '01011': 'm','01100': 'n', '01101': 'o','01110': 'p', '01111': 'q','10000': 'r', '10001': 's','10010': 't', '10011': 'u','10100': 'w', '10101': 'x','10110': 'y', '10111': 'z'}withopen("out.txt", "r") as f:encrypted = f.read().strip()decoded = ''.join([chr(ord(c) + 13) for c in encrypted])bits = []for i inrange(0, len(decoded), 5):group = decoded[i:i+5]bit_string = ''.join(['1' if c.isupper() else '0' for c in group])bits.append(bit_string)plaintext = ''.join([baconian.get(b, '?') for b in bits])print("Decrypted flag:", plaintext)
解密后的字符为tictfoinkooinkoooinkooooink
把tictf改为tjctf,后面的东西用花括号包起来就是flag。
02
alchemist-recipe
解密脚本
import hashlibSNEEZE_FORK = "AurumPotabileEtChymicumSecretum"WUMBLE_BAG = 8def glorbulate_sprockets_for_bamboozle(blorbo):zing = {}yarp = hashlib.sha256(blorbo.encode()).digest()zing['flibber'] = list(yarp[:WUMBLE_BAG])zing['twizzle'] = list(yarp[WUMBLE_BAG:WUMBLE_BAG+16])glimbo = list(yarp[WUMBLE_BAG+16:])snorb = list(range(256))sploop = 0for _ in range(256):for z in glimbo:wob = (sploop + z) % 256snorb[sploop], snorb[wob] = snorb[wob], snorb[sploop]sploop = (sploop + 1) % 256zing['drizzle'] = snorbreturn zingdef descrungle_crank(chunk, sprockets):wiggle = sprockets['flibber']quix = sprockets['twizzle']drizzle = sprockets['drizzle']# 反向排序waggly = sorted([(wiggle[i], i) for i in range(WUMBLE_BAG)])zort = [oof for _, oof in waggly]unsorted = [0] * WUMBLE_BAGfor y in range(WUMBLE_BAG):x = zort[y]unsorted[x] = chunk[y]splatted = bytes(unsorted)# 异或还原zonked = bytes([splatted[i] ^ quix[i % len(quix)] for i inrange(WUMBLE_BAG)])# drizzle 的逆映射drizzle_inv = [0] * 256for i, val in enumerate(drizzle):drizzle_inv[val] = i# 原始数据恢复original = bytes([drizzle_inv[b] for b in zonked])return originaldef unsnizzle_bytegum(data, jellybean):decrypted = b""for i in range(0, len(data), WUMBLE_BAG):chunk = data[i:i+WUMBLE_BAG]decrypted += descrungle_crank(chunk, jellybean)# 去除 PKCS#7 paddingpad_len = decrypted[-1]if all(p == pad_len for p in decrypted[-pad_len:]):decrypted = decrypted[:-pad_len]return decrypteddef decrypt():with open("encrypted.txt", "r") as f:encrypted_hex = f.read().strip()encrypted_bytes = bytes.fromhex(encrypted_hex)jellybean = glorbulate_sprockets_for_bamboozle(SNEEZE_FORK)decrypted = unsnizzle_bytegum(encrypted_bytes, jellybean)print("Decrypted flag:", decrypted.decode())if __name__ == "__main__":decrypt()
03
theartofwar
RSA加密,类型是多模数攻击
from Crypto.Util.number import long_to_bytesfrom sympy.ntheory.modular import crtfrom gmpy2 import irootimport re# 读取 output.txtwith open("output.txt", "r") as f:data = f.read()# 提取 e、n、c 值e = int(re.search(r"es*=s*(d+)", data).group(1))pairs = re.findall(r"nd+s*=s*(d+)s+cd+s*=s*(d+)", data)n_list = [int(n) for n, _ in pairs]c_list = [int(c) for _, c in pairs]# 使用中国剩余定理合并C, N = crt(n_list, c_list)# 计算 e 次根(m ≈ (C)^(1/e))m_root, exact = iroot(C, e)if not exact:print("Warning: root not exact, result may be incorrect.")# 转换为原始明文flag = long_to_bytes(m_root)print("Recovered flag:", flag)
04
seeds/种子
这道题是一个随机数预测攻击+AES ECB解密的问题。
from Crypto.Cipher import AESfrom Crypto.Util.Padding import unpadfrom datetime import datetime, timedeltaimport timeclass RandomGenerator:def __init__(self, seed, modulus=2 ** 32, multiplier=157, increment=1):if isinstance(seed, str):seed = int.from_bytes(seed.encode(), "big")self.seed = seedself.m = modulusself.a = multiplierself.c = incrementdef randint(self, bits: int):self.seed = (self.a * self.seed + self.c) % self.mresult = self.seed.to_bytes(4, "big")while len(result) < bits // 8:self.seed = (self.a * self.seed + self.c) % self.mresult += self.seed.to_bytes(4, "big")return int.from_bytes(result, "big") % (2 ** bits)def randbytes(self, length: int):return self.randint(length * 8).to_bytes(length, "big")ciphertext = bytes.fromhex('...') # 替换为你从服务拿到的 ciphertext# 设定服务器可能启动时间范围(调整为你的时区偏移)start = datetime(2025, 6, 7, 8, 0, 0) # 可能是早上8点end = datetime(2025, 6, 7, 10, 0, 0) # 到10点delta = timedelta(seconds=1)print("Trying time window:", start, "to", end)cur = startwhile cur <= end:seed_str = time.asctime(cur.timetuple())rng = RandomGenerator(seed_str)key = rng.randbytes(32)cipher = AES.new(key, AES.MODE_ECB)try:plain = unpad(cipher.decrypt(ciphertext), 16)if b'tjctf{' in plain:print("[!] Found:", plain.decode())breakexcept:passcur += delta
可以直接使用kali去nc tjc.tf 31493
我们需要的这个东西,将这串代码放到这个地方就可以得出完整的解密脚本
ciphertext = bytes.fromhex('...') # 替换为你从服务拿到的 ciphertext
ciphertext =b'I<Bx8f7x1ax9dxbaxcb=Dz8x97xe9cxb7xafx15x01xf4xd9xd9xc2x83jmx1axa2xdax10xb5'
-END-
原文始发于微信公众号(晨星安全团队):TJCTF部分Crypto-wp
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-


评论