diff --git a/README.md b/README.md new file mode 100644 index 0000000..79b4004 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# 熵密杯附件整理-备注 + +## 题目信息 + +三道初始谜题(CTF)带交互机,解出任意一道可访问场景题目。 + +场景题目共4台机器,5个flag + + + +## 场景题目信息 + +### 网络拓扑 + +网络拓扑图不需要逐一解出即全部给出 + +![](网络拓扑.png) + + + +### 场景解题顺序 + +1. 在Gitea上下载到`shangmibei-master.zip`,在其中解出加密口令解压`协同签名源码文件.zip`,得到flag1 + +2. 然后通过`数据库管理系统数据.zip`中的文件破解数据库管理系统服务器,进入后台拿到flag3和附件 +3. 在第一步解出后的附件中可破解协同签名服务器,交互得到flag2 +4. 在第二步得到的附件中解密流量文件,找到flag4 +5. 在完成上述步骤后伪造总经理签名提交给签名提交服务器,得到最终flag5 + + + +### 其他 + +1. 数据库管理系统服务器有用根密钥指定公钥派发证书的register接口 +2. 协同签名服务器交互流程与`总经理协同签名流量包`相同 +3. 签名提交服务器的给定 msg_hash 为`9e810778a6b177c6aa1799365977adfbeef605c19b5ea917527d1541c1339019` + diff --git a/shangmibei-master/shangmibei/passwordEncryptorV2.c b/shangmibei-master/shangmibei/passwordEncryptorV2.c new file mode 100644 index 0000000..b167195 --- /dev/null +++ b/shangmibei-master/shangmibei/passwordEncryptorV2.c @@ -0,0 +1,148 @@ +#include +#include +#include + +#define ROUND 16 + +//S-Box 16x16 +int sBox[16] = + { + 2, 10, 4, 12, + 1, 3, 9, 14, + 7, 11, 8, 6, + 5, 0, 15, 13 + }; + + +// 将十六进制字符串转换为 unsigned char 数组 +void hex_to_bytes(const char* hex_str, unsigned char* bytes, size_t bytes_len) { + size_t hex_len = strlen(hex_str); + if (hex_len % 2 != 0 || hex_len / 2 > bytes_len) { + fprintf(stderr, "Invalid hex string length.\n"); + return; + } + + for (size_t i = 0; i < hex_len / 2; i++) { + sscanf(hex_str + 2 * i, "%2hhx", &bytes[i]); + } +} + + +// 派生轮密钥 +void derive_round_key(unsigned int key, unsigned char *round_key, int length) { + + unsigned int tmp = key; + for(int i = 0; i < length / 16; i++) + { + memcpy(round_key + i * 16, &tmp, 4); tmp++; + memcpy(round_key + i * 16 + 4, &tmp, 4); tmp++; + memcpy(round_key + i * 16 + 8, &tmp, 4); tmp++; + memcpy(round_key + i * 16 + 12, &tmp, 4); tmp++; + } +} + + +// 比特逆序 +void reverseBits(unsigned char* state) { + unsigned char temp[16]; + for (int i = 0; i < 16; i++) { + unsigned char byte = 0; + for (int j = 0; j < 8; j++) { + byte |= ((state[i] >> j) & 1) << (7 - j); + } + temp[15 - i] = byte; + } + for (int i = 0; i < 16; i++) { + state[i] = temp[i]; + } +} + + +void sBoxTransform(unsigned char* state) { + for (int i = 0; i < 16; i++) { + int lo = sBox[state[i] & 0xF]; + int hi = sBox[state[i] >> 4]; + state[i] = (hi << 4) | lo; + } +} + + +void leftShiftBytes(unsigned char* state) { + unsigned char temp[16]; + for (int i = 0; i < 16; i += 4) { + temp[i + 0] = state[i + 2] >> 5 | (state[i + 1] << 3); + temp[i + 1] = state[i + 3] >> 5 | (state[i + 2] << 3); + temp[i + 2] = state[i + 0] >> 5 | (state[i + 3] << 3); + temp[i + 3] = state[i + 1] >> 5 | (state[i + 0] << 3); + } + for (int i = 0; i < 16; i++) + { + state[i] = temp[i]; + } +} + + +// 轮密钥加 +void addRoundKey(unsigned char* state, unsigned char* roundKey, unsigned int round) { + for (int i = 0; i < 16; i++) { + for (int j = 0; j < 8; j++) { + state[i] ^= ((roundKey[i + round * 16] >> j) & 1) << j; + } + } +} + +// 加密函数 +void encrypt(unsigned char* password, unsigned int key, unsigned char* ciphertext) { + unsigned char roundKeys[16 * ROUND] = {}; // + + // 生成轮密钥 + derive_round_key(key, roundKeys, 16 * ROUND); + + // 初始状态为16字节的口令 + unsigned char state[16]; // 初始状态为16字节的密码 + memcpy(state, password, 16); // 初始状态为密码的初始值 + + // 迭代加密过程 + for (int round = 0; round < ROUND; round++) + { + reverseBits(state); + sBoxTransform(state); + leftShiftBytes(state); + addRoundKey(state, roundKeys, round); + } + + memcpy(ciphertext, state, 16); +} + +void main() { + unsigned char password[] = "pwd:xxxxxxxxxxxx"; // 口令明文固定以pwd:开头,16字节的口令 + unsigned int key = 0xF0FFFFFF; // 4字节的密钥 + unsigned char ciphertext[16]; // 16字节的状态 + + printf("Password: \n"); + printf("%s\n", password); + + encrypt(password, key, ciphertext); + + // 输出加密后的结果 + printf("Encrypted password:\n"); + for (int i = 0; i < 16; i++) { + printf("%02X", ciphertext[i]); + } + printf("\n"); +} + + + + + + + + + + + + + + + diff --git "a/shangmibei-master/shangmibei/\345\212\240\345\257\206\345\217\243\344\273\244\345\257\206\346\226\207.txt" "b/shangmibei-master/shangmibei/\345\212\240\345\257\206\345\217\243\344\273\244\345\257\206\346\226\207.txt" new file mode 100644 index 0000000..2305643 --- /dev/null +++ "b/shangmibei-master/shangmibei/\345\212\240\345\257\206\345\217\243\344\273\244\345\257\206\346\226\207.txt" @@ -0,0 +1 @@ +99F2980AAB4BE8640D8F322147CBA409 \ No newline at end of file diff --git "a/shangmibei-master/shangmibei/\345\215\217\345\220\214\347\255\276\345\220\215\346\272\220\347\240\201\346\226\207\344\273\266.zip" "b/shangmibei-master/shangmibei/\345\215\217\345\220\214\347\255\276\345\220\215\346\272\220\347\240\201\346\226\207\344\273\266.zip" new file mode 100644 index 0000000..d649b41 Binary files /dev/null and "b/shangmibei-master/shangmibei/\345\215\217\345\220\214\347\255\276\345\220\215\346\272\220\347\240\201\346\226\207\344\273\266.zip" differ diff --git "a/shangmibei-master/shangmibei/\346\225\260\346\215\256\345\272\223\347\256\241\347\220\206\347\263\273\347\273\237\346\225\260\346\215\256.zip" "b/shangmibei-master/shangmibei/\346\225\260\346\215\256\345\272\223\347\256\241\347\220\206\347\263\273\347\273\237\346\225\260\346\215\256.zip" new file mode 100644 index 0000000..32682b1 Binary files /dev/null and "b/shangmibei-master/shangmibei/\346\225\260\346\215\256\345\272\223\347\256\241\347\220\206\347\263\273\347\273\237\346\225\260\346\215\256.zip" differ diff --git "a/\345\210\235\345\247\213\350\260\234\351\242\2301/client_one.exe" "b/\345\210\235\345\247\213\350\260\234\351\242\2301/client_one.exe" new file mode 100644 index 0000000..85c64fe Binary files /dev/null and "b/\345\210\235\345\247\213\350\260\234\351\242\2301/client_one.exe" differ diff --git "a/\345\210\235\345\247\213\350\260\234\351\242\2301/encryption.py" "b/\345\210\235\345\247\213\350\260\234\351\242\2301/encryption.py" new file mode 100644 index 0000000..7fa35a3 --- /dev/null +++ "b/\345\210\235\345\247\213\350\260\234\351\242\2301/encryption.py" @@ -0,0 +1,87 @@ +from sympy import Mod, Integer +from sympy.core.numbers import mod_inverse + +# 模数 +N_HEX = "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123" +MODULUS = Integer(int(N_HEX, 16)) +MSG_PREFIX = "CryptoCup message:" + + +# 加密函数 +def encrypt_message(message, key): + # 添加前缀 + message_with_prefix = MSG_PREFIX + message + message_bytes = message_with_prefix.encode('utf-8') + message_len = len(message_bytes) + num_blocks = (message_len + 15) // 16 + blocks = [message_bytes[i * 16:(i + 1) * 16] for i in range(num_blocks)] + + # 进行0填充 + blocks[-1] = blocks[-1].ljust(16, b'\x00') + + encrypted_blocks = [] + + k = key + + # 加密每个分组 + for block in blocks: + block_int = int.from_bytes(block, byteorder='big') + encrypted_block_int = Mod(block_int * k, MODULUS) + encrypted_blocks.append(encrypted_block_int) + k += 1 # 密钥自增1 + + # 将加密后的分组连接成最终的密文 + encrypted_message = b''.join( + int(block_int).to_bytes(32, byteorder='big') for block_int in encrypted_blocks + ) + + return encrypted_message + + +# 解密函数 +def decrypt_message(encrypted_message, key): + num_blocks = len(encrypted_message) // 32 + blocks = [encrypted_message[i * 32:(i + 1) * 32] for i in range(num_blocks)] + + decrypted_blocks = [] + + k = key + + # 解密每个分组 + for block in blocks: + block_int = int.from_bytes(block, byteorder='big') + key_inv = mod_inverse(k, MODULUS) + decrypted_block_int = Mod(block_int * key_inv, MODULUS) + decrypted_blocks.append(decrypted_block_int) + k += 1 # 密钥自增1 + + # 将解密后的分组连接成最终的明文 + decrypted_message = b''.join( + int(block_int).to_bytes(16, byteorder='big') for block_int in decrypted_blocks + ) + + # 去除前缀 + if decrypted_message.startswith(MSG_PREFIX.encode('utf-8')): + decrypted_message = decrypted_message[len(MSG_PREFIX):] + + return decrypted_message.rstrip(b'\x00').decode('utf-8') + + +# 测试 +initial_key = Integer(0x123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0) +message = "Hello, this is a test message." +print("Original Message:", message) + +# 加密 +encrypted_message = encrypt_message(message, initial_key) +print("Encrypted Message (hex):", encrypted_message.hex()) + +# 解密 +decrypted_message = decrypt_message(encrypted_message, initial_key) +print("Decrypted Message:", decrypted_message) + + + + + + diff --git "a/\345\210\235\345\247\213\350\260\234\351\242\2302/client_two.exe" "b/\345\210\235\345\247\213\350\260\234\351\242\2302/client_two.exe" new file mode 100644 index 0000000..87cc651 Binary files /dev/null and "b/\345\210\235\345\247\213\350\260\234\351\242\2302/client_two.exe" differ diff --git "a/\345\210\235\345\247\213\350\260\234\351\242\2302/hmac.py" "b/\345\210\235\345\247\213\350\260\234\351\242\2302/hmac.py" new file mode 100644 index 0000000..7c4e5c3 --- /dev/null +++ "b/\345\210\235\345\247\213\350\260\234\351\242\2302/hmac.py" @@ -0,0 +1,71 @@ +import binascii +from gmssl import sm3 + + +# 读取HMAC key文件 +def read_hmac_key(file_path): + with open(file_path, 'rb') as f: + hmac_key = f.read().strip() + return hmac_key + + +# 生成token +def generate_token(hmac_key, counter): + # 如果HMAC_KEY长度不足32字节,则在末尾补0,超过64字节则截断 + if len(hmac_key) < 32: + hmac_key = hmac_key.ljust(32, b'\x00') + elif len(hmac_key) > 32: + hmac_key = hmac_key[:32] + + # 将计数器转换为字节表示 + counter_bytes = counter.to_bytes((counter.bit_length() + 7) // 8, 'big') + # print("counter_bytes:", binascii.hexlify(counter_bytes)) + + tobe_hashed = bytearray(hmac_key + counter_bytes) + + # print("tobe_hashed:", binascii.hexlify(tobe_hashed)) + + # 使用SM3算法计算哈希值 + sm3_hash = sm3.sm3_hash(tobe_hashed) + + # 将SM3的哈希值转换为十六进制字符串作为token + token = sm3_hash + + return token + + +current_counter = 0 + + +def verify_token(hmac_key, counter, token): + # 生成token + generated_token = generate_token(hmac_key, counter) + global current_counter + # 比较生成的token和输入的token是否相同 + if generated_token == token: + if counter & 0xFFFFFFFF > current_counter: + current_counter = counter & 0xFFFFFFFF + print("current_counter: ", hex(current_counter)) + return "Success" + else: + return "Error: counter must be increasing" + else: + return "Error: token not match" + + +# 假设HMAC key文件路径 +hmac_key_file = 'hmac_key.txt' +# 假设计数器值 +counter = 0x12345678 + +# 读取HMAC key +hmac_key = read_hmac_key(hmac_key_file) + +# 生成token +token = generate_token(hmac_key, counter) +print("Generated token:", token) +print(verify_token(hmac_key, counter, token)) + + + + diff --git "a/\345\210\235\345\247\213\350\260\234\351\242\2303/client_three.exe" "b/\345\210\235\345\247\213\350\260\234\351\242\2303/client_three.exe" new file mode 100644 index 0000000..ce16c52 Binary files /dev/null and "b/\345\210\235\345\247\213\350\260\234\351\242\2303/client_three.exe" differ diff --git "a/\345\210\235\345\247\213\350\260\234\351\242\2303/lwe.py" "b/\345\210\235\345\247\213\350\260\234\351\242\2303/lwe.py" new file mode 100644 index 0000000..cda58d2 --- /dev/null +++ "b/\345\210\235\345\247\213\350\260\234\351\242\2303/lwe.py" @@ -0,0 +1,62 @@ +import sympy as sp +import random + +# 设置参数 +n = 16 # 向量长度 +q = 251 # 模数 + +# 生成随机噪声向量e +e = sp.Matrix(sp.randMatrix(n, 1, min=0, max=1)) # 噪声向量 + +# 生成随机n维私钥向量s和n*n矩阵A +s = sp.Matrix(sp.randMatrix(n, 1, min=0, max=q - 1)) # 私钥向量 +Temp = sp.Matrix(sp.randMatrix(n, n, min=0, max=q - 1)) # 中间变量矩阵Temp +A = Temp.inv_mod(q) # 计算矩阵Temp在模 q 下的逆矩阵作为A + +# 计算n维公钥向量b +b = (A * s + e) % q # 公钥向量b = A * s + e + + +# 加密函数 +def encrypt(message, A, b): + m_bin = bin(message)[2:].zfill(n) # 将消息转换为16比特的二进制字符串 + m = sp.Matrix([int(bit) for bit in m_bin]) # 转换为SymPy矩阵 + x = sp.Matrix(sp.randMatrix(n, n, min=0, max=q // (n * 4))) # 随机产生一个n*n的矩阵x + e1 = sp.Matrix(sp.randMatrix(n, 1, min=0, max=1)) # 随机产生一个n维噪声向量e + c1 = (x * A) % q # 密文部分c1 = x * A + c2 = (x * b + e1 + m * (q // 2)) % q # 密文部分c2 = x * b + e1 + m * q/2 + return c1, c2 + + +# 解密函数 +def decrypt(c1, c2, s): + m_dec = (c2 - c1 * s) % q + m_rec = m_dec.applyfunc(lambda x: round(2 * x / q) % 2) # 还原消息 + m_bin = ''.join([str(bit) for bit in m_rec]) # 将SymPy矩阵转换为二进制字符串 + m_rec_int = int(m_bin, 2) # 将二进制字符串转换为整数 + return m_rec_int + + +# 测试加解密 +message = random.randint(0, 2 ** n - 1) # 要加密的消息,随机生成一个16比特整数 +c1, c2 = encrypt(message, A, b) # 加密 + +print("原始消息: ", message) +print("公钥A=sp.", A) +print("公钥b=sp.", b) +print("密文c1=sp.", c1) +print("密文c2=sp.", c2) + +decrypted_message = decrypt(c1, c2, s) +print("解密后的消息: ", decrypted_message) # 输出解密后的消息 + + + + + + + + + + + diff --git "a/\346\225\260\346\215\256\345\272\223\347\256\241\347\220\206\347\263\273\347\273\237\346\225\260\346\215\256\346\224\273\345\205\213\345\220\216\351\231\204\344\273\266/SM4\345\212\240\345\257\206\350\247\243\345\257\206\344\273\243\347\240\201\357\274\210\347\224\250\344\272\216\345\212\240\345\257\206\346\265\201\351\207\217\345\214\205\346\226\207\344\273\266\357\274\211.py" "b/\346\225\260\346\215\256\345\272\223\347\256\241\347\220\206\347\263\273\347\273\237\346\225\260\346\215\256\346\224\273\345\205\213\345\220\216\351\231\204\344\273\266/SM4\345\212\240\345\257\206\350\247\243\345\257\206\344\273\243\347\240\201\357\274\210\347\224\250\344\272\216\345\212\240\345\257\206\346\265\201\351\207\217\345\214\205\346\226\207\344\273\266\357\274\211.py" new file mode 100644 index 0000000..e01b700 --- /dev/null +++ "b/\346\225\260\346\215\256\345\272\223\347\256\241\347\220\206\347\263\273\347\273\237\346\225\260\346\215\256\346\224\273\345\205\213\345\220\216\351\231\204\344\273\266/SM4\345\212\240\345\257\206\350\247\243\345\257\206\344\273\243\347\240\201\357\274\210\347\224\250\344\272\216\345\212\240\345\257\206\346\265\201\351\207\217\345\214\205\346\226\207\344\273\266\357\274\211.py" @@ -0,0 +1,76 @@ +from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT + +MULTIPLIER = 6364136223846793005 +ADDEND = 1 +MASK = 0xffffffffffffffff +ITERATIONS = 1000 + +# 从文件中读取seed +def read_seed(file_path): + with open(file_path, 'r') as file: + seed = int(file.read().strip(), 16) + print("seed:", hex(seed)) + return seed + +global_seed = read_seed('seed.txt') + +def genRandom(): + global global_seed + # print("global_seed", hex(global_seed)) + for _ in range(ITERATIONS): + global_seed = (global_seed * MULTIPLIER + ADDEND) & MASK + return (global_seed >> 32) & 0xffffffff + +# 16进制字符串转bytes +def HexStringToBytes(hex_str): + return bytes.fromhex(hex_str) + +# bytes转16进制字符串 +def BytesToHexString(byte_seq): + return byte_seq.hex() + +def genSM4KeyOrIV(): + return HexStringToBytes(''.join(f'{genRandom():08x}' for _ in range(4))) + +def SM4Encrypt(data_bytes, key_bytes, iv_bytes): + sm4 = CryptSM4() + sm4.set_key(key_bytes, SM4_ENCRYPT) + return sm4.crypt_cbc(iv_bytes, data_bytes) + +def SM4Decrypt(cipher_bytes, key_bytes, iv_bytes): + sm4 = CryptSM4() + sm4.set_key(key_bytes, SM4_DECRYPT) + return sm4.crypt_cbc(iv_bytes, cipher_bytes) + + +print("############ SM4 Cryptographic Services Start... ###################") + +iv_bytes = genSM4KeyOrIV() +print("iv hex:", BytesToHexString(iv_bytes)) + +key_bytes = genSM4KeyOrIV() +print("key hex:", BytesToHexString(key_bytes)) + +# 从test.pcapng读取数据并加密 +with open('test.pcapng', 'rb') as f1: + plain1_bytes = f1.read() + cipher1_bytes = SM4Encrypt(plain1_bytes,key_bytes,iv_bytes) + +# 写密文数据到cipherText.dat +with open('cipherText.dat', 'wb') as f2: + f2.write(cipher1_bytes) + +# 从cipherText.dat读密文数据 +with open('cipherText.dat', 'rb') as f3: + cipher2_bytes = f3.read() + plain2_bytes = SM4Decrypt(cipher2_bytes,key_bytes,iv_bytes) + +# 解密密文并将明文写入到plainText.pcapng(含flag4) +with open('plainText.pcapng', 'wb') as f4: + f4.write(plain2_bytes) + + + + + + diff --git "a/\346\225\260\346\215\256\345\272\223\347\256\241\347\220\206\347\263\273\347\273\237\346\225\260\346\215\256\346\224\273\345\205\213\345\220\216\351\231\204\344\273\266/\346\200\273\347\273\217\347\220\206\345\215\217\345\220\214\347\255\276\345\220\215\346\265\201\351\207\217\345\214\205\345\212\240\345\257\206\344\275\277\347\224\250\347\232\204iv.txt" "b/\346\225\260\346\215\256\345\272\223\347\256\241\347\220\206\347\263\273\347\273\237\346\225\260\346\215\256\346\224\273\345\205\213\345\220\216\351\231\204\344\273\266/\346\200\273\347\273\217\347\220\206\345\215\217\345\220\214\347\255\276\345\220\215\346\265\201\351\207\217\345\214\205\345\212\240\345\257\206\344\275\277\347\224\250\347\232\204iv.txt" new file mode 100644 index 0000000..107adbe --- /dev/null +++ "b/\346\225\260\346\215\256\345\272\223\347\256\241\347\220\206\347\263\273\347\273\237\346\225\260\346\215\256\346\224\273\345\205\213\345\220\216\351\231\204\344\273\266/\346\200\273\347\273\217\347\220\206\345\215\217\345\220\214\347\255\276\345\220\215\346\265\201\351\207\217\345\214\205\345\212\240\345\257\206\344\275\277\347\224\250\347\232\204iv.txt" @@ -0,0 +1 @@ +90fc5cf2e2f47488a257fd51e0ae615b \ No newline at end of file diff --git "a/\346\225\260\346\215\256\345\272\223\347\256\241\347\220\206\347\263\273\347\273\237\346\225\260\346\215\256\346\224\273\345\205\213\345\220\216\351\231\204\344\273\266/\346\200\273\347\273\217\347\220\206\345\215\217\345\220\214\347\255\276\345\220\215\346\265\201\351\207\217\345\214\205\357\274\210\345\212\240\345\257\206\345\220\216\347\232\204\346\226\207\344\273\266\357\274\211.dat" "b/\346\225\260\346\215\256\345\272\223\347\256\241\347\220\206\347\263\273\347\273\237\346\225\260\346\215\256\346\224\273\345\205\213\345\220\216\351\231\204\344\273\266/\346\200\273\347\273\217\347\220\206\345\215\217\345\220\214\347\255\276\345\220\215\346\265\201\351\207\217\345\214\205\357\274\210\345\212\240\345\257\206\345\220\216\347\232\204\346\226\207\344\273\266\357\274\211.dat" new file mode 100644 index 0000000..0840122 Binary files /dev/null and "b/\346\225\260\346\215\256\345\272\223\347\256\241\347\220\206\347\263\273\347\273\237\346\225\260\346\215\256\346\224\273\345\205\213\345\220\216\351\231\204\344\273\266/\346\200\273\347\273\217\347\220\206\345\215\217\345\220\214\347\255\276\345\220\215\346\265\201\351\207\217\345\214\205\357\274\210\345\212\240\345\257\206\345\220\216\347\232\204\346\226\207\344\273\266\357\274\211.dat" differ diff --git "a/\347\275\221\347\273\234\346\213\223\346\211\221.png" "b/\347\275\221\347\273\234\346\213\223\346\211\221.png" new file mode 100644 index 0000000..b86a6d7 Binary files /dev/null and "b/\347\275\221\347\273\234\346\213\223\346\211\221.png" differ