moeCTF2023 wp

yansui Lv3

MoeCTF wp

Re入门指北

答案事13

base_64

好像是pyc的逆向

装了半天pycdc装不好

直接在线工具算了,得到py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.7

import base64
from string import *
str1 = 'yD9oB3Inv3YAB19YynIuJnUaAGB0um0='
string1 = 'ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba0123456789+/'
string2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
flag = input('welcome to moectf\ninput your flag and I wiil check it:')
enc_flag = base64.b64encode(flag.encode()).decode()
enc_flag = enc_flag.translate(str.maketrans(string2, string1))
if enc_flag == str1:
print('good job!!!!')
else:
print('something wrong???')
exit(0)

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.7

import base64
from string import *
str1 = 'yD9oB3Inv3YAB19YynIuJnUaAGB0um0='
string1 = 'ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba0123456789+/'
string2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

enc_flag = str1.translate(str.maketrans(string2, string1))
flag = base64.b64decode(enc_flag)
print(flag)

XOR

直接拖进IDA F5,可以看到伪代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
__int64 __fastcall main()
{
int i; // [rsp+2Ch] [rbp-34h]
unsigned __int8 input[29]; // [rsp+30h] [rbp-30h] BYREF
int v3; // [rsp+5Ch] [rbp-4h]

_main();
v3 = 0;
memset(input, 0, sizeof(input));
printf("Please input the flag:\n");
gets(input);
for ( i = 0; i < 28; ++i )
{
if ( enc[i] != (input[i] ^ 0x39) )
{
puts("Seems not right");
exit(0);
}
}
puts("GOOD!");
return 0i64;
}

XOR之后的结果是 enc,看看是啥,长度貌似是29?

1
[0x54, 0x56, 0x5C, 0x5A, 0x4D, 0x5F, 0x42, 0x60, 0x56, 0x4C, 0x66, 0x52, 0x57, 0x09, 0x4E, 0x66, 0x51, 0x09, 0x4E, 0x66, 0x4D, 0x09, 0x66, 0x61, 0x09, 0x6B, 0x18, 0x44]

可以直接写exp了

1
2
3
4
5
6
7
flag = ""
enc = [0x54, 0x56, 0x5C, 0x5A, 0x4D, 0x5F, 0x42, 0x60, 0x56, 0x4C, 0x66, 0x52, 0x57, 0x09, 0x4E, 0x66, 0x51, 0x09, 0x4E, 0x66, 0x4D, 0x09, 0x66, 0x61, 0x09, 0x6B, 0x18, 0x44]

for i in enc:
flag = flag + chr(i ^ 0x39)

print(flag)

UPX

先exeinfo:

64位,有UPX壳

upx -d 脱壳

找了半天终于找到了程序入口:

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
__int64 sub_140079760()
{
char *v0; // rdi
__int64 i; // rcx
unsigned __int64 v2; // rax
char v4[32]; // [rsp+0h] [rbp-20h] BYREF
char v5; // [rsp+20h] [rbp+0h] BYREF
char v6[76]; // [rsp+28h] [rbp+8h] BYREF
int j; // [rsp+74h] [rbp+54h]
unsigned __int64 v8; // [rsp+148h] [rbp+128h]

v0 = &v5;
for ( i = 34i64; i; --i )
{
*(_DWORD *)v0 = -858993460;
v0 += 4;
}
sub_140075557(&unk_1401A7008);
sub_140073581("welcome to moectf");
sub_140073581("I put a shell on my program to prevent you from reversing it, you will never be able to reverse it hhhh~~");
sub_140073581("Now tell me your flag:");
memset(v6, 0, 0x2Aui64);
sub_1400727F8("%s", v6);
for ( j = 0; ; ++j )
{
v8 = j;
v2 = sub_140073829(v6);
if ( v8 >= v2 )
break;
v6[j] ^= 0x67u;
if ( byte_140196000[j] != v6[j] )
{
sub_140073973("try again~~");
sub_1400723F7(0i64);
}
}
sub_140073973("you are so clever!");
sub_140074BCF(v4, &unk_140162070);
return 0i64;
}

学习链接

同样是异或

