首页
社区
课程
招聘
[求助]一道DES的linux 逆向题
2018-11-9 10:20 7051

[求助]一道DES的linux 逆向题

2018-11-9 10:20
7051
这道题是学长给我的 按学长的说法是很简单  但是无奈我不会 学长在外实习比较忙 问了几次 没有get到学长的点   用的是openssl库的DES加密 

而且 密钥key是随机的 


A-F 范围 8位char  但是往下分析 就不知道了 。。  虽然说 有明文 有密文 但是不知道为什么在linux下没有跑出来 正确的key

然后 

看起来这个png v59 是没有变的  那我爆破不知道为啥没有跑出来 。。。  (这个源文件有upx壳 我已经脱了)   
希望有大佬给萌新解答一下  
第一次发帖 若有什么不合适  请原谅。。。

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (3)
雪    币: 1314
活跃值: (3017)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
皮皮虾啊 2018-11-9 10:31
2
0
wormfox srand 随机种子固定的啊 这表示产生的随机序列是可预测的!
对啊 但是这个题 到底要干啥 很懵啊 key我也没有跑出来  。。。很难受
雪    币: 7582
活跃值: (3249)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
arab 2018-11-13 00:16
3
0
帮你整理了一下代码, 你对照着看吧
void __fastcall PCcheck(char *a1)
{
  signed int k; // eax@10
  signed int count; // [rsp+14h] [rbp-18Ch]@7
  int i; // [rsp+18h] [rbp-188h]@7
  signed int j; // [rsp+1Ch] [rbp-184h]@15
  char cpuid[32]; // [rsp+20h] [rbp-180h]@1
  char key[32]; // [rsp+40h] [rbp-160h]@7
  char uuidMD5[48]; // [rsp+60h] [rbp-140h]@1
  char cpuidMD5[48]; // [rsp+90h] [rbp-110h]@1
  char tmpMD5[48]; // [rsp+C0h] [rbp-E0h]@1
  char uuid[48]; // [rsp+F0h] [rbp-B0h]@1
  char allAlpha[96]; // [rsp+120h] [rbp-80h]@7

  /* 初始化 */
  memset(uuid, 0, sizeof(uuid));
  memset(cpuid, 0, sizeof(cpuid));
  memset(uuidMD5, 0, sizeof(uuidMD5));
  memset(cpuidMD5, 0, sizeof(cpuidMD5));
  memset(tmpMD5, 0, sizeof(tmpMD5));

  /* 取机器 的 UUID 然后做两次 MD5, 命令行为 */
  getSystemUUID(uuid);    /* dmidecode -t 1 | grep UUID | cut -c8-43 */
  getMD5(uuid, tmpMD5);
  getMD5(tmpMD5, uuidMD5);
  /* 结果必须是 fa8480059051f6c10031ad134f360206 */
  if ( strcmp(uuidMD5, "fa8480059051f6c10031ad134f360206") )
  {
    puts("Machine inspection fail! Please use an authorized machine.");
    exit(-1);   /* 检查点 1 */
  }

  /* 取机器的 CPUID 然后做两次 MD5, 命令行为 */
  getCPUID(cpuid);   /* dmidecode -t 4 | grep ID | tail -1 | cut -c6-28 | tr -d ' ' */
  getMD5(cpuid, tmpMD5);
  getMD5(tmpMD5, cpuidMD5);
  /* 结果必须是 95962c6dfce78b57578a874640013ba2 */
  if ( strcmp(cpuidMD5, "95962c6dfce78b57578a874640013ba2") )
  {
    puts("Machine inspection fail! Please use an authorized machine.");
    exit(-1);   /* 检查点 2 */
  }

  /* 把 uuid + cpuid 拼成一个串 */
  strcpy(a1, uuid);
  strcat(a1, cpuid);

  /* 取出这个串中的所有的 A-F 填到一个新的串 allAlpha */
  count = 0;
  memset(allAlpha, 0, sizeof(allAlpha));
  memset(key, 0, sizeof(key));
  for ( i = 0; i < strlen(a1); ++i )
  {
    if ( a1[i] >= 'A' && a1[i] <= 'F' )
    {
      k = count++;
      allAlpha[k] = a1[i];
    }
  }

  /* allAlpha 的长度至少为 9 个字符 */
  if ( count <= 9 )
    exit(-1);    /* 检查点 3 */

  /* 把 allAlpha  乱序, 即用固定种子的随机序列把 allAlpha 中的值填到 key 中 */
  srand(0x90u);
  for ( j = 0; j <= 9; ++j )
    key[j] = allAlpha[rand() % count];

  /* 这就是最终的返回结果 */
  strcpy(a1, key);
}

