下载文件解压得:
加密代码:
#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;
}
是使用k[]和input经过加密算法后生成output。
文件msg001.enc和msg001是对应的,应该是用k[]和msg001(input)生成了msg001.enc(output),在这个加密过程中,k[]好像是个常量,代码中给出的应该是个例子,不是真实的k[],对msg001加密后并不是msg001.enc,看来我们需要先找到这个真实的k[]了。
根据msg001和msg001.enc,把算法逆过来算出k[]:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
if (argc != 2) {
printf("USAGE: %s INPUT OUTPUT\n", argv[0]);
return 0;
}
//FILE* input = fopen(argv[1], "rb");
FILE* input = fopen(argv[1], "rb");
if (!input) {
printf("Error\n");
return 0;
}
char c, p, t = 0;
int i = 0;
char w[] = "Hi! This is only test message\n"; //原来input中的值
unsigned int j = 0;
while ((p = fgetc(input)) != EOF) {
// printf("read %d", p);
for (j=31;j<125;j++) {
c = (p - (j ^ t) - i*i) & 0xff;
if (c == w[i]) {
printf("%c",j);
t = c;
i++;
break;
}
}
}
return 0;
}
编译之后对main传参:
int main(int argc, char **argv)
argc表示参数个数,即是后面argv数组的元素个数,不用输入,会根据传入参数计算,只需传递argv数组的元素即可。
argv数组的第一个元素(argv[0])是程序名,传参的时候注意argc的值加上这个元素,其余的元素自行传递。
这样就得到k[]:VeryLongKeyYouWillNeverGuess
然后利用k再对msg002.enc进行解密,得到msg002.enc对应的明文:
#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 c, p, t = 0;
int i = 0;
char k[] = "VeryLongKeyYouWillNeverGuess";
i = 0;
c, p, t = 0;
int g = 0;
while ((p = fgetc(input)) != EOF) {
c = (p - (k[i % strlen(k)] ^ t) - i*i) & 0xff;
printf("Decrypting %x i=%d t=%d k=%d -> %d\n",p,i,t,(k[i % strlen(k)] ^ t),c);
t = c;
i++;
//printf("%c",c);
fputc(c, output);
g++;
if (g>450) {break;}
}
return 0;
}
最终得到明文:
The known-plaintext attack (KPA) is an attack model for cryptanalysis where the attacker has samples of both the plaintext (called a crib), and its encrypted version (ciphertext). These can be used to reveal further secret information such as secret keys and code books. The term "crib" originated at Bletchley Park, the British World War II decryption operation.
The flag is CTF{6d5eba48508efb13dc87220879306619}
駕牗[?顆剝.}9壶?F*損犄溦烇?5蹈
?