因为好久没更新博客被SW拷打了,思来想去决定还是把Writrup放在blog上,一个是催自己复现喵,一个是能整理一下思路练练代码能力。
下周ciscn的PPT还没做,能不能天降一个PPT高级工程大师来救救我TT 为什么暑假会比上学忙啊,暑假回来连轴转TT

当时打l3h的时候在做手术,两天都只有半夜摸了一下电脑,只打了两道TT 但是我应该会全复现的!

TemporalParadox

One day I made a request, but I forgot what it was. Can you help me find it?

1
2
Decompilation failure:
140001D20: positive sp value has been found
1
2
3
4
.text:0000000140001D20     loc_140001D20:      ; CODE XREF: sub_140001D05+16↑j
.text:0000000140001D20 168 call locret_140001D1E
.text:0000000140001D1E locret_140001D1E: ; CODE XREF: sub_140001D05:loc_140001D20↓p
.text:0000000140001D1E 000 retn

nop掉

sub_140001D05

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
__int64 __fastcall sub_140001D05(time_t *Time, __int64 a2)
sub_140002180(Time, a2);
sub_14000A510((_DWORD)Time, a2, v2, (unsigned int)v50, v3, v4);
n1751990400 = time(Time); // 获取当前的系统时间


if ( n1751990400 > 1751990400 && n1751990400 <= 1752052051 )
//时间戳范围约束
{
sub_140001963((_DWORD)Time, a2, v5, (unsigned int)v46, v6, v7);


v54 = &v51;
v9 = std::string::c_str(Time, a2, v8, v46);
v12 = sub_14000A040((_DWORD)Time, a2, v9, (unsigned int)v50, v10, v11, v38);
sub_14000A820((_DWORD)Time, a2, v12, (unsigned int)v47, (unsigned int)&v51, v13, v39, v44);
sub_14000A6E0((_DWORD)Time, a2, v14, (unsigned int)&v51, v15, v16, v40);
p__ZSt4cout = std::operator<<<std::char_traits<char>>(Time, a2, "query: ", &std::cout);
v18 = std::operator<<<char>(Time, a2, v46, p__ZSt4cout);
std::ostream::operator<<(Time, a2, &std::endl<char,std::char_traits<char>>, v18);
v19 = std::operator<<<char>(Time, a2, v47, &std::cout);
std::ostream::operator<<(Time, a2, &std::endl<char,std::char_traits<char>>, v19);
std::string::~string(Time, a2, v20, v47);
std::string::~string(Time, a2, v21, v46);
}
std::string::basic_string(Time, a2, v5, v49);
v22 = std::operator<<<std::char_traits<char>>(Time, a2, "Please input the right query string I used:", &std::cout);
std::ostream::operator<<(Time, a2, &std::endl<char,std::char_traits<char>>, v22);
std::operator>><char>(Time, a2, v49, &std::cin);
v53 = &v52;
v24 = std::string::c_str(Time, a2, v23, v49);
v27 = sub_14000A040((_DWORD)Time, a2, v24, (unsigned int)v50, v25, v26, v38);
sub_14000A820((_DWORD)Time, a2, v27, (unsigned int)v48, (unsigned int)&v52, v28, v41, v44);
sub_14000A6E0((_DWORD)Time, a2, v29, (unsigned int)&v52, v30, v31, v42);
if ( (unsigned __int8)sub_14000A8E0(
(_DWORD)Time,
a2,
(unsigned int)"8a2fc1e9e2830c37f8a7f51572a640aa",
(unsigned int)v48,
v32,
v33,
v43,
v45) )
v34 = std::operator<<<std::char_traits<char>>(Time, a2, "Congratulations!", &std::cout);
else
v34 = std::operator<<<std::char_traits<char>>(Time, a2, "Wrong!", &std::cout);
std::ostream::operator<<(Time, a2, &std::endl<char,std::char_traits<char>>, v34);
std::string::~string(Time, a2, v35, v48);
std::string::~string(Time, a2, v36, v49);
return 0LL;
}

