avatar

红帽杯RE WP

来自buu上的红帽杯的试题

easy re

放入了ida进行分析,打开后shift+f12进行关键字的查找,找到了主函数

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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
signed __int64 sub_4009C6()
{
char *v0; // rsi
char *v1; // rdi
__int64 v2; // rax
signed __int64 result; // rax
unsigned __int64 v4; // rax
__int64 v5; // rax
const __m128i *v6; // ST10_8
const __m128i *v7; // ST18_8
const __m128i *v8; // ST20_8
const __m128i *v9; // ST28_8
const __m128i *v10; // ST30_8
const __m128i *v11; // ST38_8
const __m128i *v12; // ST40_8
const __m128i *v13; // ST48_8
const __m128i *v14; // ST50_8
__int64 v15; // ST58_8
int i; // [rsp+Ch] [rbp-114h]
char v17; // [rsp+60h] [rbp-C0h]
char v18; // [rsp+61h] [rbp-BFh]
char v19; // [rsp+62h] [rbp-BEh]
char v20; // [rsp+63h] [rbp-BDh]
char v21; // [rsp+64h] [rbp-BCh]
char v22; // [rsp+65h] [rbp-BBh]
char v23; // [rsp+66h] [rbp-BAh]
char v24; // [rsp+67h] [rbp-B9h]
char v25; // [rsp+68h] [rbp-B8h]
char v26; // [rsp+69h] [rbp-B7h]
char v27; // [rsp+6Ah] [rbp-B6h]
char v28; // [rsp+6Bh] [rbp-B5h]
char v29; // [rsp+6Ch] [rbp-B4h]
char v30; // [rsp+6Dh] [rbp-B3h]
char v31; // [rsp+6Eh] [rbp-B2h]
char v32; // [rsp+6Fh] [rbp-B1h]
char v33; // [rsp+70h] [rbp-B0h]
char v34; // [rsp+71h] [rbp-AFh]
char v35; // [rsp+72h] [rbp-AEh]
char v36; // [rsp+73h] [rbp-ADh]
char v37; // [rsp+74h] [rbp-ACh]
char v38; // [rsp+75h] [rbp-ABh]
char v39; // [rsp+76h] [rbp-AAh]
char v40; // [rsp+77h] [rbp-A9h]
char v41; // [rsp+78h] [rbp-A8h]
char v42; // [rsp+79h] [rbp-A7h]
char v43; // [rsp+7Ah] [rbp-A6h]
char v44; // [rsp+7Bh] [rbp-A5h]
char v45; // [rsp+7Ch] [rbp-A4h]
char v46; // [rsp+7Dh] [rbp-A3h]
char v47; // [rsp+7Eh] [rbp-A2h]
char v48; // [rsp+7Fh] [rbp-A1h]
char v49; // [rsp+80h] [rbp-A0h]
char v50; // [rsp+81h] [rbp-9Fh]
char v51; // [rsp+82h] [rbp-9Eh]
char v52; // [rsp+83h] [rbp-9Dh]
char v53[32]; // [rsp+90h] [rbp-90h]
int v54; // [rsp+B0h] [rbp-70h]
char v55; // [rsp+B4h] [rbp-6Ch]
char v56; // [rsp+C0h] [rbp-60h]
char v57; // [rsp+E7h] [rbp-39h]
char v58; // [rsp+100h] [rbp-20h]
unsigned __int64 v59; // [rsp+108h] [rbp-18h]

v59 = __readfsqword(40u);
v17 = 'I';
v18 = 'o';
v19 = 'd';
v20 = 'l';
v21 = '>';
v22 = 'Q';
v23 = 'n';
v24 = 'b';
v25 = '(';
v26 = 'o';
v27 = 'c';
v28 = 'y';
v29 = '';
v30 = 'y';
v31 = '.';
v32 = 'i';
v33 = '';
v34 = 'd';
v35 = '`';
v36 = '3';
v37 = 'w';
v38 = '}';
v39 = 'w';
v40 = 'e';
v41 = 'k';
v42 = '9';
v43 = '{';
v44 = 'i';
v45 = 'y';
v46 = '=';
v47 = '~';
v48 = 'y';
v49 = 'L';
v50 = '@';
v51 = 'E';
v52 = 'C';
memset(v53, 0, sizeof(v53));
v54 = 0;
v55 = 0;
v0 = v53;
sub_4406E0(0LL, (__int64)v53);
v55 = 0;
v1 = v53;
LODWORD(v2) = sub_424BA0((const __m128i *)v53);
if ( v2 == 36 )
{
for ( i = 0; ; ++i )
{
v1 = v53;
LODWORD(v4) = sub_424BA0((const __m128i *)v53);
if ( i >= v4 )
break;
if ( (unsigned __int8)(v53[i] ^ i) != *(&v17 + i) )
{
result = 4294967294LL;
goto LABEL_13;
}
}
sub_410CC0((const __m128i *)"continue!");
memset(&v56, 0, 0x40uLL);
v58 = 0;
v0 = &v56;
sub_4406E0(0LL, (__int64)&v56);
v57 = 0;
v1 = &v56;
LODWORD(v5) = sub_424BA0((const __m128i *)&v56);
if ( v5 == 39 )
{
v6 = (const __m128i *)sub_400E44((const __m128i *)&v56);
v7 = (const __m128i *)sub_400E44(v6);
v8 = (const __m128i *)sub_400E44(v7);
v9 = (const __m128i *)sub_400E44(v8);
v10 = (const __m128i *)sub_400E44(v9);
v11 = (const __m128i *)sub_400E44(v10);
v12 = (const __m128i *)sub_400E44(v11);
v13 = (const __m128i *)sub_400E44(v12);
v14 = (const __m128i *)sub_400E44(v13);
v15 = sub_400E44(v14);
v0 = off_6CC090;
v1 = (char *)v15;
if ( !(unsigned int)sub_400360(v15, (__int64)off_6CC090) )
{
sub_410CC0((const __m128i *)"You found me!!!");
v1 = "bye bye~";
sub_410CC0((const __m128i *)"bye bye~");
}
result = 0LL;
}
else
{
result = 4294967293LL;
}
}
else
{
result = 0xFFFFFFFFLL;
}
LABEL_13:
if ( __readfsqword(0x28u) != v59 )
sub_444020(v1, v0);
return result;
}

