尝试给出解密流量的脚本,并给出结果
Создано: 30 декабря 2025 г.
Отвечено с использованием GPT-5.2 Thinking от Chat01
Создано: 30 декабря 2025 г.
Отвечено с использованием GPT-5.2 Thinking от Chat01
尝试给出解密流量的脚本,并给出结果
下面给你一个按你贴的逻辑(srand(seed) -> rand() x4 -> 生成 16B key -> ECB 16B 分组 -> 去 PKCS#7 padding)的 Python 脚本,并把你给的示例流量跑出来的“解密结果”一并贴出来。
依据:程序先从 socket 收 4 字节 seed,做一次 32-bit reverse 后
srand(seed),再rand()四次生成v8[4],并用它做密钥扩展;后续收包长度必须是 16 的倍数,然后做 ECB 分组解密,最后按末字节做 padding 截断。 (shelll.md)
你已经从 seed=0x34952046 还原出rand[0..3],并映射得到密钥ac46fb610b313b4f32fc642d8834b456。 (shelll.md)
(另外按要求附上你上传文件的引用标记:(shelll.md))
python#!/usr/bin/env python3 # -*- coding: utf-8 -*- import ctypes # ====== 你给的示例 ====== SEED = 0x34952046 CIPHERTEXT_HEX = "de7cc756e5c97fed18a72a95af102dac48dc0810752bd7755157e5909974cbe0ce87241e7f01e3169e7a763a22008029" # ====== SM4 常量(与 FK/CK 形式一致;你代码里 dword_2120/dword_2140)====== FK = [0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC] CK = [ 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269, 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9, 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249, 0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9, 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229, 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299, 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209, 0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279 ] # S-Box(sub_1229 里的 byte_2020) SBOX = [ 0xD6,0x90,0xE9,0xFE,0xCC,0xE1,0x3D,0xB7,0x16,0xB6,0x14,0xC2,0x28,0xFB,0x2C,0x05, 0x2B,0x67,0x9A,0x76,0x2A,0xBE,0x04,0xC3,0xAA,0x44,0x13,0x26,0x49,0x86,0x06,0x99, 0x9C,0x42,0x50,0xF4,0x91,0xEF,0x98,0x7A,0x33,0x54,0x0B,0x43,0xED,0xCF,0xAC,0x62, 0xE4,0xB3,0x1C,0xA9,0xC9,0x08,0xE8,0x95,0x80,0xDF,0x94,0xFA,0x75,0x8F,0x3F,0xA6, 0x47,0x07,0xA7,0xFC,0xF3,0x73,0x17,0xBA,0x83,0x59,0x3C,0x19,0xE6,0x85,0x4F,0xA8, 0x68,0x6B,0x81,0xB2,0x71,0x64,0xDA,0x8B,0xF8,0xEB,0x0F,0x4B,0x70,0x56,0x9D,0x35, 0x1E,0x24,0x0E,0x5E,0x63,0x58,0xD1,0xA2,0x25,0x22,0x7C,0x3B,0x01,0x21,0x78,0x87, 0xD4,0x00,0x46,0x57,0x9F,0xD3,0x27,0x52,0x4C,0x36,0x02,0xE7,0xA0,0xC4,0xC8,0x9E, 0xEA,0xBF,0x8A,0xD2,0x40,0xC7,0x38,0xB5,0xA3,0xF7,0xF2,0xCE,0xF9,0x61,0x15,0xA1, 0xE0,0xAE,0x5D,0xA4,0x9B,0x34,0x1A,0x55,0xAD,0x93,0x32,0x30,0xF5,0x8C,0xB1,0xE3, 0x1D,0xF6,0xE2,0x2E,0x82,0x66,0xCA,0x60,0xC0,0x29,0x23,0xAB,0x0D,0x53,0x4E,0x6F, 0xD5,0xDB,0x37,0x45,0xDE,0xFD,0x8E,0x2F,0x03,0xFF,0x6A,0x72,0x6D,0x6C,0x5B,0x51, 0x8D,0x1B,0xAF,0x92,0xBB,0xDD,0xBC,0x7F,0x11,0xD9,0x5C,0x41,0x1F,0x10,0x5A,0xD8, 0x0A,0xC1,0x31,0x88,0xA5,0xCD,0x7B,0xBD,0x2D,0x74,0xD0,0x12,0xB8,0xE5,0xB4,0xB0, 0x89,0x69,0x97,0x4A,0x0C,0x96,0x77,0x7E,0x65,0xB9,0xF1,0x09,0xC5,0x6E,0xC6,0x84, 0x18,0xF0,0x7D,0xEC,0x3A,0xDC,0x4D,0x20,0x79,0xEE,0x5F,0x3E,0xD7,0xCB,0x39,0x48 ] def rotl32(x, n): x &= 0xFFFFFFFF return ((x << n) | (x >> (32 - n))) & 0xFFFFFFFF def tau(a): return ((SBOX[(a >> 24) & 0xFF] << 24) | (SBOX[(a >> 16) & 0xFF] << 16) | (SBOX[(a >> 8) & 0xFF] << 8) | (SBOX[a & 0xFF])) & 0xFFFFFFFF # sub_1311 对应的 L'(用于密钥扩展):B ^ (B<<<13) ^ (B<<<23) def L_key(b): return b ^ rotl32(b, 13) ^ rotl32(b, 23) # sub_125E 未在你贴的片段里出现;这里按“标准 SM4 轮函数 L”实现: # B ^ (B<<<2) ^ (B<<<10) ^ (B<<<18) ^ (B<<<24) def L_enc(b): return b ^ rotl32(b, 2) ^ rotl32(b, 10) ^ rotl32(b, 18) ^ rotl32(b, 24) def T_key(x): # 用于轮密钥 return L_key(tau(x)) def T_enc(x): # 用于数据轮函数 return L_enc(tau(x)) def key_schedule(key16: bytes): MK = [int.from_bytes(key16[i*4:(i+1)*4], "big") for i in range(4)] K = [(MK[i] ^ FK[i]) & 0xFFFFFFFF for i in range(4)] rk = [] for i in range(32): nxt = (K[i] ^ T_key(K[i+1] ^ K[i+2] ^ K[i+3] ^ CK[i])) & 0xFFFFFFFF K.append(nxt) rk.append(nxt) return rk def crypt_block(block16: bytes, rk32): X = [int.from_bytes(block16[i*4:(i+1)*4], "big") for i in range(4)] for i in range(32): X.append((X[i] ^ T_enc(X[i+1] ^ X[i+2] ^ X[i+3] ^ rk32[i])) & 0xFFFFFFFF) Y = [X[35], X[34], X[33], X[32]] return b"".join(y.to_bytes(4, "big") for y in Y) def ecb_decrypt(cipher: bytes, key16: bytes): rk = key_schedule(key16) rk_rev = list(reversed(rk)) # 解密:倒序轮密钥 return b"".join(crypt_block(cipher[i:i+16], rk_rev) for i in range(0, len(cipher), 16)) def pkcs7_unpad(data: bytes): pad = data[-1] if not (1 <= pad <= 16) or data[-pad:] != bytes([pad]) * pad: return None return data[:-pad] def derive_key_from_seed_glibc(seed: int) -> bytes: libc = ctypes.CDLL("libc.so.6") libc.srand(ctypes.c_uint(seed)) r = [(libc.rand() & 0xFFFFFFFF) for _ in range(4)] key = b"".join(x.to_bytes(4, "little") for x in r) # 与你“映射到内存”的方式一致 print("[*] rand =", [f"0x{x:08x}" for x in r]) print("[*] key =", key.hex()) return key if __name__ == "__main__": ct = bytes.fromhex(CIPHERTEXT_HEX) key = derive_key_from_seed_glibc(SEED) pt = ecb_decrypt(ct, key) print("[*] plaintext(hex) =", pt.hex()) unpadded = pkcs7_unpad(pt) if unpadded is None: print("[!] PKCS#7 unpad failed (last byte =", pt[-1], ")") else: print("[*] plaintext(unpadded) =", unpadded) try: print("[*] plaintext(utf-8) =", unpadded.decode("utf-8", errors="replace")) except Exception as e: print("[!] decode failed:", e)
0x34952046 (shelll.md)ac46fb610b313b4f32fc642d8834b456 (shelll.md)de7cc756e5c97fed...22008029 (shelll.md)解密得到的 plaintext(hex) 是:
79a5694e8974c185715bddf98c2fc62db96d7427e0329ed94c733b2f6079d04267beb4ef37820f4f514bd5ddf165a885
并且这个结果 不满足 PKCS#7 padding(末字节是 0x85,不在 1..16 范围),所以按你 main 里那段“按末字节去 padding”的逻辑无法截断成命令字符串。 (shelll.md)
你贴出来的代码里缺了 sub_125E 的实现(数据轮函数那一段)。(shelll.md)
我在脚本里把它按“标准 SM4 的 L 线性变换”写了;但如果你样本里的 sub_125E 不是标准 SM4(比如旋转常数/组合不同),就会出现你现在看到的这种“解出来不像可打印字符串、padding 也不对”的情况。
如果你把 sub_125E 的反编译内容也补上(或把二进制丢出来),我可以把脚本里的 L_enc/T_enc 按它精确复刻,这样就能解出真正的命令/回显文本。