【问题标题】:Decrypt an tex file encrypted with rand()解密使用 rand() 加密的 tex 文件
【发布时间】:2018-03-27 16:35:23
【问题描述】:

Question I'm trying to solve

我想采取的方法是暴力破解所有可能的密钥(种子),直到找到正确的密钥。我知道 tex 文件中的第一个字符,所以这些是我正在测试的。当我找到正确的序列时,我会停止程序并输出密钥。

/* The ISO/IEC 9899:1990 edition of the C standard */

#include <stdio.h>
#include <time.h>
#include <iostream>

//#define RAND_MAX 32767
static unsigned long int next = 1;
int rand(void) // RAND_MAX assumed to be 32767
{
    next = next * 1103515245 + 12345;
    return (unsigned int)(next/65536) % 32768;
}
void srand(unsigned int seed)
{
    next = seed;
}

using namespace std;

//Return a byte at a time of the rand() keystream
 char randchar() { 
  static int key;
  static int i = 0;

  i = i % 4;
  if (i == 0) key = rand();
  return ((char *)(&key))[i++];
}

int main(int argc, const char* argv[]) {


  for (unsigned int i = time(NULL); i >= 0; i--) //Try all possible return values of time(NULL) since today
  {

      srand(i); 

      cout << "Trying with time(NULL) = " << i << endl;

      FILE *input, *output;
      input = fopen("Homework1b-Windows.tex.enc", "r");
      output = fopen("Homework1b.tex", "w");

      int c,rc, test;
      int pos;
      pos = 0;
      bool pos0, pos1, pos2, pos3, pos4, pos5;
      pos0 = pos1 = pos2 = pos3 = pos4 = pos5 = false;
      char temp1, temp2;

      while ((c = fgetc(input)) != EOF) {
        rc=randchar();
        fputc(c^rc,output);

        test = c^rc;

        temp1 = (char)test;


        temp2 = '\\';

        if ((pos == 0) && (temp1 == temp2))
        {
                 pos0 = true;
        } 

        temp2 = 'd';

        if ((pos == 1) && (temp1 == temp2))
        {
                 pos1 = true;
        }

        /*

        temp2 = 'o';

        if ((pos == 2) && (temp1 == temp2))
        {
                 pos2 = true;
        }

        temp2 = 'c';

        if ((pos == 3) && (temp1 == temp2))
        {
                 pos3 = true;
        }

        */

        temp2 = 'u';

        if ((pos == 4) && (temp1 == temp2))
        {
                 pos4 = true;
        }

        temp2 = 'm';
        if ((pos == 5) && (temp1 == temp2))
        {
                 pos5 = true;
        }

        pos++;

      }
      fclose(input);
      fclose(output);

      if (pos0 && pos1 && pos4 && pos5)
      {
         cout << endl << "Cracked. The seed is time(NULL) = " << i << endl;
         break;
      }
  }

  system("pause");


}

我知道解密后的tex文件以“\document”开头。

我面临的问题是代码永远不会终止。它永远找不到正确的密钥(种子)。

有什么帮助吗?

谢谢。

【问题讨论】:

  • 请提供simplified code。考虑简单地从输入文件读取并写入另一个文件以更快地识别问题
  • 你应该用一个已知的值来测试你的解码器,然后在它寻找这个值的时候测试它。
  • for (unsigned int i = time(NULL); i &gt;= 0; i--) 将永远循环,因为 i 将永远大于 0
  • 这是作业。调试,跟踪变量的执行或去“穴居人”并添加打印语句。和/或思考,思考执行,在脑海中思考程序步骤。这就是你学习的方式。
  • 在重新发布此问题之前,您是否阅读过fgrieu's comment?它清楚地指出了一个错误“没有在每次新的解密尝试时将 randchar 的变量 i 归零?”你懒得修。

标签: c++ random cryptography


【解决方案1】:

您的想法是合理的(暴力破解密钥从“现在”返回并寻找匹配的纯文本),但您的实现可以改进。 例如,您不应该在循环内打开和关闭文件。

如果你看randchar()是如何实现的,直接调用rand()可能效率更高,一次比较四个字符。

其实你可以计算一次密文和明文的xor,只需将rand()返回的值与它进行比较即可。

为了进一步加快速度,您可以直接在源文件中写入加密和纯文本的前 8 个字符,使用一个简单的函数将四个 char 打包成一个 int

int to_int(const char buffer[4]) {
  return (static_cast<int>(buffer[0])) + 
         (static_cast<int>(buffer[1]) <<  8) +
         (static_cast<int>(buffer[2]) << 16) +
         (static_cast<int>(buffer[3]) << 24);
}

main()内部

  const int crypt1 = to_int("\x57\x12\x6f\x63");
  const int crypt2 = to_int("\x51\x59\x65\x6e");
  const int plain1 = to_int("\\doc");
  const int plain2 = to_int("umen");
  const int target1 = plain1 ^ crypt1;
  const int target2 = plain2 ^ crypt2;

现在剩下的就是遍历所有可能的键并寻找匹配项(正如@Raxvan 指出的那样,您不应该检查key &gt;= 0,否则循环将永远不会完成):

  unsigned int key = time(nullptr);
  for (; key > 0; --key)
  {
      srand(key);
      if (rand() == target1 and rand() == target2) {
      std::cout << "key is 0x" << std::hex << key << std::endl;
      break;
      }
  }
  if (key == 0) {
      std::cout << "key not found" << std::endl;
  }

【讨论】:

    猜你喜欢
    • 2011-01-27
    • 1970-01-01
    • 1970-01-01
    • 2021-09-22
    • 1970-01-01
    • 2013-05-07
    • 1970-01-01
    • 2017-08-18
    • 2011-08-15
    相关资源
    最近更新 更多