可以看到第一次的异或

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if ( v2 == 36 )
{
for ( i = 0; ; ++i )
{
v1 = v53;
LODWORD(v4) = sub_424BA0((const __m128i *)v53);
if ( i >= v4 )
break;
if ( (unsigned __int8)(v53[i] ^ i) != *(&v17 + i) )
{
result = 4294967294LL;
goto LABEL_13;
}
}

一共和36个字符进行比较,跟输入的v17的进行比较,需要输入的v53[i]^i等于上面有的v17到v52可以写出脚本

1
2
3
4
5
6
7
8
9
10
11
12
#include<stdio.h>
#include<string>
#include<iostream>
using namespace std;
int main() {
string A = "Iodl>Qnb(ocy y.i d`3w}wek9{iy=~yL@EC";
for (int i = 0;A[i];i++) {
A[i] = A[i] ^ i;
}
cout << A << endl;
}
//Info:The first four chars are `flag`

得出来Info:The first four chars are `flag`得出来了一个信息,然后继续向下看

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
memset(&v56, 0,64uLL);
v58 = 0;
v0 = &v56;
sub_4406E0(0LL, (__int64)&v56);
v57 = 0;
v1 = &v56;
LODWORD(v5) = sub_424BA0((const __m128i *)&v56);
if ( v5 == 39 )
{
v6 = (const __m128i *)sub_400E44((const __m128i *)&v56);
v7 = (const __m128i *)sub_400E44(v6);
v8 = (const __m128i *)sub_400E44(v7);
v9 = (const __m128i *)sub_400E44(v8);
v10 = (const __m128i *)sub_400E44(v9);
v11 = (const __m128i *)sub_400E44(v10);
v12 = (const __m128i *)sub_400E44(v11);
v13 = (const __m128i *)sub_400E44(v12);
v14 = (const __m128i *)sub_400E44(v13);
v15 = sub_400E44(v14);
v0 = off_6CC090;
v1 = (char *)v15;
if ( !(unsigned int)sub_400360(v15, (__int64)off_6CC090) )
{
sub_410CC0((const __m128i *)"You found me!!!");
v1 = "bye bye~";
sub_410CC0((const __m128i *)"bye bye~");
}
result = 0LL;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
.rodata:00000000004A23A8 aVm0wd2vhuxhtwg db 'Vm0wd2VHUXhTWGhpUm1SWVYwZDRWVll3Wkc5WFJsbDNXa1pPVlUxV2NIcFhhMk0xV'
.rodata:00000000004A23A8 ; DATA XREF: .data:off_6CC090↓o
.rodata:00000000004A23A8 db 'mpKS1NHVkdXbFpOYmtKVVZtcEtTMUl5VGtsaVJtUk9ZV3hhZVZadGVHdFRNVTVYVW'
.rodata:00000000004A23A8 db '01T2FGSnRVbGhhVjNoaFZWWmtWMXBFVWxSTmJFcElWbTAxVDJGV1NuTlhia0pXWWx'
.rodata:00000000004A23A8 db 'ob1dGUnJXbXRXTVZaeVdrWm9hVlpyV1hwV1IzaGhXVmRHVjFOdVVsWmlhMHBZV1ZS'
.rodata:00000000004A23A8 db 'R1lWZEdVbFZTYlhSWFRWWndNRlZ0TVc5VWJGcFZWbXR3VjJKSFVYZFdha1pXWlZaT'
.rodata:00000000004A23A8 db '2NtRkhhRk5pVjJoWVYxZDBhMVV3TlhOalJscFlZbGhTY1ZsclduZGxiR1J5VmxSR1'
.rodata:00000000004A23A8 db 'ZXSlZjRWhaTUZKaFZqSktWVkZZYUZkV1JWcFlWV3BHYTFkWFRrZFRiV3hvVFVoQ1d'
.rodata:00000000004A23A8 db 'sWXhaRFJpTWtsM1RVaG9hbEpYYUhOVmJUVkRZekZhY1ZKcmRGTk5Wa3A2VjJ0U1Ex'
.rodata:00000000004A23A8 db 'WlhTbFpqUldoYVRVWndkbFpxUmtwbGJVWklZVVprYUdFeGNHOVhXSEJIWkRGS2RGS'
.rodata:00000000004A23A8 db 'nJhR2hTYXpWdlZGVm9RMlJzV25STldHUlZUVlpXTlZadE5VOVdiVXBJVld4c1dtSl'
.rodata:00000000004A23A8 db 'lUWGhXTUZwell6RmFkRkpzVWxOaVNFSktWa1phVTFFeFduUlRhMlJxVWxad1YxWnR'
.rodata:00000000004A23A8 db 'lRXRXTVZaSFVsUnNVVlZVTURrPQ==',0

不难看出是经过了10次的base64,变成了如下的密文,所以本人直接在网上解密了10次,emmm,之后会写个分析base64和解密base64的exp的
upload successful
得出来是一个看雪的网址:https://bbs.pediy.com/thread-254172.htm
upload successful
shift+f7发现在.fini还存在一个函数,里面存放的是程序运行main函数之后所运行的函数,而.init是在main函数之前的

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
unsigned __int64 sub_400D35()
{
__int64 v0; // rdi
unsigned __int64 result; // rax
unsigned __int64 v2; // rt1
unsigned int v3; // [rsp+Ch] [rbp-24h]
signed int i; // [rsp+10h] [rbp-20h]
signed int j; // [rsp+14h] [rbp-1Ch]
unsigned int v6; // [rsp+24h] [rbp-Ch]
unsigned __int64 v7; // [rsp+28h] [rbp-8h]

v7 = __readfsqword(0x28u);
v0 = 0LL;
v3 = sub_43FD20() - qword_6CEE38;
for ( i = 0; i <= 1233; ++i )
{
v0 = v3;
sub_40F790(v3);
sub_40FE60(v3);
sub_40FE60(v3);
v3 = (unsigned __int64)sub_40FE60(v3) ^ 0x98765432;
}
v6 = v3;
if ( ((unsigned __int8)v3 ^ byte_6CC0A0[0]) == 102 && (HIBYTE(v6) ^ (unsigned __int8)byte_6CC0A3) == 103 )
{
for ( j = 0; j <= 24; ++j )
{
v0 = (unsigned __int8)(byte_6CC0A0[j] ^ *((_BYTE *)&v6 + j % 4));
sub_410E90(v0);
}
}
v2 = __readfsqword(0x28u);
result = v2 ^ v7;
if ( v2 != v7 )
sub_444020(v0);
return result;
}

进行分析,一共是两次异或,可以看出来v6=v3且102为f 103为g推断为上面的提示字符串flag 和内存中给的数据反向解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<stdio.h>
#include<string>
#include<iostream>
using namespace std;
int main() {
char key3[4] = {};
string key1 = "flag";
char key2[] = {
0x40,0x35,0x20,0x56,0x5D,0x18,0x22,0x45,0x17,0x2F,0x24,0x6E,0x62,0x3C,0x27,0x54,0x48,0x6C,0x24,0x6E,0x72,0x3C,0x32,0x45,0x5B };
for (int i = 0;i < 4;i++) {
key3[i] = key1[i] ^ key2[i];
}
cout << key3 << endl;//&YA1
char flag[40] = {};
for (int i = 0;i < 25;i++) {
flag[i] = key2[i] ^ key3[i % 4];
}
cout << flag << endl;
}
//flag{Act1ve_Defen5e_Test}

xx

打开ida,shift+12找到了主函数

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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
int __fastcall sub_1400011A0(__int64 a1, __int64 a2)
{
signed __int64 v2; // rbx@1
signed __int64 v3; // rax@1
__int64 v4; // rax@6
__int64 v5; // r11@6
__int128 *v6; // r14@6
int v7; // edi@6
_BYTE *v8; // rsi@6
char v9; // r10@7
int v10; // edx@7
__int64 v11; // r8@7
unsigned __int64 v12; // rcx@7
signed __int64 v13; // rcx@12
unsigned __int64 v14; // rax@18
unsigned __int64 i; // rax@28
__int64 v16; // rax@30
size_t v17; // rsi@30
__int64 v18; // rbx@30
__int64 v19; // r9@30
signed int v20; // er11@30
char *v21; // r8@30
signed __int64 v22; // rcx@31
char v23; // al@32
__int64 v24; // r9@35
signed __int64 v25; // rdx@35
__int64 v26; // rax@38
__int64 v28; // [sp+0h] [bp-68h]@38
size_t Size; // [sp+20h] [bp-48h]@30
__int128 v30; // [sp+28h] [bp-40h]@18
int v31; // [sp+38h] [bp-30h]@35
int v32; // [sp+3Ch] [bp-2Ch]@35
int Code[4]; // [sp+40h] [bp-28h]@1
int v34; // [sp+50h] [bp-18h]@1
__int64 v35; // [sp+58h] [bp-10h]@38

*(_OWORD *)Code = 0i64;
v34 = 0;
sub_1400018C0(std::cin, a2, Code);
v2 = -1i64;
v3 = -1i64;
do
++v3;
while ( *((_BYTE *)Code + v3) );
if ( v3 != 19 ) //判断输入的字符串的长度为19
{
sub_140001620(std::cout, "error\n");
_exit((unsigned __int64)Code);
}
v4 = sub_140001E5C(5ui64);
v5 = *(_QWORD *)&::Code; //qwertyuiopasdfghjklzxcvbnm1234567890的首地址
v6 = (__int128 *)v4;
v7 = 0;
v8 = (_BYTE *)v4;
do
{
v9 = v8[(_QWORD)Code - v4];
v10 = 0;
*v8 = v9;
v11 = 0i64;
v12 = -1i64;
do
++v12;
while ( *(_BYTE *)(v5 + v12) );
if ( v12 )
{
do
{
if ( v9 == *(_BYTE *)(v5 + v11) )
break;
++v10;
++v11;
}
while ( v10 < v12 );
}
v13 = -1i64;
do
++v13;
while ( *(_BYTE *)(v5 + v13) );
if ( v10 == v13 )
_exit(v5);
++v8;
}
while ( (signed __int64)&v8[-v4] < 4 );
*(_BYTE *)(v4 + 4) = 0;
do
++v2;
while ( *((_BYTE *)Code + v2) );
v14 = 0i64;
v30 = *v6;
while ( *((_BYTE *)&v30 + v14) )
{
if ( !*((_BYTE *)&v30 + v14 + 1) )
{
++v14;
break;
}
if ( !*((_BYTE *)&v30 + v14 + 2) )
{
v14 += 2i64;
break;
}
if ( !*((_BYTE *)&v30 + v14 + 3) )
{
v14 += 3i64;
break;
}
v14 += 4i64;
if ( v14 >= 0x10 )
break;
}
for ( i = v14 + 1; i < 0x10; ++i )
*((_BYTE *)&v30 + i) = 0;
LODWORD(v16) = sub_140001AB0(Code, v2, &v30, &Size);
v17 = Size;
v18 = v16;
v19 = sub_140001E5C(Size);
v20 = 1;
*(_BYTE *)v19 = *(_BYTE *)(v18 + 2);
v21 = (char *)(v19 + 1);
*(_BYTE *)(v19 + 1) = *(_BYTE *)v18;
*(_BYTE *)(v19 + 2) = *(_BYTE *)(v18 + 3);
*(_BYTE *)(v19 + 3) = *(_BYTE *)(v18 + 1);
*(_BYTE *)(v19 + 4) = *(_BYTE *)(v18 + 6);
*(_BYTE *)(v19 + 5) = *(_BYTE *)(v18 + 4);
*(_BYTE *)(v19 + 6) = *(_BYTE *)(v18 + 7);
*(_BYTE *)(v19 + 7) = *(_BYTE *)(v18 + 5);
*(_BYTE *)(v19 + 8) = *(_BYTE *)(v18 + 10);
*(_BYTE *)(v19 + 9) = *(_BYTE *)(v18 + 8);
*(_BYTE *)(v19 + 10) = *(_BYTE *)(v18 + 11);
*(_BYTE *)(v19 + 11) = *(_BYTE *)(v18 + 9);
*(_BYTE *)(v19 + 12) = *(_BYTE *)(v18 + 14);
*(_BYTE *)(v19 + 13) = *(_BYTE *)(v18 + 12);
*(_BYTE *)(v19 + 14) = *(_BYTE *)(v18 + 15);
*(_BYTE *)(v19 + 15) = *(_BYTE *)(v18 + 13);
*(_BYTE *)(v19 + 16) = *(_BYTE *)(v18 + 18);
*(_BYTE *)(v19 + 17) = *(_BYTE *)(v18 + 16);
*(_BYTE *)(v19 + 18) = *(_BYTE *)(v18 + 19);
*(_BYTE *)(v19 + 19) = *(_BYTE *)(v18 + 17);
*(_BYTE *)(v19 + 20) = *(_BYTE *)(v18 + 22);
*(_BYTE *)(v19 + 21) = *(_BYTE *)(v18 + 20);
*(_BYTE *)(v19 + 22) = *(_BYTE *)(v18 + 23);
for ( *(_BYTE *)(v19 + 23) = *(_BYTE *)(v18 + 21); v20 < v17; ++v21 )
{
v22 = 0i64;
if ( v20 / 3 > 0 )
{
v23 = *v21;
do
{
v23 ^= *(_BYTE *)(v22++ + v19);
*v21 = v23;
}
while ( v22 < v20 / 3 );
}
++v20;
}
*(_QWORD *)&v30 = -4569681940847739698i64;
v24 = v19 - (_QWORD)&v30;
*((_QWORD *)&v30 + 1) = 3819887636644928495i64;
v25 = 0i64;
v31 = -939386845;
v32 = -95004953;
do
{
if ( *((_BYTE *)&v30 + v25) != *((_BYTE *)&v30 + v25 + v24) )
_exit(v7 * v7);
++v7;
++v25;
}
while ( v25 < 24 );
LODWORD(v26) = sub_140001620(std::cout, "You win!");
std::basic_ostream<char,std::char_traits<char>>::operator<<(v26, sub_1400017F0);
return sub_140001E30((unsigned __int64)&v28 ^ v35);
}

刚开始判断了字符串的长度为19
upload successful
v5为qwertyuiopasdfghjklzxcvbnm1234567890的首地址,这里猜测v9为密钥一共是4位的和code有关,v12为v5字符串的长度36,v10为v9在v5中的位置相当于个数组,v13等于36,v4与v8与v9的密钥有关系,在v4的末尾加了\0,进行了一个取字符的一个循环,可以看到这个Golden ratio知道是TEA算法的分支
upload successful

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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
_BYTE *__fastcall sub_140001AB0(__int64 a1, unsigned __int64 a2, unsigned __int8 *a3, unsigned __int64 *a4)
{
unsigned __int64 *v4; // r13
unsigned __int8 *v5; // rbp
unsigned __int64 v6; // rbx
__int64 v7; // rsi
unsigned __int64 v8; // rdi
size_t v9; // rcx
_DWORD *v10; // rax
_DWORD *v11; // r15
signed __int64 v12; // r14
unsigned __int64 v13; // rdi
unsigned __int64 v14; // r9
int v15; // edx
_DWORD *v16; // r8
char v17; // cl
_DWORD *v18; // r12
int v19; // ecx
int v20; // eax
int v21; // ecx
int v22; // eax
int v23; // ecx
int v24; // eax
int v25; // ecx
int v26; // eax
unsigned int v27; // ebp
__int64 v28; // rcx
unsigned int v29; // er10
unsigned int v30; // eax
__int64 v31; // r9
unsigned int *v32; // rbx
__int64 v33; // r11
_DWORD *v34; // rax
__int64 v35; // rsi
__int64 v36; // r14
char v37; // r13
unsigned int v38; // er8
__int64 v39; // rcx
unsigned __int64 v40; // rbx
size_t v41; // rcx
_BYTE *v42; // rax
_BYTE *v43; // rsi
_BYTE *result; // rax
char v45; // [rsp+20h] [rbp-58h]
__int64 v46; // [rsp+28h] [rbp-50h]
signed __int64 v47; // [rsp+30h] [rbp-48h]
int v48; // [rsp+88h] [rbp+10h]
unsigned __int64 *v49; // [rsp+98h] [rbp+20h]

v49 = a4;
v4 = a4;
v5 = a3;
v6 = a2;
v7 = a1;
if ( !a2 )
return 0i64;
v8 = a2 >> 2;
if ( a2 & 3 )
v8 = (a2 >> 2) + 1;
v9 = v8 + 1;
if ( v8 >= 0xFFFFFFFFFFFFFFFFui64 )
v9 = -1i64;
v10 = calloc(v9, 4ui64);
v11 = v10;
if ( !v10 )
return 0i64;
v12 = v8 + 1;
v10[v8] = v6;
v13 = 0i64;
v47 = v12;
v14 = 0i64;
if ( v6 )
{
do
{
v15 = *(unsigned __int8 *)(v14 + v7);
v16 = &v10[v14 >> 2];
v17 = v14++ & 3;
*v16 |= v15 << 8 * v17;
}
while ( v14 < v6 );
}
v18 = calloc(4ui64, 4ui64);
if ( v18 )
{
v19 = v5[7] << 8;
v20 = v5[6];
*v18 |= *v5 | ((v5[1] | (*((unsigned __int16 *)v5 + 1) << 8)) << 8);
v21 = v5[4] | ((v5[5] | ((v20 | v19) << 8)) << 8);
v22 = v5[10];
v18[1] |= v21;
v23 = v5[8] | ((v5[9] | ((v22 | (v5[11] << 8)) << 8)) << 8);
v24 = v5[14];
v18[2] |= v23;
v25 = v5[13] | ((v24 | (v5[15] << 8)) << 8);
v26 = v5[12];
v27 = 0;
v18[3] |= v26 | (v25 << 8);
v28 = (unsigned int)(v12 - 1);
v29 = v11[v28];
v30 = 0x34 / (unsigned int)v12 + 6;
v31 = (unsigned int)(v12 - 1);
v45 = v12 - 1;
v46 = (unsigned int)(v12 - 1);
if ( (unsigned int)v28 >= 1 && 0x34 / (unsigned int)v12 != -6 )
{
do
{
v32 = v11 + 1;
v27 -= 1640531527;
v48 = v30 - 1;
v33 = 0i64;
v34 = v11;
v35 = (v27 >> 2) & 3;
v36 = v31;
v37 = v28;
do
{
v38 = *v32;
++v32;
++v34;
v39 = v35 ^ v33++ & 3;
*(v34 - 1) += ((v27 ^ v38) + (v29 ^ v18[v39])) ^ ((16 * v29 ^ (v38 >> 3)) + ((v29 >> 5) ^ 4 * v38));
v29 = *(v34 - 1);
--v36;
}
while ( v36 );
v31 = v46;
LOBYTE(v28) = v45;
v30 = v48;
v11[v31] += ((v27 ^ *v11) + (v29 ^ v18[v35 ^ v37 & 3])) ^ ((4 * *v11 ^ (v29 >> 5)) + ((*v11 >> 3) ^ 16 * v29));
v29 = v11[v46];
}
while ( v48 );
v12 = v47;
v4 = v49;
}
v40 = 4 * v12;
v41 = 4 * v12 + 1;
if ( (unsigned __int64)(4 * v12) >= 0xFFFFFFFFFFFFFFFFui64 )
v41 = -1i64;
v42 = malloc(v41);
v43 = v42;
if ( v40 )
{
do
{
v42[v13] = v11[v13 >> 2] >> 8 * (v13 & 3);
++v13;
}
while ( v13 < v40 );
}
v42[v40] = 0;
*v4 = v40;
free(v11);
free(v18);
result = v43;
}
else
{
free(v11);
result = 0i64;
}
return result;
}

取输入的前4个字符作为xxtea加密的密钥之后进行xxtea加密,接着进行位置置换操作,然后又进行了以3个为一组的异或,由于没见过什么xxtea的算法(这里还是vct师傅咔嚓咔嚓告诉我的这个算法)于是学习了一下(在这个题结束的时候写了一下)

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
v17 = Size;
v18 = v16;
v19 = sub_140001E5C(Size);
v20 = 1;
*v19 = v18[2];
v21 = v19 + 1;
v19[1] = *v18;
v19[2] = v18[3];
v19[3] = v18[1];
v19[4] = v18[6];
v19[5] = v18[4];
v19[6] = v18[7];
v19[7] = v18[5];
v19[8] = v18[10];
v19[9] = v18[8];
v19[10] = v18[11];
v19[11] = v18[9];
v19[12] = v18[14];
v19[13] = v18[12];
v19[14] = v18[15];
v19[15] = v18[13];
v19[16] = v18[18];
v19[17] = v18[16];
v19[18] = v18[19];
v19[19] = v18[17];
v19[20] = v18[22];
v19[21] = v18[20];
v19[22] = v18[23];
for ( v19[23] = v18[21]; v20 < v17; ++v21 )
{
v22 = 0i64;
if ( v20 / 3 > 0 )
{
v23 = *v21;
do
{
v23 ^= v19[v22++];
*v21 = v23;
}
while ( v22 < v20 / 3 );
}
++v20;
}

我们需要解出来在xxtea加密后的那一串数值
upload successful
00000060E7AFFB28 CE BC 40 6B 7C 3A 95 C0 EF 9B 20 20 91 F7 02 35
00000060E7AFFB38 23 18 02 C8 E7 56 56 FA

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
#include<stdio.h>
int main()
{
int count = 0;
int b[24];
int a[] = { 0xCE, 0xBC, 0x40, 0x6B, 0x7C, 0x3A, 0x95, 0xC0, 0xEF, 0x9B, 0x20, 0x20, 0x91, 0xF7, 0x02, 0x35, 0x23, 0x18, 0x02, 0xC8, 0xE7, 0x56, 0x56, 0xFA };
for (int i = 23; i >= 3; i--)
{

for (int j = 6 - count; j >= 0; j--)
{
a[i] ^= a[j];
}
if (i % 3 == 0)
{
count++;
}

}
for (int i = 0; i < 24; i++)
printf("0x%x,", a[i]);
printf("\n");
b[2] = a[0];
b[0] = a[1];
b[3] = a[2];
b[1] = a[3];
b[6] = a[4];
b[4] = a[5];
b[7] = a[6];
b[5] = a[7];
b[10] = a[8];
b[8] = a[9];
b[11] = a[10];
b[9] = a[11];
b[14] = a[12];
b[12] = a[13];
b[15] = a[14];
b[13] = a[15];
b[18] = a[16];
b[16] = a[17];
b[19] = a[18];
b[17] = a[19];
b[22] = a[20];
b[20] = a[21];
b[23] = a[22];
b[21] = a[23];
for (int i = 0; i < 24; i++)
printf("0x%x,", b[i]);
}
//0xbc,0xa5,0xce,0x40,0xf4,0xb2,0xb2,0xe7,0xa9,0x12,0x9d,0x12,0xae,0x10,0xc8,0x5b,0x3d,0xd7,0x6,0x1d,0xdc,0x70,0xf8,0xdc

进行xxtea解密代码

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
#include <stdio.h>
#include <stdint.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))

void btea(uint32_t* v, int n, uint32_t const key[4])
{
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1) /* Coding Part */
{
rounds = 6 + 52 / n;
sum = 0;
z = v[n - 1];
do
{
sum += DELTA;
e = (sum >> 2) & 3;
for (p = 0; p < n - 1; p++)
{
y = v[p + 1];
z = v[p] += MX;
}
y = v[0];
z = v[n - 1] += MX;
} while (--rounds);
}
else if (n < -1) /* Decoding Part */
{
n = -n;
rounds = 6 + 52 / n;
sum = rounds * DELTA;
y = v[0];
do
{
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--)
{
z = v[p - 1];
y = v[p] -= MX;
}
z = v[n - 1];
y = v[0] -= MX;
sum -= DELTA;
} while (--rounds);
}
}


