HackThisSite realisitc 6
这次任务是关于密文的破译
ToxiCo_Watch 这个家伙发现了 ToxiCo 化学工厂向附近的河流里排放化学废料,这个工厂的CEO 给生态督查主任 Samuel Smith 发了一个加密的邮件,这个邮件估计是有什么猫腻,然而这个加密算法涉及到了这个家伙知识的盲区,所以希望大家能帮忙破解发给他。
密文分析
由上图可以简单的得出这个是有字符 ‘.’ 和三位数组成的密文,其中还附上了加密算法.
看看这个加密
试着加密一个字符 ‘a’ 并且不带密码
加密后发现这个密文是有三个两位数组成的,并且每个数前缀了一个 ‘.’,然后试着多加密几次看看是不是还是这个结果。
当我点了很多次之后,我发现每次加密的结果都不一样,因此我记录下几次加密的结果,来分析一下。
- 第一次结果 .59.48.-10
- 第二次结果 .33.47.17
- 第三次结果 .8.54.35
观察一下这几次的结果,感觉发现了什么,我们把每次的结果以’.’ 分割求个和
/*
59 + 48 + (-10) = 97
33 + 47 + 17 = 97
8 + 54 + 35 = 97
哎,每次加密后求和的结果相等,都是 97,这里如果有经验的同学
能立马想到这个不就是ASCII码么。
a: 97, b: 98, c: 99
不带密码加密 b
16 + 5 + 77 = 98
不带密码加密 c
30 + 52 + 17 = 99
哎,这下就发现了这个秘密了
1. 每个字符加密后会得到由三个数字组成的一个密文
2. 每次生成的密文都是不同的,但将这个三个数字求和会得到这个字符的ascii码的值
*/
但是啊,我们发现邮件密文是三位数字,而我们测试的字符加密后都是两位数字,这次我们带密码加密试试。
试着加密一个字符 ‘a’ 并且带密码 123456
/*
哎,这次加密结果就有感觉了,还是求和试试
.111.123.172 sum = 406
.163.138.105 sum = 406
啧,这个结果就不对了,为什么不是 ascii码值了呢。远远的超过了,想想看,既然不带密码加密
后求和是ascii值带了密码就不对了,咋搞!猜测一下这个密码本与ascii码值有关,那么密码是不
是也经过了ascii码值得处理呢。
密码中每个字符对应ascii码中的值 1:49,2:50,3:51,4:52,5:53,6:54, 什么都别管先加起来看
看 49+50+51+52+53+54 = 309, 哎发现了没有 309 + 97 = 406。哎!是不是找到了。
我换了不同的密码又测了几次,结果都是由密码字符和密文字符的ascii码值求和的结果。
*/
经过了一系列分析得出以下结论:
- 密码本 ASCII码表;
- 密文由三个数字带 . 组成;
- 密码字符和密文字符的ascii码值求和值等于密文求和值。
啧!结论有了,那么直接撸代码吧,用自己熟悉的语言 C语言 开撸。
本人撸代码注释都是尽量用英文注释(不喜勿喷)。
代码的思路
将邮件密文复制到本地,通过文件读写来解析密文。
- 将密文一个字符一个字符的解析,每组密文求和结果放到链表中;
- 以26个小写字母为字典【因为邮件是英文,所以以26个小写字母为字典,其实也可以直接以生态督查主任的名字 Samuel Smith 为字典(这种方式我还没试过,大家可以试一下,破解密文就是靠合理猜测)】,与密文求和值相减的得到的值出现频率最高的那个就是密码了;
- 将密文求和的值和得到的密码值相减得到最后的解密结果。
#include<stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define DIGITS 3 /* each of them have three digits */
#define GROUPS 3 /* each of a set of three */
#define DOT '.' /* each of them start with a dot */
typedef struct node* ptr_node;
struct node {
int data;
int frequency;
ptr_node next;
};
typedef ptr_node list;
ptr_node malloc_space();
void free_spaces(list lst);
void print_list(list lst);
void list_append(list lst, int data);
int get_password(list lst);
void decrypt(list lst, int passwd);
int main()
{
FILE *fp = NULL;
list lst_character, lst_password;
char code, *digits;
char letter[26] = {'a','b','c','d','e','f','g',
'h','i','j','k','l','m','n',
'o','p','q','r','s','t',
'u','v','w','x','y','z'};
int num_dot = 0,
index,
index_digits = 0,
sum = 0,
index_groups = 0,
passwd;
fp = fopen("encrypted", "r");
if (fp == NULL)
exit(0);
lst_character = malloc_space();
lst_password = malloc_space();
digits = malloc(DIGITS);
printf("format encrypt message...");
while((code = fgetc(fp)) != EOF)
{
if (num_dot && isdigit(code))
*(digits + index_digits++) = code;
if (code == DOT)
num_dot++;
if (index_digits == DIGITS)
{
num_dot = index_digits = 0;
sum += atoi(digits); /* cumulative three-digit integer*/
index_groups++;
}
if (index_groups == GROUPS)
{
list_append(lst_character, sum);
for(index = 0; index < 26; index++)
list_append(lst_password, sum - letter[index]);
index_groups = sum = 0;
}
}
printf("done.\n");
passwd = get_password(lst_password);
decrypt(lst_character, passwd);
free_spaces(lst_character);
free_spaces(lst_password);
fclose(fp);
return 0;
}
/*void free_spaces {{{*/
void free_spaces(list lst)
{
ptr_node ptrnode;
while(lst!= NULL)
{
ptrnode = lst->next;
free(lst);
lst = ptrnode;
}
}
/* }}} */
/*list malloc_space() {{{*/
ptr_node malloc_space()
{
ptr_node ptrnode;
ptrnode = (ptr_node)malloc(sizeof(struct node));
if (ptrnode == NULL)
{
printf("out of space\n");
exit(1);
}
return ptrnode;
}
/*}}}*/
/*void print_list(list lst) {{{*/
void print_list(list lst)
{
printf("list: \n");
lst = lst->next;
while(lst!= NULL)
{
printf("%5d", lst->data);
lst = lst->next;
}
printf("\n");
}
/*}}}*/
/*void list_append(list lst, int data) {{{*/
void list_append(list lst, int data)
{
while(lst->next != NULL)
lst = lst->next;
lst->next = malloc_space();
lst->next->data = data;
}
/*}}}*/
/* int get_password(list lst) {{{ */
int get_password(list lst)
{
ptr_node first_head, second_head, passwd_node;
list lst_frequency = malloc_space();
printf("get encrypt password...");
/* count the number of each letter */
first_head = lst->next;
while(first_head != NULL)
{
first_head->frequency = 0;
second_head = lst->next;
while(second_head != NULL)
{
if(first_head->data == second_head->data)
first_head->frequency++;
second_head = second_head->next;
}
first_head = first_head->next;
}
/* the most of frequent is the password */
first_head = lst->next;
passwd_node = first_head;
while(first_head != NULL)
{
if (passwd_node->frequency < first_head->frequency)
passwd_node = first_head;
first_head = first_head->next;
}
printf("done.\n");
return passwd_node->data;
}
/* }}} */
/* void decrypt(list lst, int passwd) {{{*/
void decrypt(list lst, int passwd)
{
ptr_node head;
head = lst->next;
printf("decrypt...\n\n");
printf("---------------------------------------\n\n");
while(head != NULL)
{
printf("%c", head->data - passwd);
head = head->next;
}
printf("\n\n---------------------------------------");
printf("\n\ndecrypted.\n");
}
/* }}} */
将解密后的邮件发给 ToxiCo_Watch 就可以完成这次任务。