FinalEncrypt

题目给了3个附件,分别是FindEncrypt和flag.md,Encryption.exe.enc

1.查看代码主要功能

先看FindEncrypt文件,
2024-06-05T12:53:06.png
2024-06-05T12:53:15.png
主要思路就是一个指令FindEncrypt,有一些参数,加密,解密,获取key等操作,输入FindEncrypt -h会给出用法提示:
2024-06-05T12:53:37.png
所以.enc就是加密后的文件,需要进行解密enc文件,解密需要密钥,密钥由时间戳作为种子生成的伪随机数来生成,加密和解密用同一个密钥,所以就要找到给这两个enc文件加密的时间是什么时候

2.获取文件修改时间戳

使用指令tar --atime-preserve -xvf encrypted.tar.xz 保持文件的修改时间不变,解压文件

使用stat查看文件的修改时间,如下
2024-06-05T12:53:58.png2024-06-05T12:54:06.png
Encryption.exe.enc和flag.md.enc的文件修改时间分别为2024-05-08 16:20:22.000000000 +08002024-05-08 16:21:59.000000000 +0800

进行时间戳的转换,将时间改为Unix时间戳(时间戳(Unix timestamp)转换工具 - 在线工具 (tool.lu)),分别为17151276221715127719

3.修改随机数种子为文件修改时间,获取密钥

