BUUCTF Reverse WriteUp 3

ACTF rome

是个X86平台的exe文件,看了一下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
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
int func()
{
int result; // eax
int inner[4]; // [esp+14h] [ebp-44h]
unsigned __int8 v2; // [esp+24h] [ebp-34h]
unsigned __int8 v3; // [esp+25h] [ebp-33h]
unsigned __int8 v4; // [esp+26h] [ebp-32h]
unsigned __int8 v5; // [esp+27h] [ebp-31h]
unsigned __int8 v6; // [esp+28h] [ebp-30h]
int v7; // [esp+29h] [ebp-2Fh]
int v8; // [esp+2Dh] [ebp-2Bh]
int v9; // [esp+31h] [ebp-27h]
int v10; // [esp+35h] [ebp-23h]
unsigned __int8 v11; // [esp+39h] [ebp-1Fh]
char res[17]; // [esp+3Bh] [ebp-1Dh]
int i; // [esp+4Ch] [ebp-Ch]

res[0] = 81;
res[1] = 115;
res[2] = 119;
res[3] = 51;
res[4] = 115;
res[5] = 106;
res[6] = 95;
res[7] = 108;
res[8] = 122;
res[9] = 52;
res[10] = 95;
res[11] = 85;
res[12] = 106;
res[13] = 119;
res[14] = 64;
res[15] = 108;
res[16] = 0;
printf("Please input:");
scanf("%s", &v2);
result = v2;
if ( v2 == 'A' )
{
result = v3;
if ( v3 == 'C' )
{
result = v4;
if ( v4 == 'T' )
{
result = v5;
if ( v5 == 'F' )
{
result = v6;
if ( v6 == '{' )
{
result = v11;
if ( v11 == '}' )
{
inner[0] = v7;
inner[1] = v8;
inner[2] = v9;
inner[3] = v10;
for ( i = 0; i <= 15; ++i )
{
if ( *(inner + i) > '@' && *(inner + i) <= 'Z' )
*(inner + i) = (*(inner + i) - 51) % 26 + 65;
if ( *(inner + i) > '`' && *(inner + i) <= 'z' )
*(inner + i) = (*(inner + i) - 79) % 26 + 97;
}
for ( i = 0; i <= 15; ++i )
{
result = res[i];
if ( *(inner + i) != result )
return result;
}
result = printf("You are correct!");
}
}
}
}
}
}
return result;
}

看上去就是让你去爆的,写个脚本,出了

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
import string
table = string.printable
res = [0] * 17
res[0] = 81;
res[1] = 115;
res[2] = 119;
res[3] = 51;
res[4] = 115;
res[5] = 106;
res[6] = 95;
res[7] = 108;
res[8] = 122;
res[9] = 52;
res[10] = 95;
res[11] = 85;
res[12] = 106;
res[13] = 119;
res[14] = 64;
res[15] = 108;
res[16] = 0;

def enc(x:str):
if x.isupper():
return (ord(x) - 51) % 26 + 65
if x.islower():
return (ord(x) - 79) % 26 + 97;
return ord(x)

flag = []
for i in range(16):
for ch in table:
if enc(ch) == res[i]:
flag.append(ch)
break;
print(''.join(flag))

Cae3ar_th4_Gre@t

CrackMe

打开看是个x86下的exe文件,无壳,主函数比较清晰

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
int wmain()
{
FILE *v0; // eax
FILE *v1; // eax
char v3; // [esp+3h] [ebp-405h]
char v4; // [esp+4h] [ebp-404h]
char v5; // [esp+5h] [ebp-403h]
char v6; // [esp+104h] [ebp-304h]
char v7; // [esp+105h] [ebp-303h]
char password; // [esp+204h] [ebp-204h]
char v9; // [esp+205h] [ebp-203h]
char username; // [esp+304h] [ebp-104h]
char v11; // [esp+305h] [ebp-103h]

printf("Come one! Crack Me~~~\n");
username = 0;
memset(&v11, 0, 0xFFu);
password = 0;
memset(&v9, 0, 0xFFu);
while ( 1 )
{
do
{
do
{
printf("user(6-16 letters or numbers):");
scanf("%s", &username);
v0 = (FILE *)sub_4024BE();
fflush(v0);
}
while ( !checkIsAlNum(&username) );
printf("password(6-16 letters or numbers):");
scanf("%s", &password);
v1 = (FILE *)sub_4024BE();
fflush(v1);
}
while ( !checkIsAlNum(&password) );
sub_401090(&username);
v6 = 0;
memset(&v7, 0, 0xFFu);
v4 = 0;
memset(&v5, 0, 0xFFu);
v3 = ((int (__cdecl *)(char *, char *))loc_4011A0)(&v6, &v4);
if ( sub_401830((int)&username, &password) )
{
if ( v3 )
break;
}
printf(&v4);
}
printf(&v6);
return 0;
}

