0x00 分析

给了三个文件,一个程序,两个.enc结尾的,应该是加密了

后面要爆破时间戳

主打一个写代码

0x01 解

无壳,直接上IDA

main函数直接给出,一步步分析

接收输入然后根据输入的命令执行不同操作

具体操作可以查看printHelp函数

1
2
3
4
5
6
7
8
9
10
11
12
13
"Usage: FinalEncrypt [OPTIONS]...\n"
"Encrypts/Decrypts files using FinalEncrypt\n"
"\n"
" -h Prints help screen\n"
" -e [filename] Encrypts a specified file (must be passed with -r)\n"
" -d [filename] Decrypts a specified file (must be passed with -k)\n"
" -k [512 bit Key in hex] Specifies the key used for decryption\n"
" -r Generates a random key\n"
"\n"
"Examples - \n"
"FinalEncrypt -r -e testfile.txt\n"
"FinalEncrypt -d testfile.txt.enc -k D84165183346405877C13F497EB32B34410D5653A8141B07E307044F780EB733A62F1D087C126537"
"BBEAB769EA56E15FCAC19E4E215A4E1A28D3FC46362FC80D\n");

根据help,可以知道程序用于加密和解密文件,加密流程可以在main函数中找到

就是以时间为种子,取随机数,然后用此随机数去进行加密

进去fileEncrtpt函数会发现使用了ChaChaEncrypt函数,不过这里不需要深究,只要搞出时间戳出来就能解密了

尝试使用文件的修改时间的时间戳

1
2
3
4
5
import os
print(hex(int(os.path.getmtime('./Encryption.exe.enc'))))
print(hex(int(os.path.getmtime('./flag.md.enc'))))
#0x663b35c6
#0x663b3627

动调

记得设置参数

断在time位置,单步运行,修改srand的传入值

获取两次的key

1
2
exe:507CD82354B1A821ED46A45FAF06D53D0F941C24E085D511F244410B2666056462E126287107616B308DDB193B62036C89C7112C8E713828BC8E8C5079ED221A
md:CB0C24457D0BE9695EFDD94C533DE2036E0E6E706C1B06471DBE334DA3195C32F46C8078C7311D068270A10EAE446D0553FA1F628CE4336A39DA852730625324

使用key对两个文件进行解密

1
2
3
./FinalEncrypt -d Encryption.exe.enc -k 507CD82354B1A821ED46A45FAF06D53D0F941C24E085D511F244410B2666056462E126287107616B308DDB193B62036C89C7112C8E713828BC8E8C5079ED221A

./FinalEncrypt -d flag.md.enc -k CB0C24457D0BE9695EFDD94C533DE2036E0E6E706C1B06471DBE334DA3195C32F46C8078C7311D068270A10EAE446D0553FA1F628CE4336A39DA852730625324

解密出来一个exe和一个md

md内容如下

1
e07816e1dba1da61536634bef2c3b6346d533cc3b6b834e3beb634c80264143c34e36400bb4daa6902ff643414e3b8344dff6634b8b66db6bbc33834143461ab147e04

又是加密

exe就是一个加密器,用于加密

接下来就是看exe了

无壳

又是用到时间戳生成随机数

加密就是根据输入的flag字符在v8中找值

本质上是一个代换

那么重点就是搞出v8的内容,这里直接dump下生成表的过程然后进行爆破

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
using namespace std;

unsigned char __ROR1__(unsigned char value, int count) {
return ((value >> count) | (value << (8 - count))) & 0xFF;
}
void custom_algorithm(unsigned int v3, unsigned char *v8) {
unsigned int time_seed; // eax
char Str[8]; // [rsp+20h] [rbp-60h] BYREF
char v6[56]; // [rsp+28h] [rbp-58h] BYREF
int v7; // [rsp+60h] [rbp-20h]
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, 0x100);
srand(v3);
do
v19 = rand();
while ( !v19 );
memset(v8, 0, 0x100);
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 = (unsigned __int8)(v23 ^ v17);
v16 = __ROR1__(v23 ^ v17, 7);
v15 = v16 ^ (unsigned __int8)(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 );
}

bool match_v8_with_b(const unsigned char *v8, const char *b, unsigned char *indices) {
size_t b_len = strlen(b);
bool all_found = true;
size_t idx = 0;

for (size_t i = 0; i < b_len; i += 2) {
char hex_str[3] = {b[i], b[i + 1], '\0'};
unsigned char byte = (unsigned char)strtol(hex_str, NULL, 16);
bool found = false;

for (int j = 0; j < 128; j++) {
if (v8[j] == byte) {
indices[idx++] = j; // Store index of v8 where match is found
found = true;
break;
}
}
if (!found) {
all_found = false;
break;
}
}
indices[idx] = 0xFF; // Terminate the indices array
return all_found;
}

int main(){
const char *b = "e07816e1dba1da61536634bef2c3b6346d533cc3b6b834e3beb634c80264143c34e36400bb4daa6902ff643414e3b8344dff6634b8b66db6bbc33834143461ab147e04";
unsigned char v8[256];
unsigned char indices[128]; // Large enough to store all indices needed
unsigned int start_time =1715153796; // time stamp of FileEncrypt
unsigned int end_time = 1715156519; // time stamp of flag.md.enc

for (unsigned int v3 = start_time; v3 <= end_time; v3++) {
custom_algorithm(v3, v8);
if (match_v8_with_b(v8, b, indices)) {
printf("Match found for seed %u\n", v3);
printf("Matching indices in v8: ");
for (int i = 0; indices[i] != 128; i++) {
printf("%c", indices[i]);
}
printf("\n");
}
}
return 0;
}
// DASCTF{7ou_h@ve_5o1ved_4he_fina1_4ncrypti0n_a4d_y0u_de5erv3_a_7lag}