0%

buu

Buuctf

1、lucky_guy

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
unsigned __int64 get_flag()
{
unsigned int v0; // eax
int i; // [rsp+4h] [rbp-3Ch]
int j; // [rsp+8h] [rbp-38h]
__int64 s; // [rsp+10h] [rbp-30h] BYREF
char v5; // [rsp+18h] [rbp-28h]
unsigned __int64 v6; // [rsp+38h] [rbp-8h]

v6 = __readfsqword(0x28u);
v0 = time(0LL);
srand(v0);
for ( i = 0; i <= 4; ++i )
{
switch ( rand() % 200 )
{
case 1:
puts("OK, it's flag:");
memset(&s, 0, 0x28uLL);
strcat((char *)&s, f1);
strcat((char *)&s, &f2);
printf("%s", (const char *)&s);
break;
case 2:
printf("Solar not like you");
break;
case 3:
printf("Solar want a girlfriend");
break;
case 4:
s = 0x7F666F6067756369LL;
v5 = 0;
strcat(&f2, (const char *)&s);
break;
case 5:
for ( j = 0; j <= 7; ++j )
{
if ( j % 2 == 1 )
*(&f2 + j) -= 2;
else
--*(&f2 + j);
}
break;
default:
puts("emmm,you can't find flag 23333");
break;
}
}
return __readfsqword(0x28u) ^ v6;
}

这是主函数,switch中有5个case,case1中f1有半截字符串,我们要得到f2,拼起来才是我们要的flag,那么要f2肯定得从case4出发,到case5,才能得到f2,所以我们很清楚了,注意s是小端序

1
2
3
4
5
6
7
8
9
s=[0x69,0x63,0x75,0x67,0x60,0x6F,0x66,0x7F]
flag = ''
for i in range(8):
if(i%2==1):
flag+=chr(s[i]-2)
else:
flag+=chr(s[i]-1)
print("GXY{do_not_"+ flag)
#GXY{do_not_hate_me}

2、刮开有奖

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
INT_PTR __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
const char *v4; // esi
const char *v5; // edi
int v7[2]; // [esp+8h] [ebp-20030h] BYREF
int v8; // [esp+10h] [ebp-20028h]
int v9; // [esp+14h] [ebp-20024h]
int v10; // [esp+18h] [ebp-20020h]
int v11; // [esp+1Ch] [ebp-2001Ch]
int v12; // [esp+20h] [ebp-20018h]
int v13; // [esp+24h] [ebp-20014h]
int v14; // [esp+28h] [ebp-20010h]
int v15; // [esp+2Ch] [ebp-2000Ch]
int v16; // [esp+30h] [ebp-20008h]
CHAR String[65536]; // [esp+34h] [ebp-20004h] BYREF
char v18[65536]; // [esp+10034h] [ebp-10004h] BYREF

if ( a2 == 272 )
return 1;
if ( a2 != 273 )
return 0;
if ( (_WORD)a3 == 1001 )
{
memset(String, 0, 0xFFFFu);
GetDlgItemTextA(hDlg, 1000, String, 0xFFFF);
if ( strlen(String) == 8 )
{
v7[0] = 'Z';
v7[1] = 'J';
v8 = 83;
v9 = 69;
v10 = 'C';
v11 = 97;
v12 = 78;
v13 = 72;
v14 = 51;
v15 = 110;
v16 = 103;
sub_1710F0((int)v7, 0, 10);
memset(v18, 0, 0xFFFFu);
v18[0] = String[5];
v18[2] = String[7];
v18[1] = String[6];
v4 = sub_171000((int)v18, strlen(v18));
memset(v18, 0, 0xFFFFu);
v18[1] = String[3];
v18[0] = String[2];
v18[2] = String[4];
v5 = sub_171000((int)v18, strlen(v18));
if ( String[0] == v7[0] + 34
&& String[1] == v10
&& 4 * String[2] - 141 == 3 * v8
&& String[3] / 4 == 2 * (v13 / 9)
&& !strcmp(v4, "ak1w")
&& !strcmp(v5, "V1Ax") )
{
MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
}
}
return 0;
}
if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 )
return 0;
EndDialog(hDlg, (unsigned __int16)a3);
return 1;
}