od跟一下到了sub_401830的时候这个username和password有没有变化

image-20200810175727286

好的没变,跟进去看看

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
bool __usercall check@<al>(int a1@<ebx>, int username, const char *password)
{
int i; // [esp+18h] [ebp-22Ch]
signed int data_idx; // [esp+1Ch] [ebp-228h]
signed int k; // [esp+28h] [ebp-21Ch]
unsigned int cnt; // [esp+30h] [ebp-214h]
char v8; // [esp+36h] [ebp-20Eh]
char encrypt1; // [esp+37h] [ebp-20Dh]
char iter1; // [esp+38h] [ebp-20Ch]
unsigned __int8 v11; // [esp+39h] [ebp-20Bh]
unsigned __int8 v12; // [esp+3Ah] [ebp-20Ah]
char v13; // [esp+3Bh] [ebp-209h]
int v14; // [esp+3Ch] [ebp-208h]
char data; // [esp+40h] [ebp-204h]
char v16; // [esp+41h] [ebp-203h]
char data2; // [esp+140h] [ebp-104h]
char v18; // [esp+141h] [ebp-103h]

data_idx = 0;
k = 0;
v12 = 0;
v11 = 0;
data2 = 0;
memset(&v18, 0, 0xFFu);
data = 0;
memset(&v16, 0, 0xFFu);
iter1 = 0;
cnt = 0;
i = 0;
while ( cnt < strlen(password) )
{
if ( isdigit(password[cnt]) )
{
encrypt1 = password[cnt] - '0';
}
else if ( isxdigit(password[cnt]) )
{
if ( *(*(__readfsdword(0x30u) + 24) + 12) != 2 )
password[cnt] = 0x22;
encrypt1 = (password[cnt] | 0x20) - 87;
}
else
{
encrypt1 = ((password[cnt] | 0x20) - 97) % 6 + 10;
}
iter1 = encrypt1 + 16 * iter1;
if ( !((cnt + 1) % 2) ) // 如果是是单数
{
*(&data + i++) = iter1;
a1 = i;
iter1 = 0;
}
++cnt;
} // data 为输入的8个转化为字节
// abcd1234 -> AB CD 12 34
while ( k < 8 )
{
v11 += table[++v12];
v13 = table[v12];
v8 = table[v11];
table[v11] = v13;
table[v12] = v8;
if ( *(__readfsdword(0x30u) + 104) & 0x70 )
v13 = v11 + v12;
*(&data2 + k) = table[(v8 + v13)] ^ *(&data + data_idx);
if ( *(__readfsdword(0x30u) + 2) & 0xFF )
{
v11 = -83;
v12 = 43;
}
sub_401710(&data2, username, k++);
data_idx = k;
if ( k >= (&data + strlen(&data) + 1 - &v16) )
data_idx = 0;
}
v14 = 0;
sub_401470(a1, &data2, &v14);
return v14 == 43924;
}

哇,这个,有点难看啊,初步可以判断出,最上面的data就是对输入的密码取变成字节,然后下面的一张表变来变去,真的不知道如何是好,跟也跟不出,网站翻了一下writeUp,有反调试,如果是在调试就给进行其他的骚操作,淦

