2022MT-CTF逆向部分题解,这次题目比较有意思,一大一小,small and static。
很精致的のlf文件,IDA加载失败,但是代码足够小,用cutter进行识别。
关键代码逻辑如下,可见是个tea加密,魔改了delta和加密轮数。
翻译后的代码如下
1
2
3
4
5
6
7
8
9
10
11
12
|
void Tea_Encrypt(ut32
*
src) {
ut32
sum
=
0
;
ut32 v0
=
src[
0
];
ut32 v1
=
src[
1
];
for
(
int
i
=
0
; i <
0x23
; i
+
+
) {
sum
+
=
0x67452301
;
v0
+
=
((v1 <<
4
)
+
1
) ^ (v1
+
sum
) ^ ((v1 >>
5
)
+
0x23
);
v1
+
=
((v0 <<
4
)
+
0x45
) ^ (v0
+
sum
) ^ ((v0 >>
5
)
+
0x67
);
}
src[
0
]
=
v0;
src[
1
]
=
v1;
}
|
接着是密文比对,是倒叙进行比对。
因为rsi在上面代码中每次会+8,所以实际的密文顺序不变,并且在偏移0x100f7处。
解密代码如下
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
|
"""
enc=list(bytes.fromhex('437108ded21bf9c4dcdaf6da4cd59e6de74eeb7504dc1d5dd90f1b51fb88dc51'))
for i in range(0,len(enc),4):
num=0
for j in range(4):
num|=(enc[i+j]<<(8*j))
print(hex(num),end=',')
"""
#include<iostream>
#define ut32 unsigned int
#define delta 0x67452301
void Tea_Decrypt(ut32
*
enc) {
unsigned
int
sum
=
0x67452301
*
0x23
;
/
/
0x1e73c923
;
ut32 v0
=
enc[
0
];
ut32 v1
=
enc[
1
];
for
(
int
i
=
0
; i <
0x23
; i
+
+
) {
v1
-
=
((v0 <<
4
)
+
0x45
) ^ (v0
+
sum
) ^ ((v0 >>
5
)
+
0x67
);
v0
-
=
((v1 <<
4
)
+
1
) ^ (v1
+
sum
) ^ ((v1 >>
5
)
+
0x23
);
sum
-
=
0x67452301
;
}
enc[
0
]
=
v0;
enc[
1
]
=
v1;
}
void Tea_Encrypt(ut32
*
src) {
ut32
sum
=
0
;
ut32 v0
=
src[
0
];
ut32 v1
=
src[
1
];
for
(
int
i
=
0
; i <
0x23
; i
+
+
) {
sum
+
=
0x67452301
;
v0
+
=
((v1 <<
4
)
+
1
) ^ (v1
+
sum
) ^ ((v1 >>
5
)
+
0x23
);
v1
+
=
((v0 <<
4
)
+
0x45
) ^ (v0
+
sum
) ^ ((v0 >>
5
)
+
0x67
);
}
printf(
"%08x\n"
,
sum
);
src[
0
]
=
v0;
src[
1
]
=
v1;
}
int
main() {
ut32 enc[
8
]
=
{
0xde087143
,
0xc4f91bd2
,
0xdaf6dadc
,
0x6d9ed54c
,
0x75eb4ee7
,
0x5d1ddc04
,
0x511b0fd9
,
0x51dc88fb
};
for
(
int
i
=
0
; i <
8
; i
+
=
2
) {
Tea_Decrypt(enc
+
i);
}
for
(
int
i
=
0
; i <
32
; i
+
+
) {
printf(
"%c"
,
*
((unsigned char
*
)enc
+
i));
}
/
/
327a6c4304ad5938eaf0efb6cc3e53dc
return
0
;
}
|
采用静态编译,程序比较的臃肿,加载或者是恢复符号需要大量的时间,并且程序控制流走向不是很清晰。
因为符号恢复时间比较长,所以wp基于修复后的程序编写,符号恢复思路是全局使用Lumina,对于部分函数使用finger。
主函数处理如下,前部分是取出flag的内容,去掉"-"的符号
可是调试发现,在循环右移2后,走到vector_unicorn
的地方程序会退出,并且v10
是重复的两组显然不是需要的flag。
借助find_crypt
插件,发现程序中存在aes加密,所以猜测发生了重定位。用pintool
打印trace
,最好是code coverage
,因为比较轻量且会高亮控制流。
https://github.com/gaasedelen/lighthouse
测试输入flag{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa},走过的代码会被高亮。
结合对表的交叉引用,发现可疑处理函数。
发现该部分处理过32字节的字符串,分成两段处理,IDA调试发现该部分断下后rdi0
中存储的是输入flag{}中的内容。
第一段处理
结合常量表和10次异或,猜测是aes加密,并且轮秘钥已预先生成好写在了10个xmmword
变量中,所以第一个便是初始秘钥。
对于第二部分的加密,因为之前出现的unicorn
字符串,并且结构与unicorn
比较类似,搜索一个c调用的模板进行比对。
sub_406BBB
是uc_open
确定架构和模式,2对应着ARM64。
1
2
3
4
5
6
7
8
9
10
|
typedef enum uc_arch {
UC_ARCH_ARM
=
1
,
/
/
ARM architecture (including Thumb, Thumb
-
2
)
UC_ARCH_ARM64,
/
/
ARM
-
64
, also called AArch64
UC_ARCH_MIPS,
/
/
Mips architecture
UC_ARCH_X86,
/
/
X86 architecture (including x86 & x86
-
64
)
UC_ARCH_PPC,
/
/
PowerPC architecture (currently unsupported)
UC_ARCH_SPARC,
/
/
Sparc architecture
UC_ARCH_M68K,
/
/
M68K architecture
UC_ARCH_MAX,
} uc_arch;
|
字节码存在byte_19762c0
中,调试可知v2=0x5dc, dump出0x5dc个字节写入一个文件,ida用arm架构解析,结合代码可知该部分是对第二部分flag进行了处理。
1
2
3
4
5
6
7
8
|
code
=
[
0xFF
,
0x43
,
0x01
,
0xD1
,
0xE0
,
0x27
,
0x00
,
0xF9
,
0xE8
,
0x27
,
0x40
,
0xF9
,
0x08
,
0x01
,
0x40
,
0x39
,
0xE9
,
0x27
,
0x40
,
0xF9
,
0x29
,
0x15
,
0x40
,
0x39
,
0x08
,
0x01
,
0x09
,
0x4A
,
0xE9
,
0x27
,
0x40
,
0xF9
,
0x29
,
0x09
,
0x40
,
0x39
,
0x08
,
0x15
,
0x09
,
0x4A
,
0xE9
,
0x27
,
0x40
,
0xF9
,
0x29
,
0x25
,
0x40
,
0x39
,
0x08
,
0x05
,
0x09
,
0x4A
,
0xE9
,
0x27
,
0x40
,
0xF9
,
0x29
,
0x29
,
0x40
,
0x39
,
0x09
,
0x05
,
0x09
,
0x4A
,
...
0xE8
,
0x03
,
0x00
,
0xB9
,
0xF2
,
0xFF
,
0xFF
,
0x17
,
0xFF
,
0x43
,
0x01
,
0x91
]
f
=
open
(r
'bin'
,
'wb+'
)
f.write(bytes(code))
|
ida加载bin
后第一部分如下,逻辑方程,可用z3约束求解。
第二部分是个xxtea
,delta为 -0x21524111(0xdeadbeef)
综上第一部分加密为aes_ecb,第二部分为逻辑方程+xxtea,接下来找到比对密文即可,根据trace可知真正比对密文为下面32字节。
解密如下
part1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
from
Crypto.Cipher.AES
import
*
def
getb(a:
list
):
res
=
b''
for
i
in
a:
res
+
=
int
.to_bytes(i,
8
,
'little'
)
return
res
enc
=
[
0x1624B3C3E0E4FEAA
,
0xA0CAE19E13F75B4E
,
0x4D26D4BBFB732728
,
0x26BAFC68DA122E3A
]
c1
=
getb(enc[:
2
])
c2
=
getb(enc[
2
:])
#flag{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
k
=
[
0x0B
,
0x3A
,
0xBA
,
0x39
,
0xA2
,
0x64
,
0x27
,
0x1C
,
0x36
,
0x31
,
0x98
,
0x80
,
0x9E
,
0x77
,
0x9E
,
0xEB
]
aes
=
new(bytes(k),MODE_ECB)
t
=
aes.decrypt(c1)
print
(t)
##2e64949cd16c4449
|
part2
解xxtea
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
|
#include<iostream>
#define ut32 unsigned int
#define delta 0xdeadbeef
using namespace std;
void XXTea_Encrypt(ut32
*
src, ut32 n, ut32
*
key);
void XXTea_Decrypt(ut32
*
enc, ut32 n, ut32
*
key);
void output(ut32
*
m, ut32
len
);
void XXTea_Encrypt(ut32
*
src, ut32 n, ut32
*
key) {
ut32 y, z,
sum
=
0
;
ut32 e, rounds;
int
p;
/
/
定义为无符号时 p
-
1
>
=
0
这个判断恒成立
rounds
=
6
+
52
/
n;
do {
z
=
src[n
-
1
];
sum
+
=
delta;
e
=
(
sum
>>
2
) &
3
;
for
(p
=
0
; p < n
-
1
; p
+
+
) {
y
=
src[p
+
1
];
src[p]
+
=
(((z >>
5
^ y <<
2
)
+
(y >>
3
^ z <<
4
)) ^ ((
sum
^ y)
+
(key[(p &
3
) ^ e] ^ z)));
z
=
src[p];
}
y
=
src[
0
];
src[n
-
1
]
+
=
(((z >>
5
^ y <<
2
)
+
(y >>
3
^ z <<
4
)) ^ ((
sum
^ y)
+
(key[(p &
3
) ^ e] ^ z)));
}
while
(
-
-
rounds);
}
void XXTea_Decrypt(ut32
*
enc, ut32 n, ut32
*
key) {
ut32 y, z,
sum
;
ut32 e, rounds;
int
p;
rounds
=
6
+
52
/
n;
sum
=
delta
*
rounds;
do {
e
=
(
sum
>>
2
) &
3
;
for
(p
=
n
-
1
; p >
0
; p
-
-
) {
y
=
enc[(p
+
1
)
%
n];
z
=
enc[(p
-
1
)];
enc[p]
-
=
(((z >>
5
^ y <<
2
)
+
(y >>
3
^ z <<
4
)) ^ ((
sum
^ y)
+
(key[(p &
3
) ^ e] ^ z)));
}
y
=
enc[
1
];
z
=
enc[n
-
1
];
enc[
0
]
-
=
(((z >>
5
^ y <<
2
)
+
(y >>
3
^ z <<
4
)) ^ ((
sum
^ y)
+
(key[(
0
&
3
) ^ e] ^ z)));
sum
-
=
delta;
}
while
(
-
-
rounds);
}
void output(ut32
*
m, ut32
len
) {
for
(
int
i
=
0
; i <
len
; i
+
+
)
printf(
"0x%08x "
, m[i]);
printf(
"\n"
);
}
int
main() {
ut32 m[
4
]
=
{
0xFB732728
,
0x4D26D4BB
,
0xDA122E3A
,
0x26BAFC68
};
ut32 k[
4
]
=
{
12
,
34
,
56
,
78
};
XXTea_Decrypt(m,
4
, k);
for
(
int
i
=
0
; i <
16
; i
+
+
) {
printf(
"%d,"
,
*
((unsigned char
*
)m
+
i));
}
return
0
;
}
|
z3约束求解
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
|
from
z3
import
*
s
=
Solver()
enc
=
[
53
,
0
,
27
,
154
,
177
,
235
,
146
,
141
,
130
,
127
,
222
,
7
,
180
,
208
,
151
,
164
]
m
=
[BitVec(
'm%d'
%
i,
8
)
for
i
in
range
(
16
)]
s.add(m[
0
] ^ m[
5
] ^ (
32
*
m[
2
]) ^ (
2
*
m[
9
]) ^ (
2
*
m[
10
])
=
=
enc[
0
] )
s.add(m[
1
] ^ (m[
13
] >>
2
) ^ (m[
12
] >>
2
) ^ m[
15
] ^ (m[
4
] >>
6
)
=
=
enc[
1
] )
s.add(m[
2
] ^ (m[
1
] <<
7
) ^ (m[
15
] >>
6
) ^ (
8
*
m[
14
]) ^ (m[
4
] >>
1
)
=
=
enc[
2
] )
s.add(m[
3
] ^ (
2
*
m[
10
]) ^ (m[
14
] >>
4
) ^ (m[
6
] >>
4
) ^ (
32
*
m[
13
])
=
=
enc[
3
] )
s.add(m[
4
] ^ (
4
*
m[
3
]) ^ m[
10
] ^ (
2
*
m[
0
]) ^ (m[
1
] >>
2
)
=
=
enc[
4
] )
s.add(m[
5
] ^ (m[
1
] >>
3
) ^ (m[
13
] <<
7
) ^ (m[
2
] >>
7
) ^ (
4
*
m[
8
])
=
=
enc[
5
] )
s.add(m[
6
] ^ (m[
8
] >>
7
) ^ (
4
*
m[
5
]) ^ (
16
*
m[
3
]) ^ (m[
14
] >>
3
)
=
=
enc[
6
] )
s.add(m[
7
] ^ (m[
11
] >>
6
) ^ (m[
2
] >>
5
) ^ (m[
3
] <<
6
) ^ (
2
*
m[
1
])
=
=
enc[
7
] )
s.add(m[
8
] ^ (m[
11
] <<
7
) ^ (m[
5
] >>
6
) ^ (
2
*
m[
4
]) ^ (
16
*
m[
6
])
=
=
enc[
8
] )
s.add(m[
9
] ^ (
8
*
m[
15
]) ^ (m[
4
] >>
3
) ^ (
32
*
m[
12
]) ^ m[
2
]
=
=
enc[
9
] )
s.add(m[
10
] ^ ( m[
0
] >>
2
) ^ (
2
*
m[
9
]) ^ (m[
5
] <<
7
) ^ (m[
11
] >>
7
)
=
=
enc[
10
] )
s.add(m[
11
] ^ m[
5
] ^ (m[
10
] >>
4
) ^ (m[
6
] >>
6
) ^ (m[
3
] >>
6
)
=
=
enc[
11
] )
s.add(m[
12
] ^ (m[
4
] <<
6
) ^ (m[
2
] >>
1
) ^ (m[
15
] >>
1
) ^ (m[
11
] <<
7
)
=
=
enc[
12
] )
s.add(m[
13
] ^ (m[
6
] >>
3
) ^ (m[
9
] >>
7
) ^ (
32
*
m[
1
]) ^ (m[
11
] >>
7
)
=
=
enc[
13
] )
s.add(m[
14
] ^ (m[
7
] <<
7
) ^ (
16
*
m[
9
]) ^ (m[
8
] >>
1
) ^ (
16
*
m[
2
])
=
=
enc[
14
] )
s.add(m[
15
] ^ ( m[
0
] >>
1
) ^ (m[
13
] >>
6
) ^ (
4
*
m[
7
]) ^ (m[
11
] >>
5
)
=
=
enc[
15
] )
print
(s.check())
ans
=
s.model()
for
i
in
range
(
16
):
print
(
chr
(ans[m[i]].as_long()),end
=
'')
#87320a0cc24e6667
|
最终提交uuid格式
更多【2022MT-CTF Re】相关视频教程:www.yxfzedu.com