很简单,string长8位,从if中判断前两位分别是,U,J,然后,后六位是两个base64解密移位就出来了。

下面是base64反编译,没有换标

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
_BYTE *__cdecl sub_171000(int a1, int a2)
{
int v2; // eax
int v3; // esi
size_t v4; // ebx
_BYTE *v5; // eax
_BYTE *v6; // edi
int v7; // eax
_BYTE *v8; // ebx
int v9; // edi
int v10; // edx
int v11; // edi
int v12; // eax
int i; // esi
_BYTE *result; // eax
_BYTE *v15; // [esp+Ch] [ebp-10h]
_BYTE *v16; // [esp+10h] [ebp-Ch]
int v17; // [esp+14h] [ebp-8h]
int v18; // [esp+18h] [ebp-4h]

v2 = a2 / 3;
v3 = 0;
if ( a2 % 3 > 0 )
++v2;
v4 = 4 * v2 + 1;
v5 = malloc(v4);
v6 = v5;
v15 = v5;
if ( !v5 )
exit(0);
memset(v5, 0, v4);
v7 = a2;
v8 = v6;
v16 = v6;
if ( a2 > 0 )
{
while ( 1 )
{
v9 = 0;
v10 = 0;
v18 = 0;
do
{
if ( v3 >= v7 )
break;
++v10;
v9 = *(unsigned __int8 *)(v3 + a1) | (v9 << 8);
++v3;
}
while ( v10 < 3 );
v11 = v9 << (8 * (3 - v10));
v12 = 0;
v17 = v3;
for ( i = 18; i > -6; i -= 6 )
{
if ( v10 >= v12 )
{
*((_BYTE *)&v18 + v12) = (v11 >> i) & 0x3F;
v8 = v16;
}
else
{
*((_BYTE *)&v18 + v12) = 64;
}
*v8++ = byte_177830[*((char *)&v18 + v12++)];
v16 = v8;
}
v3 = v17;
if ( v17 >= a2 )
break;
v7 = a2;
}
v6 = v15;
}
result = v6;
*v8 = 0;
return result;
}

3、findit

有一说一这个题不太好猜。

image-20220210153616734

猜测第一个数组是就是flag,其实不是,第二个才是,但搞出来后发现是:

pvkq{m164675262033l4m49lnp7p9mnk28k75}

flag{c164675262033b4c49bdf7f9cda28a75}

然后又猜测是凯撒密码,有点难猜

4、pyre

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
#!/usr/bin/env python

# visit https://tool.lu/pyc/ for more information

print 'Welcome to Re World!'
print 'Your input1 is your flag~'
l = len(input1)
for i in range(l):
num = ((input1[i] + i) % 128 + 128) % 128
code += num

for i in range(l - 1):
code[i] = code[i] ^ code[i + 1]

print code
code = [
'\x1f',
'\x12',
'\x1d',
'(',
'0',
'4',
'\x01',
'\x06',
'\x14',
'4',
',',
'\x1b',
'U',
'?',
'o',
'6',
'*',
':',
'\x01',
'D',
';',
'%',
'\x13']

这是一个pyc文件,所以在线反编译,逆向就行了

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
code = [
'\x1f',
'\x12',
'\x1d',
'(',
'0',
'4',
'\x01',
'\x06',
'\x14',
'4',
',',
'\x1b',
'U',
'?',
'o',
'6',
'*',
':',
'\x01',
'D',
';',
'%',
'\x13']
for i in range(len(code)-2,-1,-1):
code[i] = chr(ord(code[i])^ord(code[i+1]))
flag = ""
for i in range(23):
for j in range(27,127):
num = ((j + i) % 128 + 128) % 128
if num==ord(code[i]):
flag+=chr(j)
break
print(flag)