最下面的操作是要让data2 = dbappsec,但是这个tabel变来变去是真的难受,跟进去看是个272长度的table,自己写个脚本模拟了一下

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
data = [
0x5E, 0xBE, 0x4D, 0x43, 0x24, 0xEB, 0x58, 0xE4, 0xC2, 0x5C,
0xBD, 0xC4, 0xAB, 0x39, 0x1D, 0x73, 0x27, 0xD7, 0x88, 0xB8,
0xF6, 0xF9, 0x01, 0xF4, 0x6D, 0xEF, 0x00, 0x15, 0x8C, 0xD5,
0x98, 0x11, 0xA5, 0x25, 0x36, 0x1A, 0x21, 0x47, 0xB4, 0x50,
0xDA, 0xBF, 0x31, 0x32, 0x70, 0xC3, 0x60, 0xB9, 0xDB, 0x81,
0xAD, 0xF2, 0xE0, 0xC5, 0xAC, 0xC0, 0x6F, 0x05, 0xB3, 0x51,
0xE7, 0xA6, 0xAE, 0x6B, 0x8F, 0x7D, 0xCF, 0x7B, 0xA3, 0x56,
0x5A, 0x9A, 0xD4, 0x76, 0x42, 0x9F, 0x53, 0x80, 0xB5, 0x0F,
0xA0, 0xCB, 0x8B, 0xA1, 0x13, 0x2D, 0x85, 0x93, 0xFE, 0xCC,
0x1B, 0xF0, 0x54, 0x61, 0x20, 0x1C, 0xFB, 0x7F, 0x17, 0x64,
0x4A, 0x9D, 0xD0, 0x03, 0xA8, 0x2F, 0x37, 0x30, 0x3D, 0x33,
0xE2, 0x83, 0x8E, 0xD9, 0xB7, 0x18, 0xF7, 0x59, 0xDC, 0x0B,
0x77, 0xAF, 0xEA, 0xB1, 0x10, 0x35, 0x7C, 0x55, 0x4B, 0x74,
0x26, 0xB2, 0x8D, 0x8A, 0x91, 0x97, 0x89, 0xE8, 0xD2, 0x79,
0x3C, 0x44, 0x40, 0x5D, 0xCE, 0x9E, 0x9C, 0x3E, 0x75, 0x29,
0x72, 0x2B, 0xBB, 0x1E, 0x6A, 0x28, 0x2E, 0x62, 0xDF, 0xA2,
0x02, 0x09, 0xBA, 0xC6, 0x3A, 0xB6, 0x4E, 0x7A, 0x71, 0x38,
0x99, 0x65, 0xAA, 0x9B, 0x4C, 0xE6, 0x0C, 0x6C, 0xCD, 0xA7,
0xE3, 0x16, 0xD3, 0x19, 0x49, 0xF5, 0x12, 0xC8, 0x41, 0xDE,
0x06, 0x07, 0x95, 0xD8, 0xFA, 0x66, 0x2A, 0x7E, 0x94, 0x0D,
0x48, 0x90, 0xCA, 0x04, 0xED, 0x67, 0xE5, 0x4F, 0x2C, 0x1F,
0x14, 0xC1, 0xC9, 0xA4, 0xF8, 0x08, 0xE1, 0xB0, 0xEC, 0xE9,
0xA9, 0x34, 0xDD, 0x57, 0x23, 0x87, 0xC7, 0xEE, 0x3B, 0x5B,
0x46, 0x69, 0x84, 0x86, 0x0E, 0x96, 0x78, 0xD1, 0xFD, 0xFF,
0x68, 0xBC, 0x63, 0xF3, 0xD6, 0xFC, 0x82, 0x3F, 0x92, 0x52,
0x6E, 0x5F, 0x22, 0xF1, 0x0A, 0x45, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
]
data2 = 'dbappsec'
idx1, idx2, idx3, idx4 = 0,0,0,0

password = []
for i in range(8):
idx1 += 1
idx2 += data[idx1]
idx2 &= 0xff
idx3 = data[idx1]
idx3 &= 0xff
idx4 = data[idx2]
data[idx2] = idx3
data[idx1] = idx4
# idx3 = (idx1 + idx2) & 0xff
ch = data[(idx3 + idx4)&0xff] ^ ord(data2[i])
password.append(chr(ch))

print(password)

['N', 'µ', 'ó', '\x99', '#', '\x91', '¡', '®'],这是人能打出来的?

完全对不上号啊,跟一下每次xor的值吧,反正这个是固定的,只和调试器的状态有关

0x7e 0x98 0xc9 0x95 0x10 0x6d 0xf3 0x67

淦,不对,用OD跟一下

