adworld-crypto-Easy-one

it2024-06-27  42

大致思路:根据加密代码和已知明文和密文,解出秘钥,进而解给定密文

拿到题目,给了一份加密代码,一份测试明文和测试密文,以及一份密文

加密代码在这里 可以分析出来加密逻辑就是 c = (p + (k[i % strlen(k)] ^ t) + i*i) & 0xff; 其中k是秘钥,t是上一个字符(初始为0)

#include <stdlib.h> #include <stdio.h> #include <string.h> int main(int argc, char **argv) { if (argc != 3) { printf("USAGE: %s INPUT OUTPUT\n", argv[0]); return 0; } FILE* input = fopen(argv[1], "rb"); FILE* output = fopen(argv[2], "wb"); if (!input || !output) { printf("Error\n"); return 0; } char k[] = "CENSORED"; char c, p, t = 0; int i = 0; while ((p = fgetc(input)) != EOF) { c = (p + (k[i % strlen(k)] ^ t) + i*i) & 0xff; t = p; i++; fputc(c, output); } return 0; }

那我们可以针对已知明文和密文,试探出秘钥 如果你是把明文复制出来的,一定要记得在后面加上’\n’

def judge(target, p, k, last_c, i): ''' all params are number param target: 目标字符 target param p: 当前字符 p param k: 秘钥字符 k param lastc: 上一个字符 last_c param i: 当前位置 i ''' return target == ((p + (k ^ last_c) + i * i) & 0xff) def genKey(message, message_enc): ''' param message: 明文 message param message: 密文 message_enc ''' key = [] last_c = 0 for i in range(len(message)): p = ord(message[i]) target = message_enc[i] # 试探 k for k in range(0x20, 0x7f): if judge(target, p, k, last_c, i): key.append(k) last_c = p return key

这里可以得到key为: [86, 101, 114, 121, 76, 111, 110, 103, 75, 101, 121, 89, 111, 117, 87, 105, 108, 108, 78, 101, 118, 101, 114, 71, 117, 101, 115, 115, 86, 101] 因为我们知道这个key的长度是有限的,在加密过程中循环利用了 又看出最后两个与前俩个是重合的 所以可以判断出真正的key应该是: [86, 101, 114, 121, 76, 111, 110, 103, 75, 101, 121, 89, 111, 117, 87, 105, 108, 108, 78, 101, 118, 101, 114, 71, 117, 101, 115, 115]

那么key求出来了,我们就可以解密msg_002了 爆破每一个位置的明文即可

def judge(target, p, k, last_c, i): ''' all params are number param target: 目标字符 target param p: 当前字符 p param k: 秘钥字符 k param lastc: 上一个字符 last_c param i: 当前位置 i ''' return target == ((p + (k ^ last_c) + i * i) & 0xff) def decode(msg_enc, key): last_c = 0 flag = '' for i in range(len(msg_enc)): target = msg_enc[i] # 爆破当前位置的明文 for c in range(0x01, 0x7f): if judge(target, c, key[i % len(key)], last_c, i): flag += chr(c) break last_c = ord(flag[i]) return flag

完整代码:

def load_data(filename): with open(filename, 'rb') as fp: data = fp.read() return data def judge(target, p, k, last_c, i): ''' all params are number param target: 目标字符 target param p: 当前字符 p param k: 秘钥字符 k param lastc: 上一个字符 last_c param i: 当前位置 i ''' return target == ((p + (k ^ last_c) + i * i) & 0xff) def genKey(message, message_enc): ''' param message: 明文 message param message: 密文 message_enc ''' key = [] last_c = 0 for i in range(len(message)): p = ord(message[i]) target = message_enc[i] for k in range(0x20, 0x7f): if judge(target, p, k, last_c, i): key.append(k) last_c = p return key def decode(msg_enc, key): last_c = 0 flag = '' for i in range(len(msg_enc)): target = msg_enc[i] # 爆破当前位置的明文 for c in range(0x01, 0x7f): if judge(target, c, key[i % len(key)], last_c, i): flag += chr(c) break last_c = ord(flag[i]) return flag if __name__ == "__main__": message = 'Hi! This is only test message\n' message_enc = load_data('../Easy-one/msg001.enc') key = genKey(message, message_enc) # key = [86, 101, 114, 121, 76, 111, 110, 103, 75, 101, 121, 89, 111, 117, 87, 105, 108, 108, 78, 101, 118, 101, 114, 71, 117, 101, 115, 115, 86, 101] key = key[:-2] print(key) result = decode(load_data('../Easy-one/msg002.enc'), key) print(result)
最新回复(0)