avatar

Buuctf wp

记录一下buuctf的write up.

RE

Easyre

下载后的拖进ida64:

upload successful

发现 flag{this_Is_a_EaSyRe}

helloword

打开下载的压缩包里面发现是个apk的文件
拖进APK改之理找到主函数发现flag

upload successful

flag{7631a988259a00816deda84afb29430a}

Reverse1

打开压缩包拖进dbg,由于我们现在在内核模式空间(.dll),我们需要自己调整到用户层面(.exe),所以按一下alt+f9

upload successful
大概主函数在exit的附近看见exit有两个我们在附近进去看看

upload successful
我们看到了flag的值 但是我们需要判断进行了什么操作,然后我们去进行分析

upload successful
经过分析来说

1
2
if ( Str2[j] == 'o' )
Str2[j] = '0';

可以看到进行的操作是o字符变成了0所以flag为:
flag{hell0_world}

Reverse2

打开压缩包放进ida

upload successful
可以看到里面进行了判断如果字符串有i和r就变成1 看到了strcmp里面进行和flag地址进行了比较

1
2
3
.data:0000000000601080 flag            db '{'                  ; DATA XREF: main+34↑r
.data:0000000000601080 ; main+44↑r ...
.data:0000000000601081 aHackingForFun db 'hacking_for_fun}',0

我们可以推出来flag{hacking_for_fun}进行变换:flag{hack1ng_fo1_fun}

新年快乐

我们把这个压缩包拖进PEiD的时候发现有壳是一个upx的壳

upload successful
我们把这个包拖进dbg 找到popad

upload successful
我们给jmp下断点

upload successful
到call 00401000位置进去 发现已经脱壳成功

upload successful
进行字符串探索 进入到403024:"please input the true flag:"位置进去看看

upload successful
我们可以分析出来进行了字符串的strcmp的函数功能判断是否和HappyNewYear!相同
flag为flag{HappyNewYear!}

xor

打开压缩文件,拖进ida

upload successful
看到strcmp函数进行了比较,我们进去看一下再跳转到100000F6Eh可以看到进行了字符串

upload successful

1
2
for ( i = 1; i < '!'; ++i )
v6[i] ^= v6[i - 1];

可以不难分析,进行了前一个和下一个字符串进行了异或,第一个字符串不变,而两次异或就是原来的值所以我们写一个python的脚本

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/python
str1 = ['f', 0x0A, 'k', 0x0C, 'w', '&', 'O', '.', '@', 0x11, 'x', 0x0D, 'Z', ';', 'U', 0x11, 'p', 0x19, 'F', 0x1F, 'v', '"', 'M', '#', 'D', 0x0E, 'g', 6, 'h', 0x0F, 'G', '2', 'O']
x = 'f'
for i in range(1, len(str1)):
if (isinstance(str1[i], str)):
if (isinstance(str1[i - 1], str)):
x += chr(ord(str1[i]) ^ ord(str1[i - 1]))
else:
x += chr(ord(str1[i]) ^ str1[i - 1])
else:
x += chr(str1[i] ^ ord(str1[i - 1]))
print(x)

跑出来就是:

upload successful

内涵的软件

打开压缩包中的文件拖进ida

upload successful
进入pirntf的里面那个地址看看有什么重要信息

upload successful
Y输入就是

upload successful
N输入就是

upload successful
如果输入非Y/N就是

upload successful
我们看一下结果的函数我们发现了提示

upload successful

flag为:flag{49d3c93df25caad81232130f3d2ebfad}

Reverse3

我们打开压缩包里的文件放进ida

upload successful
看见了strcmp的函数里面进行了比较我们进去看一下

upload successful
我们看到了关键的字符串:e3nifIH9b_C@n@dH

1
2
for ( j = 0; j < v10; ++j )
Dest[j] += j;

看到了这个函数我们就知道我们进行的操作是dest字符串第一个减去0第二个减去2 是原来的数组
写一个python的脚本

1
2
3
4
5
6
#!/usr/bin/python
s = "e3nifIH9b_C@n@dH"
x = " "
for i in range(0,len(s)):
x += chr(ord(s[i]) - i)
print(x)

得到字符串 e2lfbDB2ZV95b3V9
strncpy是放进第一个数组里面我们看一下v1函数进行的操作

upload successful