int main()
{
uint32_t v[6] = { (unsigned int)0x40cea5bc, (unsigned int)0xe7b2b2f4,(unsigned int)0x129d12a9,(unsigned int)0x5bc810ae,(unsigned int)0x1d06d73d,(unsigned int)0xdcf870dc };
uint32_t const k[4] = { (unsigned int)0x67616c66, (unsigned int)0x0, (unsigned int)0X0, (unsigned int)0x0 };//flag密钥
int n = 6; //n的绝对值表示v的长度,取正表示加密,取负表示解密
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
//printf("加密前原始数据:%u %u\n", v[0], v[1]);
//btea(v, n, k);
//printf("加密后的数据:%u %u\n", v[0], v[1]);
btea(v, -n, k);
printf("解密后的数据:%x %x %x %x %x %x\n", v[0], v[1],v[2],v[3],v[4],v[5]);
return 0;
}
//67616c66 5858437b 646e615f 742b2b5f 7d6165 13
//flag{CXX_and_++tea}

TEA系列(微型加密算法)

特征

含有Golden Ratio=0x9E3779B9

密钥长度为16byte(128位)

TEA

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
#include <stdio.h>
#include <stdint.h>

//加密函数
void encrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=0, i; /* set up */
uint32_t delta=0x9e3779b9; /* a key schedule constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
for (i=0; i < 32; i++) { /* basic cycle start */
sum += delta;
v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
} /* end cycle */
v[0]=v0; v[1]=v1;
}
//解密函数
void decrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i; /* set up */
uint32_t delta=0x9e3779b9; /* a key schedule constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
for (i=0; i<32; i++) { /* basic cycle start */
v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
sum -= delta;
} /* end cycle */
v[0]=v0; v[1]=v1;
}