int __cdecl main(int argc, const char **argv, const char **envp)
{
  const char *v3; // rt1@1
  int v4; // ST24_4@1
  int str_len; // ST20_4@1
  int result; // eax@13
  __int64 v7; // rsi@13
  int i; // [rsp+14h] [rbp-52Ch]@1
  int j; // [rsp+14h] [rbp-52Ch]@4
  signed int k; // [rsp+18h] [rbp-528h]@10
  int des_block; // [rsp+1Ch] [rbp-524h]@1
  FILE *stream; // [rsp+28h] [rbp-518h]@10
  char ks1; // [rsp+30h] [rbp-510h]@1
  char ks2; // [rsp+130h] [rbp-410h]@1
  char ks3; // [rsp+230h] [rbp-310h]@1
  char keystring[16]; // [rsp+330h] [rbp-210h]@1
  char key[32]; // [rsp+340h] [rbp-200h]@1
  char des[24]; // [rsp+360h] [rbp-1E0h]@1
  char deskey[24]; // [rsp+380h] [rbp-1C0h]@1
  char string[32]; // [rsp+3A0h] [rbp-1A0h]@1
  char str[64]; // [rsp+3C0h] [rbp-180h]@1
  char desin[64]; // [rsp+400h] [rbp-140h]@1
  char desout[64]; // [rsp+440h] [rbp-100h]@1
  char v24[64]; // [rsp+480h] [rbp-C0h]@1
  char png[112]; // [rsp+4C0h] [rbp-80h]@1
  __int64 v26; // [rsp+538h] [rbp-8h]@1


   /* 生成 key */
  memset(key, 0, sizeof(key));
  PCcheck(key); 

  /* 实际 Key : KEY:FF + key */
  *(_QWORD *)string = 'FF:YEK';
  *(_QWORD *)&string[8] = 0LL;
  *(_QWORD *)&string[16] = 0LL;
  string[24] = 0;
  strcat(string, key);

  /* 待加密的固定串 */
  strcpy(str, "Hint:The_key_is_the_key");
  *(_QWORD *)&str[24] = 0LL;
  *(_QWORD *)&str[32] = 0LL;
  *(_QWORD *)&str[40] = 0LL;
  *(_QWORD *)&str[48] = 0LL;
  *(_DWORD *)&str[56] = 0;

  /* 初始化 */
  /* 相当于 png[111] = { 0x3C, ...., 0x18 }; */
  png[0] = 0x3C;
  ...
  png[110] = 0x18;
  /* 相当于 des[24] = { 0xF4, ...., 0xA5 }; */
  des[0] = 0xF4;
  ...
  des[23] = 0xA5;

  memset(desin, 0, sizeof(desin));
  memset(desout, 0, sizeof(desout));
  memset(v24, 0, sizeof(v24));

  /* 初始化 des */
  v4 = strlen(string);
  memcpy(deskey, string, v4);
  memset(&deskey[v4], 0, 24 - v4);
  *(_QWORD *)keystring = *(_QWORD *)deskey;
  DES_set_key_unchecked(keystring, &ks1);
  *(_QWORD *)keystring = *(_QWORD *)&deskey[8];
  DES_set_key_unchecked(keystring, &ks2);
  *(_QWORD *)keystring = *(_QWORD *)&deskey[16];
  DES_set_key_unchecked(keystring, &ks3);

  /* 加密固定串 */
  str_len = strlen(str);
  memcpy(desin, str, str_len);
  des_block = 8 * (str_len / 8 + 1);
  memset(&desin[str_len], (char)(8 - (char)str_len % 8), 8 - str_len % 8);
  for ( i = 0; i < des_block; i += 8 )
    DES_ecb3_encrypt(&desin[i], &desout[i], &ks1, &ks2, &ks3, 1LL);

  /* 比较加密结果 */
  for ( j = 0; j < des_block; ++j )
  {
    if ( desout[j] != des[j] )
    {
      puts("Error!");
      exit(0);  /* 检查点 4 */
    }
  }

  /* 成功, 输出 key */
  puts("Congratulations, this is your key:");
  puts("   aaaaa");
  puts(" aaaaaaaaaa");
  puts("aaaa   aaaaaaaaaaaaaaaaaaa");
  printf("aaa     aaaaaaaaFF%s\n", key, argv);
  puts("aaaa   aaaaaaaaaaaaaaaaaaa");
  puts(" aaaaaaaaaa");
  puts("   aaaaa");

  /* 解密成功标志文件 */
  stream = fopen("flag.png", "wb");
  for ( k = 0; k <= 110; ++k )
    fputc((char)(PNG[k] ^ png[k]), stream);
  fclose(stream);
  result = 0;
  return result;
}

这个程序有四个检查点, 三个在 PCcheck, 一个在 main, 不成功会直接退出, 成功后会输出正确的 key, 并且会解密  flag.png 文件. 所以你看看题目的要求是什么, 是爆破呢, 还是求真正的 key, 然后决定在哪下手吧

雪    币: 1314
活跃值: (3017)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
皮皮虾啊 2018-11-13 14:05
4
0
arab 帮你整理了一下代码, 你对照着看吧void&nbsp;__fastcall&nbsp;PCcheck(char&nbsp;*a1) { &nbsp;&nbs ...
谢谢您! 我再好好看看。。
游客
登录 | 注册 方可回帖
返回