主要思路是调试修改随机数种子为文件的修改时间,这样得到的密钥就是文件加密时的密钥,用这个密钥解密,就能得到正确的解密文件(之前没往这边想,只知道随机数种子是时间戳,不知道怎么处理这些

可以用gdb调试

使用指令:gdb --args ./FinalEncrypt -re test.txt

其中 --args :此选项告诉gdb将后续参数直接传递给正在调试的程序

   ./FinalEncrypt:表示要调试的程序

 -re test.txt:表示参数

(没安装pwndbg一直调试不了,pwndbg是gdb的一个插件,在ctf比赛中调试pwn程序用处很大

注意:需要安装pwndbg,(安装中有很多问题,在执行命令r时候出现libc.so.6: version ‘GLIBC_2.34‘ not found问题,可以参考如下文章:问题:libc.so.6: version ‘GLIBC_2.34‘ not found 高效解决办法-CSDN博客


2024-06-05T12:54:25.png(出现这种,需要使用指令chmod +x 文件 ,给文件提权
程序运行到这里,能看到调用eax中的数据当作种子,然后调用scrand函数,所以我们要修改的就是eax的值,使用set $rax=1715156422 ,修改rax的值,按c接着执行,获取到key
2024-06-05T12:54:48.png
2024-06-05T12:54:58.png
507CD82354B1A821ED46A45FAF06D53D0F941C24E085D511F244410B2666056462E126287107616B308DDB193B62036C89C7112C8E713828BC8E8C5079ED221A

A768B85A09DB4A2066AA416CFFE7E0356B54682DD29EDF279D2D851AA25F631915FBD95364FB5337CA383573A66D744BB7731C2C587F5A048CE2484984DE772C

4.用获取到的密钥解密文件

使用指令:FinalEncrypt -d Encryption.exe.enc -k 507CD82354B1A821ED46A45FAF06D53D0F941C24E085D511F244410B2666056462E126287107616B308DDB193B62036C89C7112C8E713828BC8E8C5079ED221A

密文:e07816e1dba1da61536634bef2c3b6346d533cc3b6b834e3beb634c80264143c34e36400bb4daa6902ff643414e3b8344dff6634b8b66db6bbc33834143461ab147e04

Encryption.exe主函数思路:
2024-06-05T12:55:18.png
2024-06-05T12:55:26.png

生成的密码表是随机数,需要获取随机数的种子,因为flag形式是DASCTF{}并且v8表所有值都不超过0xff(动调可以看到),v8[0]=rand(),所以尝试去爆破种子
2024-06-05T12:55:42.png
写脚本爆破得到种子为35,然后求解flag即可

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <windows.h>
__int64 __fastcall __ROR1__(unsigned __int8 a1, char a2)
{
  return ((a1 >> a2) | (a1 << (8 - a2)));
}
int main()
{
  unsigned int v3;       // eax
  char Str[8];           // [rsp+20h] [rbp-60h] BYREF
  char v6[56];           // [rsp+28h] [rbp-58h] BYREF
  int v7;                // [rsp+60h] [rbp-20h]
  unsigned char v8[256]; // [rsp+70h] [rbp-10h] BYREF
  int v9;                // [rsp+174h] [rbp+F4h]
  int v10;               // [rsp+178h] [rbp+F8h]
  int v11;               // [rsp+17Ch] [rbp+FCh]
  int v12;               // [rsp+180h] [rbp+100h]
  int v13;               // [rsp+184h] [rbp+104h]
  int v14;               // [rsp+188h] [rbp+108h]
  int v15;               // [rsp+18Ch] [rbp+10Ch]
  int v16;               // [rsp+190h] [rbp+110h]
  char v17;              // [rsp+195h] [rbp+115h]
  char v18;              // [rsp+196h] [rbp+116h]
  char v19;              // [rsp+197h] [rbp+117h]
  int i;                 // [rsp+198h] [rbp+118h]
  unsigned __int8 v21;   // [rsp+19Ch] [rbp+11Ch]
  char v22;              // [rsp+19Dh] [rbp+11Dh]
  char v23;              // [rsp+19Eh] [rbp+11Eh]
  char v24;              // [rsp+19Fh] [rbp+11Fh]
  memset(v8, 0, 0x100L);
  // v3 = time(0L);
  // for (int i = 0; i < 256; i++)
  // {
  srand(35);
  do
    v19 = rand();
  while (!v19);
  memset(v8, 0, 0x100L);
  v8[0] = v19;
  v22 = 1;
  v21 = 1;
  do
  {
    if (v22 < 0)
      v24 = 27;
    else
      v24 = 0;
    v22 ^= v24 ^ (2 * v22);
    v18 = (2 * v21) ^ (4 * ((2 * v21) ^ v21)) ^ v21;
    v17 = v18 ^ (16 * v18);
    if (v17 < 0)
      v23 = 9;
    else
      v23 = 0;
    v21 = v23 ^ v17;
    v16 = (v23 ^ v17);
    v16 = __ROR1__(v23 ^ v17, 7);
    v15 = v16 ^ (v21 ^ v8[0]);
    v14 = v21;
    v14 = __ROR1__(v21, 6);
    v13 = v15 ^ v14;
    v12 = v21;
    v12 = __ROR1__(v21, 5);
    v11 = v13 ^ v12;
    v10 = v21;
    v10 = __ROR1__(v21, 4);
    v9 = v11 ^ v10;
    v8[v22] = v11 ^ v10;
  } while (v22 != 1);//下面是用于爆破的代码,得到种子值为35
  // if (v8[68] == 0xE0 && v8[65] == 0x78 && v8[83] == 0x16 && v8[67] == 0xe1 && v8[84] == 0xdb && v8[70] == 0xa1)
  // {
  //   printf("%d", i);
  // }
//}
  int a[] = {224, 120, 22, 225, 219, 161, 218, 97, 83, 102, 52, 190, 242, 195, 182, 52, 109, 83, 60, 195, 182, 184, 52, 227, 190, 182, 52, 200, 2, 100, 20, 60, 52, 227, 100, 0, 187, 77, 170, 105, 2, 255, 100, 52, 20, 227, 184, 52, 77, 255, 102, 52, 184, 182, 109, 182, 187, 195, 56, 52, 20, 52, 97, 171, 20, 126, 4};
  for (int j = 0; j < 67; j++)
    for (int k = 0; k < 256; k++)
    {
      if (v8[k] == a[j] && k < 126 && k > 47)
        printf("%c", k);
    }
  return 0;
}

拿到flag