upload successful看到了的数是base64进行转换的数
去写python脚本

1
2
3
4
5
6
7
#!/usr/bin/python
import base64
s = "e3nifIH9b_C@n@dH"
x = " "
for i in range(0,len(s)):
x += chr(ord(s[i]) - i)
print(base64.b64decode(x))

运行出现了flag:flag{i_l0ve_you}

不一样的flag

打开压缩包文件放进ida

upload successful

1
2
3
4
5
6
7
if ( v8[5 * v4 - 41 + v5] == '1' )
exit(1);
if ( v8[5 * v4 - 41 + v5] == '#' )
{
puts("\nok, the order you enter is the flag!");
exit(0);
}

可以分析出来1是j结束运行到#就是flag

upload successful
可以看到一个关键的字符串:*11110100001010000101111#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    if ( v6 == 2 )
{
++v4;
}
else if ( v6 > 2 )
{
if ( v6 == 3 )
{
--v5;
}
else
{
if ( v6 != 4 )
LABEL_13:
exit(1);
++v5;
}
}
else
{
if ( v6 != 1 )
goto LABEL_13;
--v4;
}

可以看到v6是输入的值,我们up和down是v4进行操作,left和right是v5进行操作
5 * v4 - 41 + v5 看出来是5*5方阵:
*1111
01000
01010
00010
1111#
走迷宫flag为22244114422:flag{22244114422}

刮开有奖

把程序放入ida中,进行分析,找到了主函数
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
  memset(&String, 0, 0xFFFFu);
GetDlgItemTextA(hDlg, 1000, &String, 0xFFFF);
if ( strlen(&String) == 8 )
{
v7 = 'Z';
v8 = 'J';
v9 = 'S';
v10 = 'E';
v11 = 'C';
v12 = 'a';
v13 = 'N';
v14 = 'H';
v15 = '3';
v16 = 'n';
v17 = 'g';
sub_4010F0(&v7, 0, 10);
memset(&v26, 0, 0xFFFFu);
v26 = v23;
v28 = v25;
v27 = v24;
v4 = (const char *)sub_401000(&v26, strlen(&v26));
memset(&v26, 0, 0xFFFFu);
v27 = v21;
v26 = v20;
v28 = v22;
v5 = (const char *)sub_401000(&v26, strlen(&v26));
if ( String == v7 + 34
&& v19 == v11
&& 4 * v20 - 141 == 3 * v9
&& v21 / 4 == 2 * (v14 / 9)
&& !strcmp(v4, "ak1w")
&& !strcmp(v5, "V1Ax") )
{
MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
}
}
return 0;
}

GetDlgItemTextA(hDlg, 1000, &String, 0xFFFF)知道是我们输入的位置,下面对string进行了判定,知道我们输入的字符应该是8位,然后对v9的开始的地址的数值中间有个函数的调用,我们进去看一下

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
int __cdecl sub_4010F0(int a1, int a2, int a3)
{
int result; // eax
int i; // esi
int v5; // ecx
int v6; // edx

result = a3;
for ( i = a2; i <= a3; a2 = i )
{
v5 = 4 * i;
v6 = *(_DWORD *)(4 * i + a1);
if ( a2 < result && i < result )
{
do
{
if ( v6 > *(_DWORD *)(a1 + 4 * result) )
{
if ( i >= result )
break;
++i;
*(_DWORD *)(v5 + a1) = *(_DWORD *)(a1 + 4 * result);
if ( i >= result )
break;
while ( *(_DWORD *)(a1 + 4 * i) <= v6 )
{
if ( ++i >= result )
goto LABEL_13;
}
if ( i >= result )
break;
v5 = 4 * i;
*(_DWORD *)(a1 + 4 * result) = *(_DWORD *)(4 * i + a1);
}
--result;
}
while ( i < result );
}
LABEL_13:
*(_DWORD *)(a1 + 4 * result) = v6;
sub_4010F0(a1, a2, i - 1);
result = a3;
++i;
}
return result;
}