5 easyre

非常简单,就是一个在数组里寻数的问题,可以用类似爆破的脚本完成。

1
2
3
4
5
6
7
8
9
10
v4 = [42,70,39,34,78,44,34,40,73,63,43,64]
string = chr(0x7E)+"}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)(" + chr(0x27) + '&%$# !"'
flag=""

for i in v4:
for j in range(1,len(string)):
if i == ord(string[j]):
flag+=chr(j+1)

print ("flag{"+flag+"}")

6 rsa

这个rsa难的地方在于,给了两个包,不好打开,注册表打开,可以将其后缀变成txt,或者直接在

http://tool.chacuo.net/cryptrsakeyparse进行n ,e的提取,还给了个enc文件,无法提取,因为这个c是乱码,所以,直接用文件提取来搞

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import gmpy2
import rsa

e = 65537
n = 86934482296048119190666062003494800588905656017203025617216654058378322103517
p = 285960468890451637935629440372639283459
q = 304008741604601924494328155975272418463

phin = (q-1)*(p-1)
d = gmpy2.invert(e, phin)

key = rsa.PrivateKey(n, e, int(d), p, q)

with open("C:\\Users\\10245\\Desktop\\output\\flag.enc", "rb+") as f:
f = f.read()
print(rsa.decrypt(f, key))
#flag{decrypt_256}

7、rome

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
int func()
{
int result; // eax
int v1[4]; // [esp+14h] [ebp-44h]
unsigned __int8 v2; // [esp+24h] [ebp-34h] BYREF
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 v12[29]; // [esp+3Bh] [ebp-1Dh] BYREF

strcpy(v12, "Qsw3sj_lz4_Ujw@l");
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 == '}' )
{
v1[0] = v7;
v1[1] = v8;
v1[2] = v9;
v1[3] = v10;
*(_DWORD *)&v12[17] = 0;
while ( *(int *)&v12[17] <= 15 )
{
if ( *((char *)v1 + *(_DWORD *)&v12[17]) > 64 && *((char *)v1 + *(_DWORD *)&v12[17]) <= 90 )
*((_BYTE *)v1 + *(_DWORD *)&v12[17]) = (*((char *)v1 + *(_DWORD *)&v12[17]) - 51) % 26 + 65;
if ( *((char *)v1 + *(_DWORD *)&v12[17]) > 96 && *((char *)v1 + *(_DWORD *)&v12[17]) <= 122 )
*((_BYTE *)v1 + *(_DWORD *)&v12[17]) = (*((char *)v1 + *(_DWORD *)&v12[17]) - 79) % 26 + 97;
++*(_DWORD *)&v12[17];
}
*(_DWORD *)&v12[17] = 0;
while ( *(int *)&v12[17] <= 15 )
{
result = (unsigned __int8)v12[*(_DWORD *)&v12[17]];
if ( *((_BYTE *)v1 + *(_DWORD *)&v12[17]) != (_BYTE)result )
return result;
++*(_DWORD *)&v12[17];
}
return printf("You are correct!");
}
}
}
}
}
}
return result;
}

这个题就是flag经过变换,要和上面字符串一样,那么最好的办法就是爆破

1
2
3
4
5
6
7
8
9
10
11
12
x = [81,115,119,51,115,106,95,108,122,52,95,85,106,119,64,108]
flag = ''
for k in range(0,16):
for i in range(0,127):
z = i
if i > 64 and i <= 90:
i = (i-51)%26 + 65
if i > 96 and i <= 122:
i = (i-79)%26 + 97
if(i == x[k]):
flag += chr(z)
print(flag)

8 level1

这个题很显然直接逆向或者爆破都可以

