尝试给出解密流量的脚本,并给出结果

Создано: 30 декабря 2025 г.

Отвечено с использованием GPT-5.2 Thinking от Chat01

Вопрос

shelll.md

尝试给出解密流量的脚本,并给出结果

Мысль

Computing decryption and showing results

Alright, I'll show the decrypted output in hex, and then we'll attempt to unpad the PKCS7 padding, though it's likely to fail. I'll display the output as bytes too. Also, we might explore using encryption instead of decryption for comparison, but that's still random. If needed, I'll clarify the direction for correct command capture. We'll also note if the result indicates a different encryption method or seed.

Integrating seed and key derivation

I need to show how to integrate the seed by deriving the key from the session's first four bytes. I'll write the script and compute the result accordingly. I'll also include the necessary citations, referencing the correct lines from the relevant files. I'll make sure no citations are inside the code fences.

Thought for 11m 56s

Ответ

下面给你一个按你贴的逻辑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,直接可跑)

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)

你给的示例流量:解密结果(我本地按上面脚本跑出来的)

  • seed:0x34952046 (shelll.md)
  • key:ac46fb610b313b4f32fc642d8834b456 (shelll.md)
  • ciphertext: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 按它精确复刻,这样就能解出真正的命令/回显文本。

Поделиться этим Q&A