转化成了c进行了运行,看一下进行了什么变化
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
_BYTE *__cdecl sub_401000(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
signed int v10; // edx
int v11; // edi
signed int v12; // eax
signed int v13; // 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);
}
while ( v10 < 3 );
v11 = v9 << 8 * (3 - v10);
v12 = 0;
v17 = v3;
v13 = 18;
do
{
if ( v10 >= v12 )
{
*((_BYTE *)&v18 + v12) = (v11 >> v13) & 0x3F;
v8 = v16;
}
else
{
*((_BYTE *)&v18 + v12) = 64;
}
*v8++ = byte_407830[*((char *)&v18 + v12)];
v13 -= 6;
++v12;
v16 = v8;
}
while ( v13 > -6 );
v3 = v17;
if ( v17 >= a2 )
break;
v7 = a2;
}
v6 = v15;
}
result = v6;
*v8 = 0;
return result;
}

知道这是个base64:密码表为
upload successful
flag的判别:

1
2
3
4
5
6
7
8
9
if ( String == v7 + 34
&& v19 == v11
&& 4 * v20 - 141 == 3 * v9
&& v21 / 4 == 2 * (v14 / 9)
&& !strcmp(v4, "ak1w")
&& !strcmp(v5, "V1Ax") )
{
MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
}

可以看出来后面的两个base64的加密等于V1Axak1w 前面的等于一个U一个J

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/python
import base64
base_now="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
base_init="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
clear="V1Axak1w"
c=""
for i in range(len(clear)):
b=base_now.find(clear[i])
c+=base_init[b]
c=base64.b64decode(c)
print c

结果flag为:flag{UJWP1jMp}

SimpleRev

把程序放入ida中,找到主函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
int v3; // eax
char v4; // [rsp+Fh] [rbp-1h]

while ( 1 )
{
while ( 1 )
{
printf("Welcome to CTF game!\nPlease input d/D to start or input q/Q to quit this program: ", argv, envp);
v4 = getchar();
if ( v4 != 100 && v4 != 68 )
break;
Decry();
}
if ( v4 == 113 || v4 == 81 )
Exit();
puts("Input fault format!");
v3 = getchar();
putchar(v3);
}
}

可以看出来,重要的是Decry函数:
upload successful
str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;运算,最后与text比较
直接给程序跑了:

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
#include <stdio.h>
int main(void)
{
int i, j, n = 0, v5 = 10, v3 = 0, v2 = 0;
char v1;
char flag[11] = { 0 };
char str2[104] = { 0 };
char key[] = "ADSFKNDCLS";
char text[] = "killshadow";


for (i = 0; i < v5; ++i)
{
if (key[v3 % v5] > 64 && key[v3 % v5] <= 90)
key[i] = key[v3 % v5] + 32;
++v3;
}
for (j = 0; j < 10; ++j) {
for (v2 = 0; v2 < 10; ++v2) {
v1 = text[v2] - 97 + 26 * j - 97 + key[v3++ % v5] + 39;
if ((v1 >= 65 && v1 <= 90) || (v1 >= 97 && v1 <= 122)) {
flag[v2] = v1;
if (++n == 10) {
printf("%s\n", flag);
return 0;
}
}
}
}
return 0;
}

upload successful
出来了flag:flag{KLDQCUDFZO}

Java逆向解密

[SWPU2019]EasiestRe

这道题主要运用了od的分析,打开放入了ida Shift+f12进行字符串检索看到了关键字
upload successful
进入查看
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
do
{
v7 = (int *)&v24;
if ( v26 >= 0x10 )
v7 = v24;
*((_BYTE *)v7 + v5) ^= *((_BYTE *)&v33 + v5 % v6);
++v5;
}
while ( v5 < 32 );
v8 = (int *)&v24;
v4 = (int)v24;
if ( v26 >= 0x10 )
v8 = v24;
v29 = 0;
v27 = 0i64;
v28 = 0i64;
*(_QWORD *)&v30 = *(_QWORD *)v8;
*((_QWORD *)&v30 + 1) = *((_QWORD *)v8 + 1);
*(_QWORD *)&v31 = *((_QWORD *)v8 + 2);
*((_QWORD *)&v31 + 1) = *((_QWORD *)v8 + 3);
sub_4025C0(v22, v23, 256, (unsigned int)&v30, (unsigned int)&v27);
v36 = -133220429;
v37 = 1571732668;
v9 = &v36;
v38 = -2041750854;
v10 = &v27;
v39 = -748513468;
v11 = 28;
v40 = 371505743;
v41 = 443719435;
v42 = 644704357;
v43 = 1741188026;
while ( 1 )
{
v12 = *v9;
if ( *v9 != *(_DWORD *)v10 )
break;
++v9;
v10 = (__int128 *)((char *)v10 + 4);
v14 = v11 < 4;
v11 -= 4;
if ( v14 )
{
v13 = 0;
goto LABEL_19;
}
}