int main()
{
uint32_t v[2]={1,2},k[4]={2,2,3,4};
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
printf("加密前原始数据:%u %u\n",v[0],v[1]);
encrypt(v, k);
printf("加密后的数据:%u %u\n",v[0],v[1]);
decrypt(v, k);
printf("解密后的数据:%u %u\n",v[0],v[1]);
return 0;
}

XTEA

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
#include <stdio.h>
#include <stdint.h>

/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */

void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9;
for (i=0; i < num_rounds; i++) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
}
v[0]=v0; v[1]=v1;
}

void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*num_rounds;
for (i=0; i < num_rounds; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0]=v0; v[1]=v1;
}

int main()
{
uint32_t v[2]={1,2};
uint32_t const k[4]={2,2,3,4};
unsigned int r=32;//num_rounds建议取值为32
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
printf("加密前原始数据:%u %u\n",v[0],v[1]);
encipher(r, v, k);
printf("加密后的数据:%u %u\n",v[0],v[1]);
decipher(r, v, k);
printf("解密后的数据:%u %u\n",v[0],v[1]);
return 0;
}

XXTEA

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
#include <stdio.h>
#include <stdint.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))

void btea(uint32_t *v, int n, uint32_t const key[4])
{
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1) /* Coding Part */
{
rounds = 6 + 52/n;
sum = 0;
z = v[n-1];
do
{
sum += DELTA;
e = (sum >> 2) & 3;
for (p=0; p<n-1; p++)
{
y = v[p+1];
z = v[p] += MX;
}
y = v[0];
z = v[n-1] += MX;
}
while (--rounds);
}
else if (n < -1) /* Decoding Part */
{
n = -n;
rounds = 6 + 52/n;
sum = rounds*DELTA;
y = v[0];
do
{
e = (sum >> 2) & 3;
for (p=n-1; p>0; p--)
{
z = v[p-1];
y = v[p] -= MX;
}
z = v[n-1];
y = v[0] -= MX;
sum -= DELTA;
}
while (--rounds);
}
}