读入文件而已,要注意读入的字符串长度是20,而不是文件里给的19,所以要加上个0

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
a=[0,198,
232,
816,
200,
1536,
300,
6144,
984,
51200,
570,
92160,
1200,
565248,
756,
1474560,
800,
6291456,
1782,
65536000,
]
flag=""
for i in range(19):
for j in range(27,127):
if((i&1)!=0):
c=j<<i
if c == a[i]:
flag+=chr(j)
break
else:
c=i*j
if c == a[i]:
flag+=chr(j)
break
print(flag)

tf2020{d9-dE6-20c,括号中就是。

9、TRANSFORM

我们要求的flag分别进行了移位和异或操作,有点简单。

1
2
3
4
5
6
7
8
9
a = [0x67, 0x79, 0x7B, 0x7F, 0x75, 0x2B, 0x3C, 0x52, 0x53, 0x79, 0x57, 0x5E, 0x5D, 0x42, 0x7B, 0x2D, 0x2A, 0x66, 0x42, 0x7E, 0x4C, 0x57, 0x79, 0x41, 0x6B, 0x7E, 0x65, 0x3C, 0x5C, 0x45, 0x6F, 0x62, 0x4D,0x3F]
b=[0x00000009, 0x0000000A, 0x0000000F, 0x00000017, 0x00000007, 0x00000018, 0x0000000C, 0x00000006, 0x00000001, 0x00000010, 0x00000003, 0x00000011, 0x00000020, 0x0000001D, 0x0000000B, 0x0000001E, 0x0000001B, 0x00000016, 0x00000004, 0x0000000D, 0x00000013, 0x00000014, 0x00000015, 0x00000002, 0x00000019, 0x00000005, 0x0000001F, 0x00000008, 0x00000012, 0x0000001A, 0x0000001C, 0x0000000E,0x8]
c=[0]*33
for i in range(33):
a[i]^=b[i]
c[b[i]] = a[i]
for i in range(33):
print(chr(c[i]))
#flag{Tr4nsp0sltiON_Clph3r_1s_3z}

10、urual加密

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // esi
int v5[3]; // [esp+8h] [ebp-74h] BYREF
__int16 v6; // [esp+14h] [ebp-68h]
char v7; // [esp+16h] [ebp-66h]
char v8[100]; // [esp+18h] [ebp-64h] BYREF

sub_403CF8(&aGiveMeYourFlag[1]);
scanf("%s", v8);
memset(v5, 0, sizeof(v5));
v6 = 0;
v7 = 0;
sub_401080(v8, strlen(v8), v5); // BASE64未换表加密
v3 = 0;
while ( *((_BYTE *)v5 + v3) == byte_40E0E4[v3] )
{
if ( ++v3 > strlen((const char *)v5) )
goto LABEL_6;
}
sub_403CF8(aError);
LABEL_6:
if ( v3 - 1 == strlen(byte_40E0E4) )
return sub_403CF8(aAreYouHappyYes);
else
return sub_403CF8(aAreYouHappyNo);
}

然后我试图直接解密,发现不对,这里面还有一个函数

是进行将大小写互换的:secret = ‘zMXHz3TIgnxLxJhFAdtZn2fFk3lYCrtPC2l9’.swapcase()

这样进行大小写互换

然后解密就行了

11、maze

这个题先upx搞一下,然后就是走迷宫,

1
2
3
4
5
6
*******+**
******* **
**** **
** *****
** **F****
** ****

很明显是从+到F,w表示上,a表示左,s表示下,d表示右。结束!


12、相册

这个安卓题还是很难的,有我三面的味了,很real

从字符串中查找,发现应该跟base64有关,我们找一下对应so文件用ida打开

NativeMethod在java里面通常用于调用外部非java的程序。Java有能力调用其他语言编写的函数or方法,这个通过JNI(Java Native Interfface)实现。使用时,通过native关键字告诉JVM这个方法是在外部定义的。

解出来就对了