0x2a, 0xd7, 0x92, 0xe9, 0x53, 0xe2, 0xc4, 0xcd

和我写脚本模拟出来的一摸一样['N', 'µ', 'ó', '\x99', '#', '\x91', '¡', '®']

等等,这个,确实是人能够打出来的,毕竟都转化成字节序列了,试试4eb5f3992391a1ae

好像还是不对,淦,下面函数里面还要和username进行一次xor,好了出了

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
import hashlib

data = [
0x5E, 0xBE, 0x4D, 0x43, 0x24, 0xEB, 0x58, 0xE4, 0xC2, 0x5C,
0xBD, 0xC4, 0xAB, 0x39, 0x1D, 0x73, 0x27, 0xD7, 0x88, 0xB8,
0xF6, 0xF9, 0x01, 0xF4, 0x6D, 0xEF, 0x00, 0x15, 0x8C, 0xD5,
0x98, 0x11, 0xA5, 0x25, 0x36, 0x1A, 0x21, 0x47, 0xB4, 0x50,
0xDA, 0xBF, 0x31, 0x32, 0x70, 0xC3, 0x60, 0xB9, 0xDB, 0x81,
0xAD, 0xF2, 0xE0, 0xC5, 0xAC, 0xC0, 0x6F, 0x05, 0xB3, 0x51,
0xE7, 0xA6, 0xAE, 0x6B, 0x8F, 0x7D, 0xCF, 0x7B, 0xA3, 0x56,
0x5A, 0x9A, 0xD4, 0x76, 0x42, 0x9F, 0x53, 0x80, 0xB5, 0x0F,
0xA0, 0xCB, 0x8B, 0xA1, 0x13, 0x2D, 0x85, 0x93, 0xFE, 0xCC,
0x1B, 0xF0, 0x54, 0x61, 0x20, 0x1C, 0xFB, 0x7F, 0x17, 0x64,
0x4A, 0x9D, 0xD0, 0x03, 0xA8, 0x2F, 0x37, 0x30, 0x3D, 0x33,
0xE2, 0x83, 0x8E, 0xD9, 0xB7, 0x18, 0xF7, 0x59, 0xDC, 0x0B,
0x77, 0xAF, 0xEA, 0xB1, 0x10, 0x35, 0x7C, 0x55, 0x4B, 0x74,
0x26, 0xB2, 0x8D, 0x8A, 0x91, 0x97, 0x89, 0xE8, 0xD2, 0x79,
0x3C, 0x44, 0x40, 0x5D, 0xCE, 0x9E, 0x9C, 0x3E, 0x75, 0x29,
0x72, 0x2B, 0xBB, 0x1E, 0x6A, 0x28, 0x2E, 0x62, 0xDF, 0xA2,
0x02, 0x09, 0xBA, 0xC6, 0x3A, 0xB6, 0x4E, 0x7A, 0x71, 0x38,
0x99, 0x65, 0xAA, 0x9B, 0x4C, 0xE6, 0x0C, 0x6C, 0xCD, 0xA7,
0xE3, 0x16, 0xD3, 0x19, 0x49, 0xF5, 0x12, 0xC8, 0x41, 0xDE,
0x06, 0x07, 0x95, 0xD8, 0xFA, 0x66, 0x2A, 0x7E, 0x94, 0x0D,
0x48, 0x90, 0xCA, 0x04, 0xED, 0x67, 0xE5, 0x4F, 0x2C, 0x1F,
0x14, 0xC1, 0xC9, 0xA4, 0xF8, 0x08, 0xE1, 0xB0, 0xEC, 0xE9,
0xA9, 0x34, 0xDD, 0x57, 0x23, 0x87, 0xC7, 0xEE, 0x3B, 0x5B,
0x46, 0x69, 0x84, 0x86, 0x0E, 0x96, 0x78, 0xD1, 0xFD, 0xFF,
0x68, 0xBC, 0x63, 0xF3, 0xD6, 0xFC, 0x82, 0x3F, 0x92, 0x52,
0x6E, 0x5F, 0x22, 0xF1, 0x0A, 0x45, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
]
data2 = 'dbappsec'
username = 'welcomebeijing'
idx1, idx2, idx3, idx4 = 0,0,0,0