这个就是主函数,防止od与ida不对应,我就看了pe结构进行了修改
upload successful
可以看到dynamic_base 是动态链接库属性
upload successful
找到了位置,由于偏移量,修改成00 81

进入od 发现第一次的异或的位置:具体的地方给了注释
upload successful
upload successful
upload successful
我们进行了分析,他把我们输入的值和所对应的密钥进行了异或的关系

我们下内存断点然后F9,看后面是谁对这串字符进行了操作
upload successful
找到了后,我们看到只是放到了堆栈里面,既没有cmp和je或者jne,所以需要继续下内存断点
upload successful
发现,ecx里面存的是第二次异或的密钥,那么我们还要继续下内存断点
upload successful
发现,有了cmp函数进行比较,这样我们的思路就完全分析明白了,自己改了ZF标志位分析后发现进行了两次异或操作然后跟最后的进行比较,看是否正确,所以写了c语言
upload successful
出现了flag:flag{Y0uaretheB3st!#@_VirtualCC}

[SWPU2019]Android1

拿到后,直接把.so文件放进了ida,shift+f12发现flag字段后,发现不对,分了很奇怪的4个函数,c语言如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<string.h> 
#include <stdio.h>
int main() {
char v3[] = "MWa";
char v2[3]; //后一次为4
for (int i = 0; i <= 2; ++i)
v2[i] = v3[i] ^ 0x38;
//uoY
char v3[] = "AVE";
for (int i = 0; i <= 2; ++i)
v2[i] = v3[i] ^ 0x24;
//era
char v3[] = "R_C";
for (int i = 0; i <= 2; ++i)
v2[i] = v3[i] ^ 0x37; /
/eht
char v3[] = "#$D5";
for (int i = 0; i <= 3; ++i)
v2[i] = v3[i] ^ 0x77;
//TS3B
for (int i = 0; i <= 3; ++i)
printf("%c", v2[i]);
return 0; }

flag为:flag{YouaretheB3ST}

[SWPU2019]Android3

找到check函数:
upload successful
判断长度是否为11,根据data值操作来存放数组的下标,进行调用fun1
upload successful
相当于链表,查看fun2
upload successful
V1=原始值 v2= -1^((b下标+原来下标)%2)
upload successful
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
int main(){ 
char a[] = "0123456789a";
int data[] = { 6, 2, 5, 0, 7, 3, 10, 9, 1, 4, 8 };
int data2[] = { 0x3C, 0x6C, 0x33, 0x4F, 0x81, 0x38, 0x2C, 0x5E, 0x54, 0x45, 0x40 };
int v1[24] = { 0 };
int b; int* z1;
int* z2;
int* z3;
for (int i = 0; i < 11; i++) {
b = data[i];
v1[2 * b ] = i;
v1[2 * b + 1] = a[i]; }
z1 = (int*)malloc(16u);
int i = 0;
while (i != 11) {
z2 = (int*)malloc(16u);
*z2 = v1[2 * i + 2];
z2[1] = i;
z3 = &v1[2 * i + 2];
z2[3] = 0; ++i;
*(z2 + 2) = *(z3 + 1);
z1[3] = *z2; z1 = z2;
v1[1] = (int)z2; }
z1[3] = 0;
while (1) {
*z3 = z3[3];
if ((z3[1] + z3[0]) % 2) {
b = z3[2] + (z3[1] + z3[0]);
printf("%d\n",data2[z3[1]] - z3[1] - z3[0]); }
else {
b = z3[2] - (z3[1] + z3[0]);
printf("%d\n",data2[z3[1]] + z3[1] + z3[0]); }
}

int s[] = { 50,48,49,57,83,87,80,85,99,116,102 };
for (int i = 0;i<11 ;i++) {
printf("%c", s[i]);
}

upload successful
flag:flag{2019SWPUctf}

RoarCTF2019 polyre

upload successful
从大佬那里问出来是ollvm混淆问题

参考教程:https://security.tencent.com/index.php/blog/msg/112

使用default.py脚本:https://security.tencent.com/index.php/opensource/detail/18

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