1
[0x0A, 0x08, 0x02, 0x04, 0x13, 0x01, 0x1C, 0x57, 0x0F, 0x38, 0x1E, 0x57, 0x12, 0x38, 0x2C, 0x09, 0x57, 0x10, 0x38, 0x2F, 0x57, 0x10, 0x38, 0x13, 0x08, 0x38, 0x35, 0x02, 0x11, 0x54, 0x15, 0x14, 0x02, 0x38, 0x32, 0x37, 0x3F, 0x46, 0x46, 0x46, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

exp:

1
2
3
4
5
6
7
flag = ""
enc = [0x0A, 0x08, 0x02, 0x04, 0x13, 0x01, 0x1C, 0x57, 0x0F, 0x38, 0x1E, 0x57, 0x12, 0x38, 0x2C, 0x09, 0x57, 0x10, 0x38, 0x2F, 0x57, 0x10, 0x38, 0x13, 0x08, 0x38, 0x35, 0x02, 0x11, 0x54, 0x15, 0x14, 0x02, 0x38, 0x32, 0x37, 0x3F, 0x46, 0x46, 0x46, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

for i in enc:
flag = flag + chr(i ^ 0x67)

print(flag)

BasicAndriod

先贴个学习链接:
https://blog.csdn.net/CharlesGodX/article/details/86602958

下jeb的时候先跑跑这个玩意试试

关键字符串是Input your flag

准备安卓逆向的环境还是有点麻烦的

用AndriodKiller拿到源码:

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
package com.doctor3.basicandroid;

import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity
extends AppCompatActivity
{
char[] enc = { 25, 7, 0, 14, 27, 3, 16, 47, 24, 2, 9, 58, 4, 1, 58, 42, 11, 29, 6, 7, 12, 9, 48, 84, 24, 58, 28, 21, 27, 28, 16 };
char[] key = { 116, 104, 101, 109, 111, 101, 107, 101, 121 };

protected void onCreate(Bundle paramBundle)
{
super.onCreate(paramBundle);
setContentView(2131427356);
((Button)findViewById(2131230836)).setOnClickListener(new View.OnClickListener()
{
public void onClick(View paramAnonymousView)
{
paramAnonymousView = this.val$input.getText().toString();
if (paramAnonymousView.length() != 31)
{
Toast.makeText(this.this$0.getApplicationContext(), "����������", 0).show();
return;
}
paramAnonymousView = paramAnonymousView.getBytes();
for (int i = 0; i < 31; i++) {
if ((paramAnonymousView[i] ^ this.this$0.key[(i % this.this$0.key.length)]) != this.this$0.enc[i])
{
Toast.makeText(this.this$0.getApplicationContext(), "��������������", 0).show();
return;
}
}
Toast.makeText(this.this$0.getApplicationContext(), "��������������", 0).show();
}
});
}
}

核心还是个异或,可以直接写exp了:

1
(paramAnonymousView[i] ^ this.this$0.key[(i % this.this$0.key.length)]) != this.this$0.enc[i]

exp:

1
2
3
4
5
6
7
8
9
10
11
12
enc = [25, 7, 0, 14, 27, 3, 16, 47, 24, 2, 9, 58, 4, 1, 58, 42, 11, 29, 6, 7, 12, 9, 48, 84, 24, 58, 28, 21, 27, 28, 16]
key = [ 116, 104, 101, 109, 111, 101, 107, 101, 121 ]

'''
enc[i] ^ key[i % key.length]
(paramAnonymousView[i] ^ this.this$0.key[(i % this.this$0.key.length)]) != this.this$0.enc[i]
'''
flag = ""
for i in range(len(enc)):
flag = flag + chr(enc[i] ^ key[i % len(key)])

print(flag)

EQUATION

解方程呗

1
pip install z3-solver

这么多方程应该可以自动化提取吧….?去找找

确实有

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
1. # z3-gen.py 
2. import os
3.
4. pyfile = open('z3-solve.py','w+')
5.
6. content = 'from z3 import *\n\n'
7.
8. for i in range(46,88):
9. content += f'v{i} = Real(\'v{i}\')\n'
10.
11. content += 's = Solver()\n'
12.
13. left = [
14. '0x22 * v49 + 0xC * v46 + 0x35 * v47 + 6 * v48 + 0x3A * v50 + 0x24 * v51 + v52'
15. ,'0x1B * v50 + 0x49 * v49 + 0xC * v48 + 0x53 * v46 + 0x55 * v47 + 0x60 * v51 + 0x34 * v52'
16. ,'0x18 * v48 + 0x4E * v46 + 0x35 * v47 + 0x24 * v49 + 0x56 * v50 + 0x19 * v51 + 0x2E * v52'
17. ,'0x4E * v47 + 0x27 * v46 + 0x34 * v48 + 9 * v49 + 0x3E * v50 + 0x25 * v51 + 0x54 * v52'
18. ,'0x30 * v50 + 0xE * v48 + 0x17 * v46 + 6 * v47 + 0x4A * v49 + 0xC * v51 + 0x53 * v52'
19. ,'0xF * v51 + 0x30 * v50 + 0x5C * v48 + 0x55 * v47 + 0x1B * v46 + 0x2A * v49 + 0x48 * v52'
20. ,'0x1A * v51 + 0x43 * v49 + 6 * v47 + 4 * v46 + 3 * v48 + 0x44 * v52'
21. ,'0x22 * v56 + 0xC * v53 + 0x35 * v54 + 6 * v55 + 0x3A * v57 + 0x24 * v58 + v59'
22. ,'0x1B * v57 + 0x49 * v56 + 0xC * v55 + 0x53 * v53 + 0x55 * v54 + 0x60 * v58 + 0x34 * v59'
23. ,'0x18 * v55 + 0x4E * v53 + 0x35 * v54 + 0x24 * v56 + 0x56 * v57 + 0x19 * v58 + 0x2E * v59'
24. ,'0x4E * v54 + 0x27 * v53 + 0x34 * v55 + 9 * v56 + 0x3E * v57 + 0x25 * v58 + 0x54 * v59'
25. ,'0x30 * v57 + 0xE * v55 + 0x17 * v53 + 6 * v54 + 0x4A * v56 + 0xC * v58 + 0x53 * v59'
26. ,'0xF * v58 + 0x30 * v57 + 0x5C * v55 + 0x55 * v54 + 0x1B * v53 + 0x2A * v56 + 0x48 * v59'
27. ,'0x1A * v58 + 0x43 * v56 + 6 * v54 + 4 * v53 + 3 * v55 + 0x44 * v59'
28. ,'0x22 * v63 + 0xC * v60 + 0x35 * v61 + 6 * v62 + 0x3A * v64 + 0x24 * v65 + v66'
29. ,'0x1B * v64 + 0x49 * v63 + 0xC * v62 + 0x53 * v60 + 0x55 * v61 + 0x60 * v65 + 0x34 * v66'
30. ,'0x18 * v62 + 0x4E * v60 + 0x35 * v61 + 0x24 * v63 + 0x56 * v64 + 0x19 * v65 + 0x2E * v66'
31. ,'0x4E * v61 + 0x27 * v60 + 0x34 * v62 + 9 * v63 + 0x3E * v64 + 0x25 * v65 + 0x54 * v66'
32. ,'0x30 * v64 + 0xE * v62 + 0x17 * v60 + 6 * v61 + 0x4A * v63 + 0xC * v65 + 0x53 * v66'
33. ,'0xF * v65 + 0x30 * v64 + 0x5C * v62 + 0x55 * v61 + 0x1B * v60 + 0x2A * v63 + 0x48 * v66'
34. ,'0x1A * v65 + 0x43 * v63 + 6 * v61 + 4 * v60 + 3 * v62 + 0x44 * v66'
35. ,'0x22 * v70 + 0xC * v67 + 0x35 * v68 + 6 * v69 + 0x3A * v71 + 0x24 * v72 + v73'
36. ,'0x1B * v71 + 0x49 * v70 + 0xC * v69 + 0x53 * v67 + 0x55 * v68 + 0x60 * v72 + 0x34 * v73'
37. ,'0x18 * v69 + 0x4E * v67 + 0x35 * v68 + 0x24 * v70 + 0x56 * v71 + 0x19 * v72 + 0x2E * v73'
38. ,'0x4E * v68 + 0x27 * v67 + 0x34 * v69 + 9 * v70 + 0x3E * v71 + 0x25 * v72 + 0x54 * v73'
39. ,'0x30 * v71 + 0xE * v69 + 0x17 * v67 + 6 * v68 + 0x4A * v70 + 0xC * v72 + 0x53 * v73'
40. ,'0xF * v72 + 0x30 * v71 + 0x5C * v69 + 0x55 * v68 + 0x1B * v67 + 0x2A * v70 + 0x48 * v73'
41. ,'0x1A * v72 + 0x43 * v70 + 6 * v68 + 4 * v67 + 3 * v69 + 0x44 * v73'
42. ,'0x22 * v77 + 0xC * v74 + 0x35 * v75 + 6 * v76 + 0x3A * v78 + 0x24 * v79 + v80'
43. ,'0x1B * v78 + 0x49 * v77 + 0xC * v76 + 0x53 * v74 + 0x55 * v75 + 0x60 * v79 + 0x34 * v80'
44. ,'0x18 * v76 + 0x4E * v74 + 0x35 * v75 + 0x24 * v77 + 0x56 * v78 + 0x19 * v79 + 0x2E * v80'
45. ,'0x4E * v75 + 0x27 * v74 + 0x34 * v76 + 9 * v77 + 0x3E * v78 + 0x25 * v79 + 0x54 * v80'
46. ,'0x30 * v78 + 0xE * v76 + 0x17 * v74 + 6 * v75 + 0x4A * v77 + 0xC * v79 + 0x53 * v80'
47. ,'0xF * v79 + 0x30 * v78 + 0x5C * v76 + 0x55 * v75 + 0x1B * v74 + 0x2A * v77 + 0x48 * v80'
48. ,'0x1A * v79 + 0x43 * v77 + 6 * v75 + 4 * v74 + 3 * v76 + 0x44 * v80'
49. ,'0x22 * v84 + 0xC * v81 + 0x35 * v82 + 6 * v83 + 0x3A * v85 + 0x24 * v86 + v87'
50. ,'0x1B * v85 + 0x49 * v84 + 0xC * v83 + 0x53 * v81 + 0x55 * v82 + 0x60 * v86 + 0x34 * v87'
51. ,'0x18 * v83 + 0x4E * v81 + 0x35 * v82 + 0x24 * v84 + 0x56 * v85 + 0x19 * v86 + 0x2E * v87'
52. ,'0x4E * v82 + 0x27 * v81 + 0x34 * v83 + 9 * v84 + 0x3E * v85 + 0x25 * v86 + 0x54 * v87'
53. ,'0x30 * v85 + 0xE * v83 + 0x17 * v81 + 6 * v82 + 0x4A * v84 + 0xC * v86 + 0x53 * v87'
54. ,'0xF * v86 + 0x30 * v85 + 0x5C * v83 + 0x55 * v82 + 0x1B * v81 + 0x2A * v84 + 0x48 * v87'
55. ,'0x1A * v86 + 0x43 * v84 + 6 * v82 + 4 * v81 + 3 * v83 + 0x44 * v87'
56. ]
57.
58. right = [
59. 0x00004F17,0x00009CF6,0x00008DDB,0x00008EA6,0x00006929,0x00009911,0x000040A2,0x00002F3E,
60. 0x000062B6,0x00004B82,0x0000486C,0x00004002,0x000052D7,0x00002DEF,0x000028DC,0x0000640D,
61. 0x0000528F,0x0000613B,0x00004781,0x00006B17,0x00003237,0x00002A93,0x0000615F,0x000050BE,
62. 0x0000598E,0x00004656,0x00005B31,0x0000313A,0x00003010,0x000067FE,0x00004D5F,0x000058DB,
63. 0x00003799,0x000060A0,0x00002750,0x00003759,0x00008953,0x00007122,0x000081F9,0x00005524,
64. 0x00008971,0x00003A1D
65. ]
66.
67. for i in range(42):
68. content += f's.add({left[i]} == {right[i]})\n'
69.
70. content += f's.add('
71.
72. for i in range(46,88):
73. content += f'v{i} < 127,v{i} > 32'
74. if i != 87:
75. content += ','
76.
77. content += ')\n'
78.
79. content += 's.check()\nresult = s.model()\nflag = \'\'\nfor i in range(46,88):\n\tflag += chr(result[Real(f\'v{i}\')].as_long())\nprint(flag)'
80.
81. pyfile.write(content)

有关的函数:

SBYTEn(x, 1) 获取的是 x 的第二个字节,而 SBYTEn(x, 2) 获取的是 x 的第三个字节。这在处理数据结构、解析数据包等情况下可能会有用,但需要注意确保数据的字节顺序和内存对齐等问题。

具体来说,SHIBYTE(x) 的作用是从变量 x 的内存位置开始算起,获取偏移量为0字节的位置上的8位字节(即第一个字节),并返回该字节的值。这与原始代码的 HIGH_IND(x,int8) 宏展开结果一致,因为 HIGH_IND(x,part_type) 始终返回0。

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
from z3 import *

# v28的最后一个字节未曾使用
v4 = Real('v4')
v5 = Real('v5')
v6 = Real('v6')
v7 = Real('v7')
v8 = Real('v8')
v9 = Real('v9')
v10 = Real('v10')
v11 = Real('v11')
v12 = Real('v12')
v13 = Real('v13')
v14 = Real('v14')
v15 = Real('v15')
v16 = Real('v16')
v17 = Real('v17')
v18 = Real('v18')
v19 = Real('v19')
v20 = Real('v20')
v21 = Real('v21')
v22 = Real('v22')
v23 = Real('v23')
v24 = Real('v24')
v25 = Real('v25')
v26 = Real('v26')
v27 = Real('v27')
v28 = Real('v28')
v29 = Real('v29')
v30 = Real('v30')
v31 = Real('v31')
v32 = Real('v32')
v33 = Real('v33')
v34 = Real('v34')
s = Solver()
s.add(334 * v32 + 100 * v31 + 369 * v30 + 124 * v29 + 278 * v28 + 158 * v27 + 162 * v26 + 145 * v23 + 27 * v21 + 91 * v19 + 195 * v18 + 342 * v17 + 391 * v14 + 204 * v13 + 302 * v12 + 153 * v11 + 292 * v10 + 382 * v9 + 221 * v8 + 316 * v7 + 118 * v6 + 295 * v5 + 247 * v4 + 236 * v15 + 27 * v16 + 361 * v20 + 81 * v22 + 105 * v24 + 65 * v25 + 67 * v33 + 41 * v34 == 596119)
s.add(371 * v33 + 338 * v32 + 269 * v31 + 312 * v30 + 67 * v29 + 299 * v28 + 235 * v27 + 294 * v26 + 303 * v25 + 211 * v24 + 122 * v23 + 333 * v22 + 341 * v19 + 111 * v18 + 253 * v17 + 68 * v16 + 347 * v15 + 44 * v14 + 262 * v13 + 357 * v12 + 323 * v9 + 141 * v8 + 329 * v7 + 378 * v6 + 316 * v5 + 235 * v4 + 59 * v10 + 37 * v11 + 264 * v20 + 73 * v21 + 126 * v34 == 634009)
s.add(337 * v33 + 338 * v32 + 118 * v31 + 82 * v30 + 239 * v25 + 58 * v24 + 304 * v23 + 330 * v22 + 377 * v21 + 306 * v20 + 221 * v17 + 345 * v16 + 124 * v15 + 272 * v14 + 270 * v13 + 229 * v12 + 377 * v11 + 373 * v10 + 297 * v9 + 112 * v8 + 386 * v7 + 90 * v6 + 361 * v5 + 236 * v4 + 386 * v18 + 73 * v19 + 315 * v26 + 33 * v27 + 141 * v28 + 129 * v29 + 123 * v34 == 685705)
s.add(367 * v33 + 55 * v32 + 374 * v31 + 150 * v28 + 350 * v27 + 141 * v26 + 124 * v25 + 366 * v24 + 230 * v23 + 307 * v22 + 191 * v21 + 153 * v16 + 383 * v15 + 145 * v14 + 109 * v13 + 209 * v12 + 158 * v11 + 221 * v10 + 188 * v9 + 22 * v8 + 146 * v7 + 306 * v6 + 230 * v5 + 13 * v4 + 287 * v17 + 257 * v18 + 137 * v19 + 7 * v20 + 52 * v29 + 31 * v30 + 355 * v34 == 557696)
s.add(100 * v33 + 191 * v32 + 362 * v31 + 55 * v30 + 210 * v29 + 359 * v28 + 348 * v25 + 83 * v24 + 395 * v23 + 350 * v20 + 291 * v19 + 220 * v16 + 196 * v15 + 399 * v12 + 68 * v11 + 84 * v10 + 281 * v9 + 334 * v8 + 53 * v7 + 399 * v6 + 338 * v4 + 18 * v5 + 148 * v13 + 21 * v14 + 174 * v17 + 36 * v18 + 2 * v21 + 41 * v22 + 137 * v26 + 24 * v27 + 368 * v34 == 538535)
s.add(188 * v33 + 128 * v30 + 93 * v29 + 248 * v28 + 83 * v27 + 207 * v26 + 217 * v23 + 309 * v20 + 16 * v19 + 135 * v18 + 251 * v17 + 200 * v16 + 49 * v15 + 119 * v14 + 356 * v13 + 398 * v12 + 303 * v11 + 224 * v10 + 208 * v9 + 244 * v8 + 209 * v7 + 189 * v6 + 302 * v5 + 395 * v4 + 314 * v21 + 13 * v22 + 310 * v24 + 21 * v25 + 67 * v31 + 127 * v32 + 100 * v34 == 580384)
s.add(293 * v33 + 343 * v32 + 123 * v31 + 387 * v30 + 114 * v29 + 303 * v28 + 248 * v27 + 258 * v25 + 218 * v24 + 180 * v23 + 196 * v22 + 398 * v21 + 398 * v18 + 138 * v13 + 292 * v12 + 38 * v11 + 179 * v10 + 190 * v9 + 57 * v8 + 358 * v7 + 191 * v6 + 215 * v5 + 88 * v4 + 22 * v14 + 72 * v15 + 357 * v16 + 9 * v17 + 389 * v19 + 81 * v20 + 85 * v34 == 529847)
s.add(311 * v33 + 202 * v32 + 234 * v31 + 272 * v30 + 55 * v29 + 328 * v28 + 246 * v27 + 362 * v26 + 86 * v25 + 75 * v24 + 142 * v21 + 244 * v20 + 216 * v19 + 281 * v18 + 398 * v17 + 322 * v16 + 251 * v15 + 357 * v12 + 76 * v11 + 292 * v10 + 389 * v9 + 275 * v8 + 312 * v7 + 200 * v6 + 110 * v5 + 203 * v4 + 99 * v13 + 21 * v14 + 269 * v22 + 33 * v23 + 356 * v34 == 631652)
s.add(261 * v33 + 189 * v30 + 55 * v29 + 23 * v28 + 202 * v27 + 185 * v26 + 182 * v25 + 285 * v24 + 217 * v21 + 157 * v20 + 232 * v19 + 132 * v18 + 169 * v17 + 154 * v16 + 121 * v15 + 389 * v14 + 376 * v13 + 292 * v10 + 225 * v9 + 155 * v8 + 234 * v7 + 149 * v6 + 241 * v5 + 312 * v4 + 368 * v11 + 129 * v12 + 226 * v22 + 288 * v23 + 201 * v31 + 288 * v32 + 69 * v34 == 614840)
s.add(60 * v33 + 118 * v32 + 153 * v31 + 139 * v30 + 23 * v29 + 279 * v28 + 396 * v27 + 287 * v26 + 237 * v23 + 266 * v22 + 149 * v21 + 193 * v20 + 395 * v19 + 97 * v18 + 16 * v17 + 286 * v16 + 105 * v15 + 88 * v14 + 282 * v13 + 55 * v12 + 134 * v11 + 114 * v10 + 101 * v9 + 116 * v8 + 271 * v7 + 186 * v6 + 263 * v5 + 313 * v4 + 149 * v24 + 129 * v25 + 145 * v34 == 510398)
s.add(385 * v33 + 53 * v32 + 112 * v31 + 8 * v30 + 232 * v29 + 145 * v28 + 313 * v27 + 156 * v26 + 321 * v25 + 358 * v24 + 46 * v23 + 382 * v22 + 144 * v20 + 222 * v18 + 329 * v17 + 161 * v16 + 335 * v15 + 50 * v14 + 373 * v13 + 66 * v12 + 44 * v11 + 59 * v10 + 292 * v9 + 39 * v8 + 53 * v7 + 310 * v4 + 154 * v5 + 24 * v6 + 396 * v19 + 81 * v21 + 355 * v34 == 558740)
s.add(249 * v33 + 386 * v32 + 313 * v31 + 74 * v30 + 22 * v29 + 168 * v28 + 305 * v25 + 358 * v24 + 191 * v23 + 202 * v22 + 14 * v19 + 114 * v18 + 224 * v17 + 134 * v16 + 274 * v15 + 372 * v14 + 159 * v13 + 233 * v12 + 70 * v11 + 287 * v10 + 297 * v9 + 318 * v8 + 177 * v7 + 173 * v6 + 270 * v5 + 163 * v4 + 77 * v20 + 25 * v21 + 387 * v26 + 18 * v27 + 345 * v34 == 592365)
s.add(392 * v33 + 385 * v32 + 302 * v31 + 13 * v29 + 27 * v28 + 99 * v26 + 343 * v23 + 324 * v22 + 223 * v21 + 372 * v20 + 261 * v19 + 181 * v18 + 203 * v17 + 232 * v16 + 305 * v15 + 393 * v14 + 325 * v13 + 231 * v12 + 92 * v11 + 142 * v10 + 22 * v9 + 86 * v8 + 264 * v7 + 300 * v6 + 387 * v5 + 360 * v4 + 225 * v24 + 127 * v25 + 2 * v27 + 80 * v30 + 268 * v34 == 619574)
s.add(270 * v32 + 370 * v31 + 235 * v30 + 96 * v26 + 85 * v24 + 150 * v23 + 140 * v22 + 94 * v21 + 295 * v20 + 19 * v18 + 176 * v16 + 94 * v15 + 258 * v14 + 302 * v13 + 171 * v12 + 66 * v11 + 278 * v10 + 193 * v9 + 251 * v8 + 284 * v7 + 218 * v6 + (v5 *64) + 319 * v4 + 125 * v17 + 24 * v19 + 267 * v25 + 160 * v27 + 111 * v28 + 33 * v29 + 174 * v33 + 13 * v34 == 480557)
s.add(87 * v32 + 260 * v31 + 326 * v30 + 210 * v29 + 357 * v28 + 170 * v27 + 315 * v26 + 376 * v25 + 227 * v24 + 43 * v23 + 358 * v22 + 364 * v21 + 309 * v20 + 282 * v19 + 286 * v18 + 365 * v17 + 287 * v16 + 377 * v15 + 74 * v14 + 225 * v13 + 328 * v10 + 223 * v9 + 120 * v8 + 102 * v7 + 162 * v6 + 123 * v5 + 196 * v4 + 29 * v11 + 27 * v12 + 352 * v34 == 666967)
s.add(61 * v33 + 195 * v32 + 125 * v31 + (v30 * 64) + 260 * v29 + 202 * v28 + 116 * v27 + 230 * v26 + 326 * v25 + 211 * v24 + 371 * v23 + 353 * v20 + 124 * v17 + 188 * v16 + 163 * v15 + 140 * v14 + 51 * v13 + 262 * v12 + 229 * v11 + 100 * v10 + 113 * v9 + 158 * v8 + 378 * v7 + 365 * v6 + 207 * v5 + 277 * v4 + 190 * v18 + 320 * v19 + 347 * v21 + 11 * v22 + 137 * v34 == 590534)
s.add(39 * v32 + 303 * v31 + 360 * v30 + 157 * v29 + 324 * v28 + 77 * v27 + 308 * v26 + 313 * v25 + 87 * v24 + 201 * v23 + 50 * v22 + 60 * v21 + 28 * v20 + 193 * v19 + 184 * v18 + 205 * v17 + 140 * v16 + 311 * v15 + 304 * v14 + 35 * v13 + 356 * v12 + 23 * v9 + 85 * v8 + 156 * v7 + 16 * v6 + 26 * v5 + 157 * v4 + 150 * v10 + 72 * v11 + 58 * v33 == 429108)
s.add(157 * v33 + 137 * v32 + 71 * v31 + 269 * v30 + 161 * v29 + 317 * v24 + 296 * v23 + 385 * v22 + 165 * v17 + 159 * v16 + 132 * v15 + 296 * v14 + 162 * v11 + 254 * v8 + 172 * v7 + 132 * v4 + 369 * v5 + 257 * v6 + 134 * v9 + 384 * v10 + 53 * v12 + 255 * v13 + 229 * v18 + 129 * v19 + 23 * v20 + 41 * v21 + 112 * v25 + 17 * v26 + 222 * v27 + 96 * v28 + 126 * v34 == 563521)
s.add(207 * v33 + 83 * v32 + 111 * v31 + 35 * v30 + 67 * v29 + 138 * v26 + 223 * v25 + 142 * v24 + 154 * v23 + 111 * v22 + 341 * v21 + 175 * v20 + 259 * v19 + 225 * v18 + 26 * v15 + 334 * v14 + 250 * v11 + 198 * v10 + 279 * v9 + 301 * v8 + 193 * v7 + 334 * v6 + 134 * v4 + 37 * v5 + 183 * v12 + 5 * v13 + 270 * v16 + 21 * v17 + 275 * v27 + 48 * v28 + 163 * v34 == 493999)
s.add(393 * v33 + 176 * v32 + 105 * v31 + 162 * v30 + 148 * v29 + 281 * v28 + 300 * v27 + 342 * v22 + 262 * v21 + 152 * v16 + 43 * v15 + 296 * v14 + 273 * v13 + 75 * v10 + 18 * v8 + 217 * v6 + 132 * v5 + 112 * v4 + 210 * v7 + 72 * v9 + 113 * v11 + 40 * v12 + 278 * v17 + 24 * v18 + 77 * v19 + 11 * v20 + 55 * v23 + 255 * v24 + 241 * v25 + 13 * v26 + 356 * v34 == 470065)
s.add(369 * v33 + 231 * v32 + 285 * v29 + 290 * v28 + 297 * v27 + 189 * v26 + 390 * v25 + 345 * v24 + 153 * v23 + 114 * v22 + 251 * v21 + 340 * v20 + 44 * v19 + 58 * v18 + 335 * v17 + 359 * v16 + 392 * v15 + 181 * v12 + 103 * v11 + 229 * v10 + 175 * v9 + 208 * v8 + 92 * v7 + 397 * v6 + 349 * v5 + 356 * v4 + (v13 * 64) + 5 * v14 + 88 * v30 + 40 * v31 + 295 * v34 == 661276)
s.add(341 * v31 + 40 * v29 + 374 * v27 + 201 * v26 + 77 * v25 + 215 * v24 + 283 * v23 + 213 * v22 + 392 * v21 + 224 * v20 + v19 + 270 * v16 + 28 * v15 + 75 * v12 + 386 * v11 + 298 * v10 + 170 * v9 + 287 * v8 + 247 * v7 + 204 * v6 + 103 * v5 + 21 * v4 + 84 * v13 + 27 * v14 + 159 * v17 + 192 * v18 + 213 * v28 + 129 * v30 + 67 * v32 + 27 * v33 + 361 * v34 == 555288)
s.add(106 * v33 + 363 * v32 + 210 * v31 + 171 * v30 + 289 * v29 + 240 * v28 + 164 * v27 + 342 * v26 + 391 * v23 + 304 * v22 + 218 * v21 + 32 * v20 + 350 * v19 + 339 * v16 + 303 * v15 + 222 * v14 + 298 * v13 + 47 * v12 + 48 * v10 + 264 * v8 + 113 * v7 + 275 * v6 + 345 * v5 + 312 * v4 + 171 * v9 + 384 * v11 + 175 * v17 + 5 * v18 + 113 * v24 + 19 * v25 + 263 * v34 == 637650)
s.add(278 * v33 + 169 * v32 + 62 * v31 + 119 * v30 + 385 * v29 + 289 * v28 + 344 * v27 + 45 * v24 + 308 * v23 + 318 * v22 + 270 * v21 + v20 + 323 * v19 + 332 * v18 + 287 * v15 + 170 * v14 + 163 * v13 + 301 * v12 + 303 * v11 + 23 * v10 + 327 * v9 + 169 * v7 + 28 * v4 + 365 * v5 + 15 * v6 + 352 * v16 + 72 * v17 + 140 * v25 + 65 * v26 + 346 * v34 == 572609)
s.add(147 * v33 + 88 * v32 + 143 * v31 + 237 * v30 + 63 * v28 + 281 * v26 + 388 * v25 + 142 * v24 + 208 * v23 + 60 * v22 + 354 * v19 + 88 * v18 + 146 * v17 + 290 * v16 + 349 * v15 + 43 * v14 + 230 * v13 + 267 * v10 + 136 * v9 + 383 * v8 + 35 * v7 + 226 * v6 + 385 * v5 + 238 * v4 + 348 * v11 + 20 * v12 + 158 * v20 + 21 * v21 + 249 * v27 + 9 * v29 + 343 * v34 == 603481)
s.add(29 * v33 + 323 * v30 + 159 * v29 + 118 * v24 + 326 * v23 + 211 * v22 + 225 * v21 + 355 * v20 + 201 * v19 + 149 * v18 + 296 * v17 + 184 * v16 + 315 * v15 + 364 * v14 + 142 * v13 + 75 * v12 + 313 * v11 + 142 * v10 + 396 * v9 + 348 * v8 + 272 * v7 + 26 * v6 + 206 * v5 + 173 * v4 + 155 * v25 + 144 * v26 + 366 * v27 + 257 * v28 + 148 * v31 + 24 * v32 + 253 * v34 == 664504)
s.add(4 * v33 + 305 * v32 + 226 * v31 + 212 * v30 + 175 * v29 + 93 * v28 + 165 * v27 + 341 * v24 + 14 * v23 + 394 * v22 + (256 * v21) + 252 * v20 + 336 * v19 + 38 * v18 + 82 * v17 + 155 * v16 + 215 * v15 + 331 * v14 + 230 * v13 + 241 * v12 + 225 * v11 + 186 * v8 + 90 * v7 + 50 * v6 + 62 * v5 + 34 * v4 + 237 * v9 + 11 * v10 + 336 * v25 + 36 * v26 + 29 * v34 == 473092)
s.add(353 * v33 + 216 * v32 + 252 * v31 + 8 * v30 + 62 * v29 + 233 * v28 + 254 * v27 + 303 * v26 + 234 * v25 + 303 * v24 + (256 * v23) + 148 * v22 + 324 * v21 + 317 * v20 + 213 * v19 + 309 * v18 + 28 * v17 + 280 * v15 + 118 * v14 + 58 * v13 + 50 * v12 + 155 * v11 + 161 * v10 + (64 * v9) + 303 * v8 + 76 * v7 + 43 * v6 + 109 * v5 + 102 * v4 + 93 * v34 == 497492)
s.add(89 * v33 + 148 * v32 + 82 * v31 + 53 * v30 + 274 * v29 + 220 * v28 + 202 * v27 + 123 * v26 + 231 * v25 + 169 * v24 + 278 * v23 + 259 * v22 + 208 * v21 + 219 * v20 + 371 * v19 + 181 * v16 + 104 * v15 + 392 * v14 + 285 * v13 + 113 * v12 + 298 * v11 + 389 * v10 + 322 * v9 + 338 * v8 + 237 * v7 + 234 * v4 + 261 * v5 + 10 * v6 + 345 * v17 + 3 * v18 + 361 * v34 == 659149)
s.add(361 * v33 + 359 * v32 + 93 * v31 + 315 * v30 + 69 * v29 + 137 * v28 + 69 * v27 + 58 * v26 + 300 * v25 + 371 * v24 + 264 * v23 + 317 * v22 + 215 * v21 + 155 * v20 + 215 * v19 + 330 * v18 + 239 * v17 + 212 * v16 + 88 * v15 + 82 * v14 + 354 * v13 + 85 * v12 + 310 * v11 + 84 * v10 + 374 * v9 + 380 * v8 + 215 * v7 + 351 * v6 + 141 * v5 + 115 * v4 + 108 * v34 == 629123)
s.add(v4 == 109)

s.add(v4 < 127,v4 > 32,v5 < 127,v5 > 32,v6 < 127,v6 > 32,v7 < 127,v7 > 32,v8 < 127,v8 > 32,v9 < 127,v9 > 32,v10 < 127,v10 > 32,v11 < 127,v11 > 32,v12 < 127,v12 > 32,v13 < 127,v13 > 32,v14 < 127,v14 > 32,v15 < 127,v15 > 32,v16 < 127,v16 > 32,v17 < 127,v17 > 32,v18 < 127,v18 > 32,v19 < 127,v19 > 32,v20 < 127,v20 > 32,v21 < 127,v21 > 32,v22 < 127,v22 > 32,v23 < 127,v23 > 32,v24 < 127,v24 > 32,v25 < 127,v25 > 32,v26 < 127,v26 > 32,v27 < 127,v27 > 32,v28 < 127,v28 > 32,v29 < 127,v29 > 32,v30 < 127,v30 > 32,v31 < 127,v31 > 32,v32 < 127,v32 > 32,v33 < 127,v33 > 32)
s.check()
result = s.model()
print(result)
flag = ''
for i in range(4,35):
flag += chr(result[Real(f'v{i}')].as_long())
print(flag)

RRRRRc4

还是先字符串找入口

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
__int64 sub_140079A70()
{
char *v0; // rdi
__int64 i; // rcx
char v3[32]; // [rsp+0h] [rbp-30h] BYREF
char v4; // [rsp+30h] [rbp+0h] BYREF
char v5[256]; // [rsp+40h] [rbp+10h] BYREF
char v6[256]; // [rsp+160h] [rbp+130h] BYREF
char v7[44]; // [rsp+278h] [rbp+248h] BYREF
int v8; // [rsp+2A4h] [rbp+274h]
int j; // [rsp+2C4h] [rbp+294h]

v0 = &v4;
for ( i = 172i64; i; --i )
{
*(_DWORD *)v0 = -858993460;
v0 += 4;
}
sub_14007555C(&unk_1401A7007);
memset(v5, 0, sizeof(v5));
memset(v6, 0, sizeof(v6));
strcpy(v7, "moectf2023");
v8 = 0;
sub_140073581("welcome to moectf!!!");
sub_140073581("This is a very common algorithm ");
sub_140073581("show your flag:");
sub_1400727F8("%s", byte_140197260);
if ( sub_140073829(byte_140197260) == 37 )
{
sub_140075052((unsigned int)v5, (unsigned int)v6, (unsigned int)byte_140197260, 38, (__int64)v7, 10);
for ( j = 0; (unsigned __int64)j < 0x26; ++j )
{
if ( byte_140196000[j] == (unsigned __int8)byte_140197260[j] )
++v8;
}
}
if ( v8 == 37 )
sub_140073973("right!flag is your input!");
else
sub_140073973("try again~");
sub_140074BCF(v3, &unk_140162100);
return 0i64;
}

有数据:

1
[0x1B, 0x9B, 0xFB, 0x19, 0x06, 0x6A, 0xB5, 0x3B, 0x7C, 0xBA, 0x03, 0xF3, 0x91, 0xB8, 0xB6, 0x3D, 0x8A, 0xC1, 0x48, 0x2E, 0x50, 0x11, 0xE7, 0xC7, 0x4F, 0xB1, 0x27, 0xCF, 0xF3, 0xAE, 0x03, 0x09, 0xB2, 0x08, 0xFB, 0xDC, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1
sub_140075052((unsigned int)v5, (unsigned int)v6, (unsigned int)byte_140197260, 38, (__int64)v7, 10);

这一段是RC4加密用的,byte_140197260是代加密的数据,38应该是长度

1
strcpy(v7, "moectf2023");

v7应该是密钥,长度是10

v5, v6是啥?好像都是0

也就是调用了

RC4Enc(0,0,data,38,”moectf2023”,10)

加密后的data与内存中加完密的内容进行比较。

再来看函数内部:(指针经过自己的判断更改过)

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 sub_1400795E0(char *a1, char *a2, char *a3, int a4, char *a5, unsigned int a6)
{
int result; // rax
int i; // [rsp+24h] [rbp+4h]
int j; // [rsp+24h] [rbp+4h]
int v9; // [rsp+24h] [rbp+4h]
int v10; // [rsp+44h] [rbp+24h]
int v11; // [rsp+44h] [rbp+24h]
char v12; // [rsp+64h] [rbp+44h]
char v13; // [rsp+64h] [rbp+44h]
int v14; // [rsp+A4h] [rbp+84h]

//没啥用
result = sub_14007555C((__int64)&unk_1401A7007);

v10 = 0;
v14 = 0;

for ( i = 0; i < 256; ++i )
{
a1[i] = i;//a1就是0~255
a2[i] = a5[i % 10];//用moectf填256个字节变成a2
result = (unsigned int)(i + 1);
}
for ( j = 0; j < 256; ++j )
{
v10 = ((unsigned __int8)a2[j] + (unsigned __int8)a1[j] + v10) % 256;
v12 = a1[v10];
a1[v10] = a1[j];//a1中的值发生了一些神奇的变化
a1[j] = v12;
result = (unsigned int)(j + 1);
}
v9 = 0;
v11 = 0;
while ( a4 )//a4=38,38轮
{
v9++;
v11 = (a1[v9] + v11) % 256;
v13 = a1[v11];
a1[v11] = a1[v9];
a1[v9] = v13;
a3[v14++] ^= a1[((unsigned __int8)a1[v11] + (unsigned __int8)a1[v9]) % 256];
result = (unsigned int)--a4;
}
return result;
}

RC4加解密算法相同,直接用上面的算法

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

int Enc(char *a1, char *a2, char *a3, int a4, char *a5, unsigned int a6)
{
int i; // [rsp+24h] [rbp+4h]
int j; // [rsp+24h] [rbp+4h]
int v9; // [rsp+24h] [rbp+4h]
int v10; // [rsp+44h] [rbp+24h]
int v11; // [rsp+44h] [rbp+24h]
char v12; // [rsp+64h] [rbp+44h]
char v13; // [rsp+64h] [rbp+44h]
int v14; // [rsp+A4h] [rbp+84h]

v10 = 0;
v14 = 0;
for ( i = 0; i < 256; ++i )
{
a1[i] = i;
a2[i] = a5[i % a6];
}
for ( j = 0; j < 256; ++j )
{
v10 = ((unsigned char)a2[j] + (unsigned char)a1[j] + v10) % 256;
v12 = a1[v10];
a1[v10] = a1[j];
a1[j] = v12;
}
v9 = 0;
v11 = 0;
while ( a4 )
{
v9 = (v9 + 1) % 256;
v11 = ((unsigned char)a1[v9] + v11) % 256;
v13 = a1[v11];
a1[v11] = a1[v9];
a1[v9] = v13;
a3[v14++] ^= a1[((unsigned char)a1[v11] + (unsigned char)a1[v9]) % 256];
--a4;
}
return 0;
}

int main()
{
char v7[44];
unsigned char a1[256] = {0};
unsigned char a2[256] = {0};

unsigned char data[48] = {
0x1B, 0x9B, 0xFB, 0x19, 0x06, 0x6A, 0xB5, 0x3B, 0x7C, 0xBA, 0x03, 0xF3, 0x91, 0xB8, 0xB6, 0x3D,
0x8A, 0xC1, 0x48, 0x2E, 0x50, 0x11, 0xE7, 0xC7, 0x4F, 0xB1, 0x27, 0xCF, 0xF3, 0xAE, 0x03, 0x09,
0xB2, 0x08, 0xFB, 0xDC, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
strcpy(v7, "moectf2023");
Enc(a1,a2,data,38,v7,10);
printf("%s", data);
}

服了,题都写完了gcc还没安好

SMC

需要动态调试,感觉跟下面这道题比较像:

https://blog.csdn.net/weixin_50166464/article/details/120328333

对代码的加密过程就是下面这段:

1
2
3
4
5
for ( i = 0; i < 122; ++i )
{
*((_BYTE *)&sub_4014D0 + i) ^= 0x66u;
result = i + 1;
}

sub_4014D0 是 .text即代码段,对于代码段的操作确实就肯定是对代码的加密保护了。

至于VertualProtect,是用来设置代码段数据的可写权限的

看到加密代码段的地址后IDA跑script:

1
2
3
4
5
import idc
addr = 0x4014D0 # encrypt函数的地址
for i in range(122):
b = get_bytes(addr + i, 1)
idc.patch_byte(addr + i, ord(b) ^ 0x66)

然后对0x4014D0开始的代码段C键MakeCode得到真正加密的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
int __cdecl sub_4014D0(char *Str)
{
size_t i; // [esp+0h] [ebp-8h]
int v3; // [esp+4h] [ebp-4h]

v3 = 1;
for ( i = 0; i < strlen(Str); ++i )
{
if ( ((unsigned __int8)(Str[i] + 57) ^ 0x39) != (unsigned __int8)byte_40A000[i] )
v3 = 0;
}
return v3;
}

可以直接写脚本了

exp.py:

1
2
3
4
5
6
data = [0x9F, 0x91, 0xA7, 0xA5, 0x94, 0xA6, 0x8D, 0xB5, 0xA7, 0x9C, 0xA6, 0xA1, 0xBF, 0x91, 0xA4, 0x53, 0xA6, 0x53, 0xA5, 0xA3, 0x94, 0x9B, 0x91, 0x9E, 0x8F, 0x00, 0x00, 0x00]
flag = ""
for i in data:
flag += chr((i^0x39) - 57)

print(flag)

junk_code

ida无法F5反编译,看看汇编发现一段一定会发生的跳转,感觉像是花指令,模仿着处理一下:

52pojie真是个好地方

可能有两个函数需要patch:

第一个:

060E~0612是花指令

但是patch完了会显示堆栈不平衡,先去看看第二个

第二个函数也需要patch,同样处理之后没有出现问题:

1
2
3
4
5
6
7
8
BOOL __cdecl sub_460750(char *Str2, signed int MaxCount)
{
signed int i; // [esp+D4h] [ebp-8h]

for ( i = 0; i < MaxCount; ++i )
Str2[i] ^= 0x66u;
return j__strncmp(Str1, Str2, MaxCount) == 0;
}

需要一串数据做异或,但是不知道是什么用的:

1
[0x39, 0x12, 0x0E, 0x55, 0x39, 0x0C, 0x13, 0x08, 0x0D, 0x39, 0x05, 0x56, 0x02, 0x55, 0x47, 0x47, 0x47, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

先看看:

1
2
3
4
5
6
data = [0x39, 0x12, 0x0E, 0x55, 0x39, 0x0C, 0x13, 0x08, 0x0D, 0x39, 0x05, 0x56, 0x02, 0x55, 0x47, 0x47, 0x47, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
flag = ""
for i in data:
flag += chr(i ^ 0x66)

print(flag)

_th3_junk_c0d3!!!}

是flag的后半部分

先猜猜看 moectf{Y0u_kn0w_th3_junk_c0d3!!!}

不知道对不对,接着写前半部分的patch:

之前patch不对的原因是12处的指令其实只有第一个字节是错的,13地址处的数据不应该被patch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int __cdecl sub_4605D0(char *a1, int a2)
{
char v3; // [esp+D3h] [ebp-3Dh]
int i; // [esp+DCh] [ebp-34h]
int j; // [esp+DCh] [ebp-34h]
int k; // [esp+DCh] [ebp-34h]
char v7[18]; // [esp+F4h] [ebp-1Ch] BYREF

memset(v7, 0, sizeof(v7));
for ( i = 0; i < a2; ++i )
{
v3 = *a1++;
v7[i] = v3;
}
for ( j = 0; j < a2; ++j )
v7[j] -= 5;
for ( k = 0; k < a2; ++k )
{
if ( aHjOavtPzmHQ[k] != v7[k] )
return 0;
}
return 1;
}

全部ASCII+5就行

moectf{y0u_rem0v3d

Flag : moectf{y0u_rem0v3d_th3_junk_c0d3!!!}

RUST

逆向出来的主要逻辑处理部分还是比较震撼的:

一点一点看内存字符串是能看出来一些端倪的,写在注释里了:

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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
// local variable allocation has failed, the output may be wrong!
void __cdecl RUST::main::h271b26b98b069e5c()
{
core::result::Result<usize,std::io::error::Error> v0; // rdi
_str *v1; // rax
unsigned __int64 v2; // rdx
_str *v3; // rax
__int64 v4; // rdx
unsigned __int64 v5; // rdx
unsigned __int8 v6; // al
core::str::iter::Chars *v7; // rdx
core::str::iter::Chars *v8; // rsi
unsigned __int8 v9; // di
core::str::iter::Chars v10; // rax
core::ops::range::Range<usize> v11; // rdi
__int64 v12; // rdx
__u8_ *v13; // rax
unsigned __int64 v14; // rdx
usize v15; // rcx
__u8_ *v16; // rax
usize v17; // rdx
usize v18; // rcx
core::fmt::Arguments v19; // [rsp+0h] [rbp-2E8h]
core::fmt::Arguments v20; // [rsp+0h] [rbp-2E8h]
core::fmt::Arguments v21; // [rsp+0h] [rbp-2E8h]
core::fmt::Arguments v22; // [rsp+0h] [rbp-2E8h]
core::option::Option<&u8> *v23; // [rsp+40h] [rbp-2A8h]
__int64 v24; // [rsp+48h] [rbp-2A0h]
u8 *v25; // [rsp+A8h] [rbp-240h]
core::str::iter::Chars *v26; // [rsp+B0h] [rbp-238h]
__int64 v27; // [rsp+B8h] [rbp-230h]
alloc::string::String v28; // [rsp+F0h] [rbp-1F8h] BYREF
core::fmt::Arguments v29; // [rsp+108h] [rbp-1E0h] BYREF
core::fmt::Arguments v30; // [rsp+138h] [rbp-1B0h] BYREF
std::io::stdio::Stdin self; // [rsp+168h] [rbp-180h] BYREF
alloc::string::String buf; // [rsp+178h] [rbp-170h] BYREF
alloc::vec::Vec<u8,alloc::alloc::Global> v33; // [rsp+1B0h] [rbp-138h] BYREF
alloc::vec::Vec<u8,alloc::alloc::Global> v34; // [rsp+1C8h] [rbp-120h] BYREF
core::option::Option<char> v35[2]; // [rsp+1E0h] [rbp-108h] BYREF
u8 *end; // [rsp+1E8h] [rbp-100h]
int value; // [rsp+1F0h] [rbp-F8h]
char v38; // [rsp+1F7h] [rbp-F1h]
core::ops::range::Range<usize> v39; // [rsp+1F8h] [rbp-F0h]
core::option::Option<usize> v40; // [rsp+208h] [rbp-E0h] BYREF
core::option::Option<usize> *v41; // [rsp+218h] [rbp-D0h]
__int64 v42; // [rsp+220h] [rbp-C8h]
core::fmt::Arguments v43; // [rsp+228h] [rbp-C0h] BYREF
core::fmt::Arguments v44; // [rsp+258h] [rbp-90h] BYREF
core::fmt::Arguments v45; // [rsp+288h] [rbp-60h] BYREF
_str *v46; // [rsp+2C8h] [rbp-20h]
__int64 v47; // [rsp+2D0h] [rbp-18h]
int v48; // [rsp+2DCh] [rbp-Ch]
__int64 v49; // [rsp+2E0h] [rbp-8h]

alloc::string::String::new::hdd714fe41b40bd6e(&v28);
core::fmt::Arguments::new_v1::h461cdefb24fe7d3d(
&v29,
(___str_)__PAIR128__(1LL, &stru_57D80),
(__core::fmt::ArgumentV1_)(unsigned __int64)&stru_45210);
std::io::stdio::_print::he04414d477e307fd(v19);
core::fmt::Arguments::new_v1::h461cdefb24fe7d3d(
&v30,
(___str_)__PAIR128__(1LL, &stru_57D90),
(__core::fmt::ArgumentV1_)(unsigned __int64)&stru_45210);
std::io::stdio::_print::he04414d477e307fd(v20);
*(std::io::stdio::Stdin *)buf.vec.buf.alloc.gap0 = std::io::stdio::stdin::h8b590be40a6f0948();
std::io::stdio::Stdin::read_line::h1919dac6fd8b6380(&self, &buf);
*(_QWORD *)&v0.gap0[8] = &stru_57DA0;
*(_QWORD *)v0.gap0 = &self;
core::result::Result$LT$T$C$E$GT$::unwrap::hc3fcaeef2c7da20e(v0);
v1 = _$LT$alloc..string..String$u20$as$u20$core..ops..deref..Deref$GT$::deref::hf8c72e0a8093fc4f(
(_str *)&v28,
&stru_57DA0);
v3 = core::str::_$LT$impl$u20$str$GT$::trim_end::he08a22e006303d78(v1, (_str)__PAIR128__(v2, v2));
*(_QWORD *)&v0.gap0[8] = v4;
*(_QWORD *)v0.gap0 = v3;
v26 = (core::str::iter::Chars *)v3;
v27 = v4;
v46 = v3;
v47 = v4;
if ( core::str::_$LT$impl$u20$str$GT$::len::h88055d0d4e46e37e((_str)v0) != 30 )
{
/* 判断输入长度是否为30 */
core::fmt::Arguments::new_v1::h461cdefb24fe7d3d(
(core::fmt::Arguments *)&buf.vec.buf.cap,
(___str_)__PAIR128__(1LL, &stru_57DB8),
(__core::fmt::ArgumentV1_)(unsigned __int64)&stru_45210);
std::io::stdio::_print::he04414d477e307fd(v21);
std::process::exit::h0481127236e019a8(1);
}
/* 这个长度也是30,感觉有玄机 */
v25 = alloc::alloc::exchange_malloc::hde43adfcaffa380d(0x1EuLL, 1uLL);
*v25 = -27;
v25[1] = -25;
v25[2] = -19;
v25[3] = -21;
v25[4] = -4;
v25[5] = -18;
v25[6] = -13;
v25[7] = -38;
v25[8] = -3;
v25[9] = -5;
v25[10] = -4;
v25[11] = -41;
v25[12] = -6;
v25[13] = -19;
v25[14] = -2;
v25[15] = -41;
v25[16] = -1;
v25[17] = -31;
v25[18] = -28;
v25[19] = -28;
v25[20] = -41;
v25[21] = -22;
v25[22] = -19;
v25[23] = -41;
v25[24] = -23;
v25[25] = -1;
v25[26] = -18;
v25[27] = -3;
v25[28] = -71;
v25[29] = -11;
alloc::slice::_$LT$impl$u20$$u5b$T$u5d$$GT$::into_vec::hc1ad046747638d0f(
&v33,
(alloc::boxed::Box<[u8],alloc::alloc::Global>)__PAIR128__(30LL, (unsigned __int64)v25));
alloc::vec::Vec$LT$T$GT$::new::h06825c11fc154b77(&v34);
v6 = (unsigned __int8)core::str::_$LT$impl$u20$str$GT$::chars::hf93cf385741f1d37(v26, (_str)__PAIR128__(v5, v27));
v8 = v7;
v9 = v6;
v10 = _$LT$I$u20$as$u20$core..iter..traits..collect..IntoIterator$GT$::into_iter::h1e09a7560f6821f0(*(core::str::iter::Chars *)(&v8 - 1));
*(_QWORD *)v35[0].gap0 = *(_QWORD *)v10.iter._marker.gap0;
end = v10.iter.end;
while ( 1 )
{
value = (unsigned int)_$LT$core..str..iter..Chars$u20$as$u20$core..iter..traits..iterator..Iterator$GT$::next::h2296d5eebc07855b(
v35,
v8);
if ( value == 1114112 )
break;
v8 = (core::str::iter::Chars *)(unsigned int)value;
v48 = value;
alloc::vec::Vec$LT$T$C$A$GT$::push::h2e984ae54aba696c(&v34, value);
}
v38 = 1;
v39.start = 0LL;
v39.end = 30LL;
v11.start = 0LL;
v11.end = 30LL;
v40 = (core::option::Option<usize>)_$LT$I$u20$as$u20$core..iter..traits..collect..IntoIterator$GT$::into_iter::he9aa44a83c2e330d(v11);
while ( 1 )
{
v41 = core::iter::range::_$LT$impl$u20$core..iter..traits..iterator..Iterator$u20$for$u20$core..ops..range..Range$LT$A$GT$$GT$::next::h81eeeedceae2bd40(
&v40,
(core::ops::range::Range<usize> *)v11.end);
v42 = v12;
if ( !v41 )
break;
v24 = v42;
v49 = v42;
v13 = _$LT$alloc..vec..Vec$LT$T$C$A$GT$$u20$as$u20$core..ops..deref..Deref$GT$::deref::hf3486ea7fe4fc5e4(
(__u8_ *)&v33,
(alloc::vec::Vec<u8,alloc::alloc::Global> *)v11.end);
v23 = core::slice::_$LT$impl$u20$$u5b$T$u5d$$GT$::get::h830c88d7067bcded(
(core::option::Option<&u8> *)v13,
(__u8_)__PAIR128__(v24, v14),
v15);
HIBYTE(v21.args.data_ptr) = *core::option::Option$LT$T$GT$::unwrap::h56fe08ee1b248068((core::option::Option<&u8>)v23);
v16 = _$LT$alloc..vec..Vec$LT$T$C$A$GT$$u20$as$u20$core..ops..deref..Deref$GT$::deref::hf3486ea7fe4fc5e4(
(__u8_ *)&v34,
&stru_57DC8);
v21.args.length = v17;
*(_QWORD *)&v21.fmt.gap0[8] = core::slice::_$LT$impl$u20$$u5b$T$u5d$$GT$::get::h830c88d7067bcded(
(core::option::Option<&u8> *)v16,
(__u8_)__PAIR128__(v24, v17),
v18);
*(_QWORD *)v21.fmt.gap0 = core::option::Option$LT$T$GT$::unwrap::h56fe08ee1b248068(*(core::option::Option<&u8> *)&v21.fmt.gap0[8]);
v11.end = 136LL;
HIBYTE(v21.pieces.length) = _$LT$$RF$u8$u20$as$u20$core..ops..bit..BitXor$LT$u8$GT$$GT$::bitxor::h0f0af3b6f52b4b37(
*(u8 **)v21.fmt.gap0,
0x88u);
if ( HIBYTE(v21.args.data_ptr) != HIBYTE(v21.pieces.length) )
v38 = 0;
}
if ( (v38 & 1) != 0 )
/* 判断正确 */
core::fmt::Arguments::new_v1::h461cdefb24fe7d3d(
&v43,
(___str_)__PAIR128__(1LL, &stru_57DF8),
(__core::fmt::ArgumentV1_)(unsigned __int64)&stru_45210);
else
core::fmt::Arguments::new_v1::h461cdefb24fe7d3d(
&v44,
(___str_)__PAIR128__(1LL, &stru_57E08),
(__core::fmt::ArgumentV1_)(unsigned __int64)&stru_45210);
std::io::stdio::_print::he04414d477e307fd(v21);
core::fmt::Arguments::new_v1::h461cdefb24fe7d3d(
&v45,
(___str_)__PAIR128__(1LL, &stru_57E18),
(__core::fmt::ArgumentV1_)(unsigned __int64)&stru_45210);
std::io::stdio::_print::he04414d477e307fd(v22);
core::ptr::drop_in_place$LT$alloc..vec..Vec$LT$u8$GT$$GT$::hda80b89241f5d746(&v34);
core::ptr::drop_in_place$LT$alloc..vec..Vec$LT$u8$GT$$GT$::hda80b89241f5d746(&v33);
core::ptr::drop_in_place$LT$alloc..string..String$GT$::h779c957dd2b7a5fa(&v28);
}

判断正确的条件好像是v41 != 0

嘶 看了一眼v25开头三个数字,正好是moe啊

那直接猜:

1
2
3
4
5
6
7
data =  [-27, -25, -19, -21,-4,-18 ]
# -13, -38, -3, -5, -4, -41, -6, -19, -2, -41, -1, -31, -28, -28, -41, -22, -19, -41, -23, -1, -18, -3, -71, -11]
flag = ""
for i in data:
flag += chr(109 + 27 + i)

print(flag)

emm不对,应该不能这么做

做了一晚上 python背大锅,一直不知道怎么取python一个数字的高八位同时保留符号位

其实做的事情就是

1
HIBYTE(v21.pieces.length) = <&u8_as_core::ops::bit::BitXor<u8>>::bitxor(*(u8 **)&v21.fmt.gap0, 0x88u);

v21来源于全是负的的v25数组
其他的都是对向量的切片/迭代器/赋值操作,所以就有exp:

1
2
3
4
5
6
7
unsigned char data[30] = { -27, -25, -19, -21, -4, -18, -13, -38, -3, -5, -4, -41, -6, -19, -2, -41, -1, -31, -28, -28, -41, -22, -19, -41, -23, -1, -18, -3, -71, -11 };
unsigned char flag[30] = { 0 };
for (int i = 0; i < 30; i++)
{
flag[i] = data[i] ^ 0x88;
}
cout << flag << endl;

ezandroid

jadx下Main Activity在这里:

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
package com.doctor3.ezandroid;

import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.doctor3.ezandroid.databinding.ActivityMainBinding;

/* loaded from: classes4.dex */
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;

public native int check(String str);

static {
System.loadLibrary("ezandroid");
}

/* JADX INFO: Access modifiers changed from: protected */
@Override // androidx.fragment.app.FragmentActivity, androidx.activity.ComponentActivity, androidx.core.app.ComponentActivity, android.app.Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding inflate = ActivityMainBinding.inflate(getLayoutInflater());
this.binding = inflate;
setContentView(inflate.getRoot());
Button btn = (Button) findViewById(R.id.button);
final EditText input = (EditText) findViewById(R.id.input);
btn.setOnClickListener(new View.OnClickListener() { // from class: com.doctor3.ezandroid.MainActivity.1
@Override // android.view.View.OnClickListener
public void onClick(View view) {
String s = input.getText().toString();
if (s.length() != 23) {
Toast.makeText(MainActivity.this.getApplicationContext(), "长度不对哦", 0).show();
} else if (MainActivity.this.check(s) == 1) {
Context applicationContext = MainActivity.this.getApplicationContext();
Toast.makeText(applicationContext, "OK!RIGHT,flag is moectf{" + s + "}", 0).show();
} else {
Toast.makeText(MainActivity.this.getApplicationContext(), "Try to reverse the native lib!", 0).show();
}
}
});
}
}

引用了本地库的check函数,把Lib下的so文件拖进IDA,感觉下面的函数有点像:

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
_BOOL4 __cdecl sub_CC0(_BYTE *a1)
{
_BYTE *v1; // eax
bool v3; // [esp+Bh] [ebp-Dh]
char *v4; // [esp+10h] [ebp-8h]
int v5; // [esp+14h] [ebp-4h]

v4 = &byte_3934 + 18;
while ( 2 )
{
/* 要返回1的话需要v3=0 & *v4 == # => 需要 */
v3 = 0;
if ( *a1 )
v3 = *v4 != 42;//v4不是*就置v3=1
if ( !v3 )//如果v4是#
return *v4 == 35;
v1 = a1++;
switch ( *v1 )
{
case 'a':
--v4;
continue;
case 'd':
++v4;
continue;
case 's':
v4 += 15;
continue;
case 'w':
v4 -= 15;
continue;
default:
v5 = 0;
break;
}
break;
}
return v5;
}

v4地址指向394C

感觉像是在走迷宫,迷宫在内存里:

1
2
3
4
5
*(_DWORD *)&v7[119] = __readgsdword(0x14u);
memcpy(
dest,
"*****************@**************..************...************.********..#***.****.....*****.****.*********......****"
"*******************",

懂了,#是终点,@是起点,.是什么?好像是15个字符一行
凑一下:

1
2
3
4
5
6
7
8
9
***************
**@************
**..***********
*...***********
*.********..#**
*.****.....****
*.****.********
*......********
***************

还需要是23步:
asdsaassssdddddwwddddwd
ssassssdddddwwddddwdd
sdsaassssdddddwwddddwd
sdsaassssdddddwwddddwdd
sdsaassssdddddwwddddwdd

所以就是

1
2
moectf{sdsaassssdddddwwddddwdd}
moectf{asdsaassssdddddwwddddwd}

楽 上面那个是假的,真的是内存里那个

1
2
3
4
5
6
7
8
9
***************
**@******#*****
**.******.*****
...******.*****
.********.*****
.****.....*****
.****.*********
......*********
**************

这个是
moectf{ssaassssdddddwwddddwwww}

上面那个还是假的,得看看hint说的了

有个返回值是int的,这个应该才对:

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
int __cdecl JNI_OnLoad(int a1)
{
int v3; // [esp+28h] [ebp-B0h]
int v4; // [esp+40h] [ebp-98h] BYREF
char dest[136]; // [esp+44h] [ebp-94h] BYREF
unsigned int v6; // [esp+CCh] [ebp-Ch]

v6 = __readgsdword(0x14u);
memcpy(
dest,
"******************@**************.************...****#..*****.********.*****.****.....*****.****.*********......****"
"*******************",
sizeof(dest));
v3 = __strlen_chk(dest, 136);
__memcpy_chk(&byte_3934, dest, v3, 136);
v4 = 0;
if ( sub_1560(a1, (int)&v4, 65540) )
return -1;
*(&off_2910 + 1075) = (Elf32_Dyn *)sub_15B0(v4, "com/doctor3/ezandroid/MainActivity");
if ( !*(&off_2910 + 1075) )
return -1;
if ( sub_15F0(v4, dword_39DC, (int)off_2824, 1) >= 0 )
return 65540;
return -1;
}
1
2
3
4
5
6
7
8
9
***************
***@***********
***.***********
*...****#..****
*.********.****
*.****.....****
*.****.********
*......********
***************

就是
moectf{ssaassssdddddwwddddwwaa}

这个是对的

其实看名字也能看出来:

GUI

虽然但是,我好像得去写数据结构课设了

不管了 先IDA启动

有个correctEncryptedFlag,但是又找不到main在哪了

长得蛮像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
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
struct tagMSG Msg; // [esp+D0h] [ebp-54h] BYREF
WNDCLASSW WndClass; // [esp+F4h] [ebp-30h] BYREF

__CheckForDebuggerJustMyCode(&unk_1028026);
WndClass.style = 0;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
memset(&WndClass.hIcon, 0, 16);
WndClass.lpfnWndProc = sub_F50CDF;
WndClass.hInstance = hInstance;
WndClass.lpszClassName = L"FlagCheckerWindowClass";
RegisterClassW(&WndClass);
hWnd = CreateWindowExW(
0,
L"FlagCheckerWindowClass",
L"Windows Flag Checker",
0xCF0000u,
100,
100,
300,
200,
0,
0,
hInstance,
0);
ShowWindow(hWnd, nShowCmd);
UpdateWindow(hWnd);
while ( GetMessageW(&Msg, 0, 0, 0) )
{
TranslateMessage(&Msg);
DispatchMessageW(&Msg);
}
return Msg.wParam;
}

找到业务处理逻辑了:

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
LRESULT __stdcall sub_F5BF90(HWND hWndParent, UINT Msg, WPARAM wParam, LPARAM lParam)
{
HWND DlgItem; // eax
char v6[36]; // [esp+258h] [ebp-4E0h] BYREF
char v7[36]; // [esp+27Ch] [ebp-4BCh] BYREF
char v8[36]; // [esp+2A0h] [ebp-498h] BYREF
WCHAR String[516]; // [esp+2C4h] [ebp-474h] BYREF
HBRUSH hbr; // [esp+6CCh] [ebp-6Ch]
HDC hDC; // [esp+6D8h] [ebp-60h]
struct tagPAINTSTRUCT Paint; // [esp+6E4h] [ebp-54h] BYREF
int v13; // [esp+734h] [ebp-4h]

__CheckForDebuggerJustMyCode(&unk_1028026);
if ( Msg > 0xF )
{
if ( Msg == 16 )
{
DestroyWindow(hWndParent);
}
else
{
if ( Msg != 273 )
return DefWindowProcW(hWndParent, Msg, wParam, lParam);
if ( (unsigned __int16)wParam == 1 )
{
DlgItem = GetDlgItem(hWndParent, 2);
GetWindowTextW(DlgItem, String, 1024);
sub_F50C94(String);
v13 = 0;
sub_F50A0A(v7, v8);
LOBYTE(v13) = 1;
sub_F50C94(a91);
if ( (unsigned __int8)sub_F531AB(v7, v6) )
MessageBoxW(hWndParent, Text, L"hint", 0);
else
MessageBoxW(hWndParent, L"Sorry, flag error.", L"hint", 0);
sub_F529B8(v6);
LOBYTE(v13) = 0;
sub_F529B8(v7);
v13 = -1;
sub_F529B8(v8);
}
}
}
else
{
switch ( Msg )
{
case 0xFu:
hDC = BeginPaint(hWndParent, &Paint);
hbr = CreateSolidBrush(0xFFFFFFu);
FillRect(hDC, &Paint.rcPaint, hbr);
DeleteObject(hbr);
EndPaint(hWndParent, &Paint);
break;
case 1u:
CreateWindowExW(0, L"STATIC", L"Please input flag:", 0x50000000u, 10, 10, 120, 20, hWndParent, 0, 0, 0);
CreateWindowExW(0, L"EDIT", &word_FFE15C, 0x50800000u, 10, 40, 250, 30, hWndParent, (HMENU)2, 0, 0);
CreateWindowExW(0, L"BUTTON", L"submit", 0x50000000u, 10, 80, 80, 30, hWndParent, (HMENU)1, 0, 0);
break;
case 2u:
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hWndParent, Msg, wParam, lParam);
}
}
return 0;
}

这段看着像关键逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int __cdecl sub_F5BE00(int a1, int a2)
{
int v3; // [esp+F8h] [ebp-54h]
_WORD *v4; // [esp+104h] [ebp-48h]
char v5[32]; // [esp+11Ch] [ebp-30h] BYREF
int v6; // [esp+148h] [ebp-4h]

__CheckForDebuggerJustMyCode(&unk_1028026);
sub_F519E6(v5);
v6 = 0;
v4 = (_WORD *)sub_F50956(a2);
v3 = sub_F5017C();
while ( v4 != (_WORD *)v3 )
sub_F516B7((*v4++ - 5) ^ 0x51);
sub_F510C7(v5);
v6 = -1;
sub_F529B8(v5);
return a1;
}

动态调试有 v3 也就是v4的结束地址是dword_6FF392

一看原来是我输入的依托东西,再看看

这个函数好像只是加密?(*v4++ - 5) ^ 0x51

终于出了草

一点一点翻函数,看到一个长得特别像字符串比较的函数,在比较的地方下断点:

到了之后F8单步步过看汇编:

这里四段数据,一段一段拿过来猜,有一段解密之后就是flag:

1
2
;下面直接点击就能看到加密之后的flag
movzx eax, word ptr [edx]

这60个字节dump下来解密就行了

exp:

1
2
3
4
5
6
data = [0x0039, 0x003B, 0x0031, 0x000F, 0x003E, 0x0030, 0x0027, 0x0013, 0x0001, 0x007D, 0x0070, 0x0070, 0x0003, 0x007D, 0x0038, 0x000E, 0x007A, 0x0023, 0x007C, 0x000B, 0x001A, 0x003C, 0x007D, 0x0039, 0x007F, 0x003C, 0x004D, 0x004D, 0x004D, 0x0029, 0x0000]
flag = ""
for i in data:
flag += chr((i^0x0051) + 5)

print(flag)

unwind

  • 标题: moeCTF2023 wp
  • 作者: yansui
  • 创建于: 2023-10-24 10:35:25
  • 更新于: 2023-10-24 10:34:54
  • 链接: http://yansui.xyz/2023/10/24/moectf/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
 评论