password = []
for i in range(8):
idx1 += 1
idx2 += data[idx1]
idx2 &= 0xff
idx3 = data[idx1]
idx3 &= 0xff
idx4 = data[idx2]
data[idx2] = idx3
data[idx1] = idx4
# idx3 = (idx1 + idx2) & 0xff
ch = data[(idx3 + idx4)&0xff] ^ ord(data2[i])
ch ^= ord(username[i])
password.append(hex(ch))


print(password)


试了下密码39d09ffa4cfcc4cc,出了,但是md5对字节加密,对字符串加密都不对?

image-20200810225935016

nmdwsm,我明明已经关了IDA和OD了啊???

网上找了一下d2be2981b84f2a905669995873d6a36c,这就是4eb5f3992391a1ae的md5

出了,结果是来自于-同用户名进行xor的不会被执行,???什么阴间题目

firmware

路由器固件?有点东西,这个没学过是真的不会,网上找找教程,用binwalk好像也没有搞出个什么东西来,然后按照官方的重新安装了一次binwalk之后,奇迹出现了,在/tmp下找到一个名为backdoor的文件,太明显了下载下来看看

发现是用UPX加壳过的,使用upx脱壳,然后发现主函数非常长,确实是一个后门

逐渐分析到了initConnection函数

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
bool initConnection()
{
char *v0; // r0
char s; // [sp+4h] [bp-208h]
int v3; // [sp+204h] [bp-8h]

memset(&s, 0, 0x200u);
if ( mainCommSock )
{
close(mainCommSock);
mainCommSock = 0;
}
if ( currentServer )
++currentServer;
else
currentServer = 0;
strcpy(&s, (&commServer)[currentServer]);
v3 = 36667;
if ( strchr(&s, ':') )
{
v0 = strchr(&s, ':');
v3 = atoi(v0 + 1);
*strchr(&s, ':') = 0;
}
mainCommSock = socket(2, 1, 0);
return connectTimeout(mainCommSock, &s, v3, 30) == 0;
}

这不就出了嘛echo.byethost51.com:36667

xxor

是个Linux x86_64文件,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
38
39
40
41
42
43
44
45
46
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
signed int i; // [rsp+8h] [rbp-68h]
signed int j; // [rsp+Ch] [rbp-64h]
__int64 input[5]; // [rsp+10h] [rbp-60h]
__int64 encrypted[5]; // [rsp+40h] [rbp-30h]
unsigned __int64 v8; // [rsp+68h] [rbp-8h]

v8 = __readfsqword(0x28u);
puts("Let us play a game?");
puts("you have six chances to input");
puts("Come on!");
input[0] = 0LL;
input[1] = 0LL;
input[2] = 0LL;
input[3] = 0LL;
input[4] = 0LL;
for ( i = 0; i <= 5; ++i )
{
printf("%s", "input: ", (unsigned int)i);
__isoc99_scanf("%d", (char *)input + 4 * i);
}
encrypted[0] = 0LL;
encrypted[1] = 0LL;
encrypted[2] = 0LL;
encrypted[3] = 0LL;
encrypted[4] = 0LL;
for ( j = 0; j <= 2; ++j )
{
front_half = input[j];
back_half = *((_DWORD *)input + j * 2 + 1);
encrypt((unsigned int *)&front_half, &key);
LODWORD(encrypted[j]) = front_half;
*((_DWORD *)encrypted + j * 2 + 1) = back_half;
}
if ( (unsigned int)check(encrypted) != 1 )
{
puts("NO NO NO~ ");
exit(0);
}
puts("Congratulation!\n");
puts("You seccess half\n");
puts("Do not forget to change input to hex and combine~\n");
puts("ByeBye");
return 0LL;
}

大概就是输入了6个int32的数,然后放在3个int64的数中进行加密操作,最后要等于一个结果,其实可以在网上找找轮子之类的

看一下最后的check部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
signed __int64 __fastcall check(_DWORD *a1)
{
signed __int64 result; // rax

if ( a1[2] - a1[3] != 0x84A236FFLL || a1[3] + a1[4] != 0xFA6CB703LL || a1[2] - a1[4] != 0x42D731A8LL )
{
puts("Wrong!");
result = 0LL;
}
else if ( *a1 != 0xDF48EF7E || a1[5] != 0x84F30420 || a1[1] != 0x20CAACF4 )
{
puts("Wrong!");
result = 0LL;
}
else
{
puts("good!");
result = 1LL;
}
return result;
}

