四象限守护者队 reverse 部分 WP

“磐石行动”2024第二届全国高校网络安全攻防活动:CTF 个人排名15,团体排名17,总排35进入复赛。出了三道 re ,最简单的签到没做出来有点可惜了,这是我距离 ak 最近的一次了。然后就是学到了很多新的东西比如说固件逆向,虽然说有点公式化了但是还是蛮有难度的(好在加密都比较简单)。然后比较可惜的是数据安全通道一题未出,真会不了一点,太吃脑子了。

image-20240525212038773

image-20240525211116000

image-20240525211152728

ezlogin

简单des加密藏得很深,混淆的函数太多了有点难找,重点是找到key。这个软件不能debug权限不够,那就解包加权限,然后调试出key=’key_here’

1、先反编译apk文件,删除原来的apk文件

1
apktool  d  ezlogin.APK

2、给AndroidManifest.xml设置为debuggable

1
android:debuggable="true"

3、重新打包

1
apktool  b  ezlogin

4、在dist文件夹找到新的apk,对文件进行对齐

1
zipalign -p -f -v 4 ezlogin.apk ezlogin1.apk

5、进行重新签名

1
apksigner sign --ks abc.keystore ezlogin1.apk
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
import base64
from Crypto.Cipher import DES
from Crypto.Util.Padding import unpad

def decrypt_des(ciphertext, key):
try:
# Convert the base64-encoded ciphertext to bytes
ciphertext_bytes = base64.b64decode(ciphertext)

# Create a DES cipher object with the provided key
cipher = DES.new(key.encode(), DES.MODE_ECB)

# Decrypt the ciphertext
plaintext_bytes = cipher.decrypt(ciphertext_bytes)

# Remove padding
plaintext = unpad(plaintext_bytes, 8).decode('utf-8')
return plaintext
except Exception as e:
raise RuntimeError(f"Decryption error: {e}")

# Example usage
encrypted_string = "yU4Ad3tEpSgTdmBJ5wDbUhZAeY+Lm3VobQEQLyck1lfhEJ+OKcyU10PMij+RGqus"
key = 'key_here' # Replace with the actual key

try:
decrypted_text = decrypt_des(encrypted_string, key)
print(f"Decrypted text: {decrypted_text}")
except Exception as e:
print(f"Error: {e}")
#Decrypted text: flag{f3c826ec-8453-4b80-8f52-468e0f9e05bf}

easy_iot

第一次做固件逆向题完全没有思路,参考这篇文章

IoT固件逆向入门-腾讯云开发者社区-腾讯云

1
binwalk -e out.bin

用binwalk把固件分离出来,然后他说flag在最简单的文件里面我直接找bin然后是文件修改时间最晚的就只有bash,套了一层upx的壳,去掉然后放进ida反编译

1
2
3
4
5
6
a=[5, 15, 2, 4, 24, 54, 85, 47, 85, 39, 86, 85, 85, 34, 86, 58, 81, 53, 86, 86, 18, 38, 86, 57, 22,85, 86, 47, 22, 81, 85, 58, 32, 36, 86, 57, 32, 30]
b=''
for i in a:
b+=chr(i^0x63)
print(b)
#flag{U6L6D566A5Y2V55qE5Zu65Lu26YCG5ZC}

easystm32

第一次操作这种固件,参考文章:

【MCU】可怕,别人把我MCU固件给反汇编了!(逆向)-CSDN博客

image-20240526134923312

image-20240526135231150

按c反编译之后查看string可以发现提示是:

Untitled

随后搜索有可能加密后的字符串:

Untitled

加密方法:

Untitled

解码就完事:

1
2
3
4
5
6
a=[0x66,0x6D,0x63,0x64,0x7f,0x57,0x37,0x4b,0x3c,0x7b,0x58,0x40,0x3a,0x70]
b=''
for i in range(14):
b+=chr(a[i]^i)
print(b)
#flag{R1L4rRK6}

再转成md5

Untitled

今天天气怎么样

第一部分包含两个函数一加密一比较:crazy()、ohh()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//crazy()
for ( i = 0; i <= 29; ++i )
{
v3 = &a1[i];
if ( (i & 1) != 0 )
a1[i] -= i;
else
a1[i] ^= i;
}
//ohh()
for ( i = 0; i <= 29; ++i )
{
if ( a1[i] != v2[i] )
v3 = 0;
}
//v2=[102, 107, 99, 100, 127, 99, 105, 112, 87, 96, 121, 84, 120, 91, 107, 80, 103, 84, 115, 97, 124, 80, 100, 72, 108, 86, 126, 70, 101, 96]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>

void action3(int *str) {
for (int i = 0; i < 30; ++i) {
if ((i & 1) != 0) {
str[i] += i;
} else {
str[i] ^= i;
}
}
}