int main()
{
uint32_t v[2]= {1,2};
uint32_t const k[4]= {2,2,3,4};
int n= 2; //n的绝对值表示v的长度,取正表示加密,取负表示解密
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
printf("加密前原始数据:%u %u\n",v[0],v[1]);
btea(v, n, k);
printf("加密后的数据:%u %u\n",v[0],v[1]);
btea(v, -n, k);
printf("解密后的数据:%u %u\n",v[0],v[1]);
return 0;
}

TEA in CTF

例题:Tea相关

认清三种TEA加密

解密代码

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
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<Windows.h>
#include <stdint.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))
void btea(uint32_t *v, int n, uint32_t const key[4])
{
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1) /* Coding Part */
{
rounds = 6 + 52 / n;
sum = 0;
z = v[n - 1];
do
{
sum += DELTA;
e = (sum >> 2) & 3;
for (p = 0; p<n - 1; p++)
{
y = v[p + 1];
z = v[p] += MX;
}
y = v[0];
z = v[n - 1] += MX;
} while (--rounds);
}
else if (n < -1) /* Decoding Part */
{
n = -n;
rounds = 6 + 52 / n;
sum = rounds*DELTA;
y = v[0];
do
{
e = (sum >> 2) & 3;
for (p = n - 1; p>0; p--)
{
z = v[p - 1];
y = v[p] -= MX;
}
z = v[n - 1];
y = v[0] -= MX;
sum -= DELTA;
} while (--rounds);
}
}
void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], delta = 0x9E3779B9, sum = delta*num_rounds;
for (i = 0; i < num_rounds; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0] = v0; v[1] = v1;
}
void decrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0xC6EF3720, i; /* set up */
uint32_t delta = 0x9e3779b9; /* a key schedule constant */
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; /* cache key */
for (i = 0; i<32; i++) { /* basic cycle start */
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
} /* end cycle */
v[0] = v0; v[1] = v1;
}