小学生方程,找个计算器就可以解出来结果的值,容我先装个z3,以后总有用

[x = 3774025685, y = 1548802262, z = 2652626477]

解出来6个加密的数分别是

a = {0xDF48EF7E, 0x20CAACF4, 0xe0f30fd5, 0x5c50d8d6, 0x9e1bde2d, 0x84F30420}

然后写个java脚本求解

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

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;

public class Leet {
public static void main(final String[] args) throws Exception {
final Solution l = new Solution();
int[] cipher = {0xDF48EF7E, 0x20CAACF4, 0xe0f30fd5, 0x5c50d8d6, 0x9e1bde2d, 0x84F30420};
ArrayList<Integer> res = new ArrayList<>();
ArrayList<Integer> cip = new ArrayList<>();
for(int i=0; i<cipher.length; i+=2){
int[] arr = l.decry(cipher[i], cipher[i+1]);
res.add(arr[0]);
res.add(arr[1]);
int[] c = l.encry(arr[0], arr[1]);
cip.add(c[0]);
cip.add(c[1]);
}
System.out.println(res);
for(int x: res){
System.out.print(Integer.toHexString(x));
System.out.print(",");
}
System.out.println();
System.out.println(cip);
for(int x: cip){
System.out.print(Integer.toHexString(x));
System.out.print(",");
}
System.out.println();
System.out.println(Arrays.toString(cipher));
}
}

class Solution {
int[] decry(int num1, int num2){
int[] key = {2, 2, 3, 4};
int magic = 0x458bcd42;
int delta = magic * 0x40;
for(int i=0; i<=0x3f; i++){
num2 -= (num1 + delta + 20) ^ ((num1 << 6) + key[2]) ^ ((num1 >> 9) + key[3]) ^ 0x10;
num1 -= (num2 + delta + 11) ^ ((num2 << 6) + key[0]) ^ ((num2 >> 9) + key[1]) ^ 0x20;
delta -= magic;
}
return new int[] {num1, num2};
}

int[] encry(int num1, int num2){
int[] key = {2, 2, 3, 4};
int delta = 0;
for (int i = 0; i <= 0x3F; ++i )
{
delta += 0x458BCD42;
num1 += (num2 + delta + 11) ^ ((num2 << 6) + key[0]) ^ ((num2 >> 9) + key[1]) ^ 0x20;
num2 += (num1 + delta + 20) ^ ((num1 << 6) + key[2]) ^ ((num1 >> 9) + key[3]) ^ 0x10;
}
return new int[] {num1, num2};
}
}

[-698534522, -1541066437, 1578206992, -287775654, 1339222190, -130761337]这个是错的

因为java这个int是带符号的,写个C脚本

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

void decry(unsigned int num1,unsigned int num2, unsigned int* res){
int key[] = {2, 2, 3, 4};
int magic = 0x458bcd42;
int delta = magic * 0x40;
int i = 0;
for(i=0; i<=0x3f; i++){
num2 -= (num1 + delta + 20) ^ ((num1 << 6) + key[2]) ^ ((num1 >> 9) + key[3]) ^ 0x10;
num1 -= (num2 + delta + 11) ^ ((num2 << 6) + key[0]) ^ ((num2 >> 9) + key[1]) ^ 0x20;
delta -= magic;
}
res[0] = num1;
res[1] = num2;
}

int main(){
unsigned int res[2] = {0, 0};
unsigned int cipher[6] = {0xDF48EF7E, 0x20CAACF4, 0xe0f30fd5, 0x5c50d8d6, 0x9e1bde2d, 0x84F30420};
int i = 0;
for(i = 0; i<6; i+=2){
unsigned num1 = cipher[i];
unsigned num2 = cipher[i+1];
decry(num1, num2, res);
printf("%x, %x,", res[0], res[1]);
}
}

666c61, 677b72,655f69, 735f67,726561, 74217d

然后hex转str一下flag{re_is_great!}

至此,BUUCTF的1分的题目全部解决,撒花★,°:.☆( ̄▽ ̄)/$:.°★