int main() {
int a[] = {102, 107, 99, 100, 127, 99, 105, 112, 87, 96, 121, 84, 120, 91, 107, 80, 103, 84, 115, 97, 124, 80, 100, 72, 108, 86, 126, 70, 101, 96};
action3(a);
for (int i = 0; i < 30; ++i) {
printf("%c", a[i]);
}
printf("\n");
return 0;
}
//flag{how_is_the_weather_today}

然后发现后面还有一关,要调用my_function(),但是都是花指令和奇怪的跳转,打断点单步调试再create function就找到了实际调用逻辑。

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
puts("please input your True flag:");
scanf("%40s", Str);
v7 = strlen(Str);
if ( v7 != 30 )
{
puts("Wrong!");
exit(0);
}
qmemcpy(v4, &unk_404040, sizeof(v4));
memset(v5, 0, sizeof(v5));
memset(v6, 0, sizeof(v6));
v2 = strlen(a2);
xxx_init(v5, (unsigned __int8 *)a2, v2);
for ( i = 0; i <= 255; ++i )
v6[i] = v5[i];
xxx_crypt(v5, (unsigned __int8 *)Str, v7);
v9 = 1;
for ( j = 0; ; ++j )
{
if ( j >= v7 )
goto LABEL_11;
if ( (unsigned __int8)Str[j] != v4[j] )
break;
}
v9 = 0;
LABEL_11:
if ( v9 )
puts("Good! have a beautiful day for you!");
else
puts("May be try again?");

//xxx_crypt(rc4加密)
unsigned int __cdecl xxx_crypt(unsigned __int8 *a1, unsigned __int8 *a2, unsigned int a3)
{
unsigned int result; // eax
unsigned __int8 v4; // [esp+Fh] [ebp-15h]
unsigned int i; // [esp+14h] [ebp-10h]
int v6; // [esp+18h] [ebp-Ch]
int v7; // [esp+1Ch] [ebp-8h]

v7 = 0;
v6 = 0;
for ( i = 0; ; ++i )
{
result = i;
if ( i >= a3 )
break;
v7 = (v7 + 1) % 256;
v6 = (v6 + a1[v7]) % 256;
v4 = a1[v7];
a1[v7] = a1[v6];
a1[v6] = v4;
a2[i] ^= a1[(unsigned __int8)(a1[v7] + a1[v6])];
}
return result;
}

单步调试得到s盒和最后要比对的值,rc4求解即可得出答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
a=[48, 114, 153, 160, 71, 163, 108, 200, 150, 187, 78, 151, 90, 7, 167, 38, 120, 18, 132, 216, 144, 9, 210, 249, 62, 52, 64, 73, 109, 29, 66, 125, 175, 119, 208, 47, 193, 138, 21, 159, 87, 241, 40, 218, 92, 234, 59, 91, 180, 99, 243, 121, 248, 148, 2, 55, 95, 220, 183, 178, 82, 0, 98, 12, 69, 36, 17, 237, 252, 165, 14, 31, 68, 113, 8, 254, 67, 37, 65, 177, 105, 42, 227, 129, 93, 209, 219, 147, 251, 10, 83, 238, 225, 70, 28, 253, 168, 236, 101, 89, 61, 201, 33, 191, 217, 128, 136, 23, 211, 231, 247, 145, 146, 112, 6, 80, 184, 197, 239, 255, 43, 134, 111, 97, 57, 81, 103, 11, 106, 172, 26, 1, 39, 226, 230, 215, 158, 53, 244, 50, 224, 35, 4, 152, 72, 164, 115, 58, 161, 126, 100, 117, 154, 46, 174, 79, 223, 214, 137, 186, 5, 24, 190, 22, 49, 235, 195, 162, 179, 60, 44, 203, 233, 245, 54, 74, 135, 156, 143, 204, 246, 140, 16, 124, 194, 171, 20, 88, 76, 181, 212, 77, 15, 188, 3, 166, 202, 142, 176, 30, 27, 206, 192, 213, 240, 221, 133, 189, 84, 96, 131, 110, 170, 141, 196, 222, 63, 242, 13, 45, 107, 155, 51, 198, 127, 94, 41, 34, 149, 205, 185, 182, 56, 250, 157, 139, 173, 123, 32, 232, 199, 116, 104, 75, 25, 122, 102, 207, 229, 118, 228, 169, 130, 19, 86, 85]
b='flag{how_is_the_weather_today}'
c=[77, 216, 118, 45, 12, 38, 12, 83, 218, 192, 23, 55, 140, 215, 243, 217, 208, 70, 43, 21, 152, 103, 241, 173, 166, 14, 124, 102, 144, 127]
def rc4_decrypt(S, ciphertext):
j = 0
out = []
i = j = 0
for char in ciphertext:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
k = S[(S[i] + S[j]) % 256]
out.append(char ^ k)

return bytes(out)
# 解密
plaintext = rc4_decrypt(a, c)
print("解密后的明文:", plaintext.decode("utf-8"))
#解密后的明文: flag{This_is_a_beautiful_day!}