int main()
{
unsigned int v[2] = { 0xE96DCB1C,0x5434E1AC };
unsigned int key[4] = { 0x656d6f63, 0x7469775f, 0x656d5f68, 0x646E655f };
printf("解密后的数据:%x %x\n", v[0], v[1]);
btea(v, -2, key);
printf("解密后的数据:%x %x\n", v[0], v[1]);
decipher(32, v, key);
printf("解密后的数据:%x %x\n", v[0], v[1]);
decrypt(v, key);
printf("解密后的数据:%x %x\n", v[0], v[1]);
system("pause");

}

childRE

放入ida中,shift+f12找到了主函数

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
signed __int64 sub_140001610()
{
signed __int64 v0; // rax
__int64 v1; // rax
const CHAR *v2; // r11
__int64 v3; // r10
__int64 v4; // r9
const CHAR *v5; // r10
signed __int64 v6; // rcx
__int64 v7; // rax
signed __int64 result; // rax
unsigned int v9; // ecx
__int64 v10; // r9
int v11; // er10
__int64 v12; // r8
__int128 v13; // [rsp+20h] [rbp-38h]
__int128 v14; // [rsp+30h] [rbp-28h]

v13 = 0i64;
v14 = 0i64;
sub_140001080("%s", &v13);
v0 = -1i64;
do
++v0;
while ( *((_BYTE *)&v13 + v0) );
if ( v0 != 31 )
{
while ( 1 )
Sleep(0x3E8u);
}
v1 = sub_140001280(&v13);
v2 = name;
if ( v1 )
{
sub_1400015C0(*(_QWORD *)(v1 + 8));
sub_1400015C0(*(_QWORD *)(v3 + 16));
v4 = dword_1400057E0;
v2[v4] = *v5;
dword_1400057E0 = v4 + 1;
}
UnDecorateSymbolName(v2, outputString, 0x100u, 0);
v6 = -1i64;
do
++v6;
while ( outputString[v6] );
if ( v6 == 62 )
{
v9 = 0;
v10 = 0i64;
do
{
v11 = outputString[v10];
v12 = v11 % 23;
if ( a1234567890Qwer[v12] != *(_BYTE *)(v10 + 5368722552i64) )
_exit(v9);
if ( a1234567890Qwer[v11 / 23] != *(_BYTE *)(v10 + 5368722488i64) )
_exit(v9 * v9);
++v9;
++v10;
}
while ( v9 < 0x3E );
sub_140001020("flag{MD5(your input)}\n", v11 / 23, v12, v10);
result = 0i64;
}
else
{
v7 = sub_1400018A0(std::cout);
std::basic_ostream<char,std::char_traits<char>>::operator<<(v7, sub_140001A60);
result = 0xFFFFFFFFi64;
}
return result;
}