sub_140001963

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
__int64 __fastcall sub_140001963(


sub_140001518((_DWORD)Time, a2, a3, (unsigned int)v51, a5, a6);
v53 = time(Time);
sub_1400014B5((_DWORD)Time, a2, v10, v53, v11, v12);//
// 将参数 a4(一个整数)保存到全局变量 dword_7FF75004B040 中,若为 0 则强制设为 1。

v58 = 0;
v57 = 0;
v56 = 0;
v55 = 0;

for ( i = 0; i < (int)random(); ++i )
{
v58 = random();
v57 = random();
v56 = random();
v55 = random();
}
v52 = random();
std::basic_stringstream<char,std::char_traits<char>,std::allocator<char>>::basic_stringstream(Time, a2, v13, v49);
v14 = (double)dword_14000B0E0;
v15 = (double)(int)(v58 | v56);
v18 = v14 * sub_1400033A0(v15, 2.0, v15, a10, v16, v17, (double)dword_14000B0E0);
v19 = (double)dword_14000B0E4;
if ( v18 == sub_1400033A0((double)(int)(v57 | v55), 2.0, v15, (double)(int)(v57 | v55), v20, v21, v18) * v19 )
{
p__ZSt4cout = std::operator<<<std::char_traits<char>>(Time, a2, "salt=", v50);
v23 = std::operator<<<char>(Time, a2, v51, p__ZSt4cout);
v24 = std::operator<<<std::char_traits<char>>(Time, a2, "&t=", v23);
v25 = std::ostream::operator<<(Time, a2, v53, v24);
v26 = std::operator<<<std::char_traits<char>>(Time, a2, "&r=", v25);
v27 = std::ostream::operator<<(Time, a2, v52, v26);
v28 = std::operator<<<std::char_traits<char>>(Time, a2, "&cipher=", v27);
v31 = sub_14000184D((_DWORD)Time, a2, v53, v52, v29, v30, v48);
std::ostream::operator<<(Time, a2, v31, v28);
}
else
{
p__ZSt4cout_1 = std::operator<<<std::char_traits<char>>(Time, a2, "salt=", v50);
v33 = std::operator<<<char>(Time, a2, v51, p__ZSt4cout_1);
v34 = std::operator<<<std::char_traits<char>>(Time, a2, "&t=", v33);
v35 = std::ostream::operator<<(Time, a2, v53, v34);
v36 = std::operator<<<std::char_traits<char>>(Time, a2, "&r=", v35);
v37 = std::ostream::operator<<(Time, a2, v52, v36);
v38 = std::operator<<<std::char_traits<char>>(Time, a2, "&a=", v37);
v39 = std::ostream::operator<<(Time, a2, v58, v38);
v40 = std::operator<<<std::char_traits<char>>(Time, a2, "&b=", v39);
v41 = std::ostream::operator<<(Time, a2, v57, v40);
v42 = std::operator<<<std::char_traits<char>>(Time, a2, "&x=", v41);
v43 = std::ostream::operator<<(Time, a2, v56, v42);
v44 = std::operator<<<std::char_traits<char>>(Time, a2, "&y=", v43);
std::ostream::operator<<(Time, a2, v55, v44);
}
std::basic_stringstream<char,std::char_traits<char>,std::allocator<char>>::str(Time, a2, v49, a4);
std::basic_stringstream<char,std::char_traits<char>,std::allocator<char>>::~basic_stringstream(Time, a2, v45, v49);
std::string::~string(Time, a2, v46, v51);
return a4;
}

自定义的random

1
2
3
4
5
6
7
8
__int64 random()
{
unsigned int v1; // [rsp+Ch] [rbp-4h]

v1 = (((dword_14000B040 << 13) ^ (unsigned int)dword_14000B040) >> 17) ^ (dword_14000B040 << 13) ^ dword_14000B040;
dword_14000B040 = (32 * v1) ^ v1;
return dword_14000B040 & 0x7FFFFFFF;
}

它是把当前系统的时间戳做随机数的种子,首先要在它约束的范围内才能运行,然后生成了5个random值拼合成一个字符串

salt=tlkyeueq7fej8vtzitt26yl24kswrgm5&t=%u&r=%d&a=%d&b=%d&x=%d&y=%d

再做md5(标准)与目标值8a2fc1e9e2830c37f8a7f51572a640aa 比较

exp

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
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <openssl/md5.h>

#define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
unsigned int seed ;
// unsigned int first = 1751990400;
// unsigned int end = 1752052051;

// v1 = (((dword_7FF75004B040 << 13) ^ (unsigned int)dword_7FF75004B040) >> 17) ^ (dword_7FF75004B040 << 13) ^ dword_7FF75004B040;
// dword_7FF75004B040 = (32 * v1) ^ v1;
// return dword_7FF75004B040 & 0x7FFFFFFF;

int random()
{
unsigned int x = (seed << 13) ^seed;
unsigned int y = (x >> 17) ^ x;
seed =(y * 32)^y;
return seed & 0x7FFFFFFF;
}

void md5hexToString(unsigned char *md, char *result) {
for (size_t i = 0; i < 16; i++) {
sprintf(result + i * 2, "%02x", md[i]);
}
result[32] = '\0';
}

int main()
{

for (int i = 1751990400; i < 1752052051; i++)
{
char query[256];
unsigned char digest[16];
char flag[33] = {0};
int v58 = 0;
int v57 = 0;
int v56 = 0;
int v55 = 0;
seed = i;


for (int k = 0; k < (int)random(); ++k )
{
v58 = random();
v57 = random();
v56 = random();
v55 = random();
}
int v52 = random();


snprintf(query, sizeof(query),
"salt=tlkyeueq7fej8vtzitt26yl24kswrgm5&t=%u&r=%d&a=%d&b=%d&x=%d&y=%d",
i, v52, v58, v57, v56, v55);
printf("%s\n", query);

MD5((unsigned char *)query, strlen(query), digest);

md5hexToString(digest, flag);
printf("%s\n", flag);

if (!strcmp(flag, "8a2fc1e9e2830c37f8a7f51572a640aa")) {
printf(" Found at time: %d\n", seed);
return 0;
}
}
return 0;
}
// salt=tlkyeueq7fej8vtzitt26yl24kswrgm5&t=1751994277&r=101356418&a=1388848462&b=441975230&x=1469980073&y=290308156
// 8a2fc1e9e2830c37f8a7f51572a640aa
// Found at time: 101356418

// L3HCTF{5cbbe37231ca99bd009f7eb67f49a98caae2bb0f}