You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

211 rivejä
5.9 KiB

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <assert.h>
  4. #include "utils/base64.h"
  5. #include "utils/hamming.h"
  6. #include "utils/xor.h"
  7. #include "set1/xor_char_finder.h"
  8. #include <ctype.h>
  9. #include <stdlib.h>
  10. void xor_char_finder(const unsigned char* const p_ciphertext_xor, struct frequency_t& o_frequency, unsigned ciphertext_len)
  11. {
  12. const char printable_ascii[] =" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!\"#$%&'()*+,-./:;<=>?@[\\]_{}|~`^\r\n";
  13. // const char printable_ascii[] =" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!()*+,-./:;<=>?@"; // '^' if I add this one then T3 doesn't work
  14. const unsigned printable_ascii_len = sizeof(printable_ascii)/sizeof(char);
  15. // -----------------------------------------------------------------------------
  16. //
  17. // Keeps xorable characters - those which produce valid ascii text after xoring
  18. // with ciphertext.
  19. //
  20. // -----------------------------------------------------------------------------
  21. int xorable = 0;
  22. unsigned char xorable_chars[printable_ascii_len];
  23. // -----------------------------------------------------------------------------
  24. //
  25. // 2. Check if Xorable. Get those characters for which XOR of ciphertext and
  26. // each byte from cipher text produces some valid text.
  27. //
  28. // -----------------------------------------------------------------------------
  29. for(int i=0; i<printable_ascii_len; ++i)
  30. {
  31. char tmp_hex[ciphertext_len];
  32. char aXorChar = printable_ascii[i];
  33. int whole_ciphertext_xorable=1; // whole ciphertext is xorable with aXorChar
  34. for(int j=0; j<ciphertext_len; ++j)
  35. {
  36. const char xor_chr = p_ciphertext_xor[j]^aXorChar;
  37. if( strchr(printable_ascii, xor_chr) == NULL)
  38. {
  39. whole_ciphertext_xorable=0;
  40. break;
  41. }
  42. }
  43. if(whole_ciphertext_xorable)
  44. {
  45. // printf("Xorable %c\n", aXorChar);
  46. xorable_chars[xorable] = aXorChar;
  47. xorable++;
  48. }
  49. }
  50. // -----------------------------------------------------------------------------
  51. //
  52. // 3. Frequency analysis: select xorable that xors to most probable result
  53. //
  54. // -----------------------------------------------------------------------------
  55. o_frequency.frequency=0;
  56. o_frequency.letter=0x00; // > is not in the set
  57. o_frequency.score = 0;
  58. double fq = 0;
  59. unsigned char* plaintext = new unsigned char[ciphertext_len];
  60. unsigned char ch[1];
  61. if( xorable > 1 )
  62. {
  63. for(int i=0; i<xorable; ++i)
  64. {
  65. xor_repeatedly(&xorable_chars[i], 1, p_ciphertext_xor, ciphertext_len, plaintext);
  66. unsigned long long score = frequency_analysis(plaintext, ciphertext_len);
  67. if(o_frequency.score > 0 && (score == o_frequency.score) )
  68. {
  69. if(tolower(o_frequency.letter) == tolower(xorable_chars[i]))
  70. {
  71. // in case two same letters are found always prefer small one (more probable)
  72. o_frequency.letter = tolower(xorable_chars[i]);
  73. }
  74. else
  75. {
  76. printf("Two results with equal scores.\n");
  77. delete [] plaintext;
  78. return;
  79. }
  80. }
  81. else if(score > o_frequency.score)
  82. {
  83. o_frequency.score = score;
  84. o_frequency.letter = xorable_chars[i];
  85. }
  86. }
  87. }
  88. else if(xorable == 1)
  89. {
  90. o_frequency.letter = xorable_chars[0];
  91. o_frequency.frequency=0;
  92. o_frequency.score = 0;
  93. }
  94. delete [] plaintext;
  95. }
  96. unsigned long long frequency_analysis(const unsigned char* i_text, const unsigned i_len)
  97. {
  98. unsigned long long score=0;
  99. double fq = 0;
  100. for(int j=0; j<i_len; ++j)
  101. {
  102. unsigned char ch = tolower(i_text[j]);
  103. if( (fq = get_frequency(ch)) )
  104. {
  105. unsigned long long tmp = score + fq;
  106. // crash if overflow
  107. assert(tmp>score);
  108. score =tmp;
  109. }
  110. }
  111. return score;
  112. }
  113. int crack_repeted_xor(const char* const i_hex_string, unsigned char* o_buf, const unsigned i_min_block, const unsigned i_max_block)
  114. {
  115. unsigned len = strlen(i_hex_string)/2;
  116. unsigned char* ciphertext_xor = new unsigned char[len];
  117. convert_string_to_hex(i_hex_string, strlen(i_hex_string), ciphertext_xor);
  118. unsigned char found_key[120];
  119. int keysize = choose_min_block_size(ciphertext_xor, len, i_min_block, i_max_block);
  120. /*
  121. fprintf(stdout, "Key Size: %d Hex Len: %d, Min key size: %d, SlideNb: %d\n",
  122. keysize,
  123. len,
  124. keysize,
  125. len/keysize);
  126. */
  127. const unsigned int block_nb = len / keysize;
  128. unsigned char* slide = new unsigned char[block_nb];
  129. for(int j=0; j<keysize; ++j)
  130. {
  131. memset(slide, '\0', block_nb);
  132. int i=0;
  133. for(; i<block_nb; ++i)
  134. {
  135. slide[i] = ciphertext_xor[i*keysize + j];
  136. }
  137. struct frequency_t max_score;
  138. xor_char_finder(slide, max_score, block_nb);
  139. // printf("> Score %d %c\n", max_score.score, max_score.letter);
  140. found_key[j]=max_score.letter;
  141. }
  142. xor_repeatedly(found_key, keysize, ciphertext_xor, len, o_buf);
  143. delete [] slide;
  144. delete [] ciphertext_xor;
  145. return keysize;
  146. }
  147. double get_frequency(char c)
  148. {
  149. // -----------------------------------------------------------------------------
  150. //
  151. // Array keeps letters that occure most frequently in english language. They are
  152. // ordered from most frequent to least frequent
  153. //
  154. // -----------------------------------------------------------------------------
  155. frequency_set frequency;
  156. for(int k=0; k<FREQUENT_LETTERS_AMOUNT; ++k)
  157. {
  158. if(frequency[k].letter == tolower(c))
  159. {
  160. return frequency[k].frequency;
  161. }
  162. }
  163. return 0;
  164. }
  165. int find_best_keysize(const char* i_hex_bytes, const unsigned i_len, const int i_min_keysize, const int i_max_keysize)
  166. {
  167. int score, best_score, block_size;
  168. score=best_score=block_size=0;
  169. int current_keysize = i_min_keysize;
  170. unsigned char* buf = (unsigned char*) malloc(i_len);
  171. while( current_keysize<i_max_keysize )
  172. {
  173. memset(buf, 0, i_len);
  174. current_keysize = crack_repeted_xor(i_hex_bytes, buf, current_keysize, i_max_keysize);
  175. // check again if keysize is in the range. Otherwise range may not be respected.
  176. if(current_keysize>i_max_keysize)
  177. break;
  178. score=frequency_analysis(buf, i_len);
  179. if(score>best_score)
  180. {
  181. best_score = score;
  182. block_size = current_keysize;
  183. }
  184. current_keysize++;
  185. }
  186. free(buf);
  187. return block_size;
  188. }