UnDecorateSymbolName函数反修饰指定已修饰的 C++ 符号名,使用方法:

1
2
3
4
5
6
DWORD WINAPI UnDecorateSymbolName(
_In_ PCTSTR DecoratedName,
_Out_ PTSTR UnDecoratedName,
_In_ DWORD UndecoratedLength,
_In_ DWORD Flags
);

DecoratedName [输入]已修饰的 C++ 符号名。此名称能以始终为问号 (?) 的首字符鉴别。UnDecoratedName [输出]指向字符串缓冲区的指针,该缓冲区接收未修饰的名字。UndecoratedLength [输入]UnDecoratedName 缓冲区的大小,为字符数。Flags [输入]用于反修饰已修饰名称的方式的选项。此参数能为零或更多个下列值。
upload successful

1
2
3
4
5
6
7
8
9
10
11
do
{
v11 = outputString[v10];
v12 = v11 % 23;
if ( byte_1400033A0[v12] != *(_BYTE *)(v10 + 0x140003478i64) )
_exit(v9);
if ( byte_1400033A0[v11 / 23] != *(_BYTE *)(v10 + 0x140003438i64) )
_exit(v9 * v9);
++v9;
++v10;
}

可以看到v10对应了两个地址0x140003478与0x140003438与0x1400033A0进行了比较所以以可反写出来

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
#include<stdio.h>
int main()
{
unsigned char a1234567890Qwer[90] = {
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x2D, 0x3D, 0x21, 0x40, 0x23, 0x24,
0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29, 0x5F, 0x2B, 0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69,
0x6F, 0x70, 0x5B, 0x5D, 0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4F, 0x50, 0x7B, 0x7D,
0x61, 0x73, 0x64, 0x66, 0x67, 0x68, 0x6A, 0x6B, 0x6C, 0x3B, 0x27, 0x41, 0x53, 0x44, 0x46, 0x47,
0x48, 0x4A, 0x4B, 0x4C, 0x3A, 0x22, 0x5A, 0x58, 0x43, 0x56, 0x42, 0x4E, 0x4D, 0x3C, 0x3E, 0x3F,
0x7A, 0x78, 0x63, 0x76, 0x62, 0x6E, 0x6D, 0x2C, 0x2E, 0x2F
};
unsigned char c[64] = {
0x28, 0x5F, 0x40, 0x34, 0x36, 0x32, 0x30, 0x21,
0x30, 0x38, 0x21, 0x36, 0x5F, 0x30, 0x2A, 0x30, 0x34, 0x34, 0x32, 0x21, 0x40, 0x31, 0x38, 0x36,
0x25, 0x25, 0x30, 0x40, 0x33, 0x3D, 0x36, 0x36, 0x21, 0x21, 0x39, 0x37, 0x34, 0x2A, 0x33, 0x32,
0x33, 0x34, 0x3D, 0x26, 0x30, 0x5E, 0x33, 0x26, 0x31, 0x40, 0x3D, 0x26, 0x30, 0x39, 0x30, 0x38,
0x21, 0x36, 0x5F, 0x30, 0x2A, 0x26
};//3478
unsigned char b[72] = {
0x35, 0x35, 0x35, 0x36, 0x35, 0x36, 0x35, 0x33,
0x32, 0x35, 0x35, 0x35, 0x35, 0x32, 0x32, 0x32, 0x35, 0x35, 0x36, 0x35, 0x35, 0x36, 0x35, 0x35,
0x35, 0x35, 0x32, 0x34, 0x33, 0x34, 0x36, 0x36, 0x33, 0x33, 0x34, 0x36, 0x35, 0x33, 0x36, 0x36,
0x33, 0x35, 0x34, 0x34, 0x34, 0x32, 0x36, 0x35, 0x36, 0x35, 0x35, 0x35, 0x35, 0x35, 0x32, 0x35,
0x35, 0x35, 0x35, 0x32, 0x32, 0x32
};//38
int count = 0;
for (int i = 0; i < 0x3e; i++)
{
for (char a = 0x20; a <= 0x78; a++)
{
int v11 = a;
int v12 = v11 % 23;
if ((a1234567890Qwer[v12] == c[i]) & (a1234567890Qwer[v11 / 23] == b[i]))
{
printf("%c", a);
count++;
}
}
}
printf("\n");
printf("%d", count);
}
//private: char * __thiscall R0Pxx::My_Aut0_PWN(unsigned char *)

得出来被反修饰的字符串根据vct师傅给的一个网址将 result的值作为参数放入函数UnDecorateSymbolName,这是MSVC++中关于名称解析的一个函数,目前没有找到它的“反函数”,也就是说这里求逆需要选手自行了解名称粉碎的规则,从而求逆。学习链接 https://www.cnblogs.com/victor-ma/p/4184806.html
得到?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<stdio.h>
int main()
{
char a[32] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ12345";
char b[32] = "PQHRSIDTUJVWKEBXYLZ1MF23N45OGCA";
char c[32] = "?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z";
char d[31];
for (int i = 0; i < 31; i++)
{
for (int j = 0; j < 31; j++)
{
if (b[i] == a[j])
{
d[j] = c[i];
break;
}
}
}
for (int i = 0;d[i];i++)
printf("%c", d[i]);
return 0;
}
//Z0@tRAEyuP@xAAA?M_A0_WNPx@@EPDP

Z0@tRAEyuP@xAAA?M_A0_WNPx@@EPDP然后md5进行加密一下
upload successful

Author: L0x1c
Link: https://l0x1c.github.io/2020/01/09/2020-01-09/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
    微信
  • 支付寶
    支付寶