-
-
[原创]2022MT-CTF Re
-
发表于: 2022-9-18 22:45 6920
-
2022MT-CTF逆向部分题解,这次题目比较有意思,一大一小,small and static。
很精致的のlf文件,IDA加载失败,但是代码足够小,用cutter进行识别。
关键代码逻辑如下,可见是个tea加密,魔改了delta和加密轮数。
翻译后的代码如下
接着是密文比对,是倒叙进行比对。
因为rsi在上面代码中每次会+8,所以实际的密文顺序不变,并且在偏移0x100f7处。
解密代码如下
采用静态编译,程序比较的臃肿,加载或者是恢复符号需要大量的时间,并且程序控制流走向不是很清晰。
因为符号恢复时间比较长,所以wp基于修复后的程序编写,符号恢复思路是全局使用Lumina,对于部分函数使用finger。
主函数处理如下,前部分是取出flag的内容,去掉"-"的符号
可是调试发现,在循环右移2后,走到vector_unicorn
的地方程序会退出,并且v10
是重复的两组显然不是需要的flag。
借助find_crypt
插件,发现程序中存在aes加密,所以猜测发生了重定位。用pintool
打印trace
,最好是code coverage
,因为比较轻量且会高亮控制流。
https://github.com/gaasedelen/lighthouse
测试输入flag{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa},走过的代码会被高亮。
结合对表的交叉引用,发现可疑处理函数。
继续交叉引用,直到sub_4064F0
发现该部分处理过32字节的字符串,分成两段处理,IDA调试发现该部分断下后rdi0
中存储的是输入flag{}中的内容。
第一段处理
结合常量表和10次异或,猜测是aes加密,并且轮秘钥已预先生成好写在了10个xmmword
变量中,所以第一个便是初始秘钥。
对于第二部分的加密,因为之前出现的unicorn
字符串,并且结构与unicorn
比较类似,搜索一个c调用的模板进行比对。
sub_406BBB
是uc_open
确定架构和模式,2对应着ARM64。
字节码存在byte_19762c0
中,调试可知v2=0x5dc, dump出0x5dc个字节写入一个文件,ida用arm架构解析,结合代码可知该部分是对第二部分flag进行了处理。
ida加载bin
后第一部分如下,逻辑方程,可用z3约束求解。
第二部分是个xxtea
,delta为 -0x21524111(0xdeadbeef)
综上第一部分加密为aes_ecb,第二部分为逻辑方程+xxtea,接下来找到比对密文即可,根据trace可知真正比对密文为下面32字节。
解密如下
part1
part2
解xxtea
z3约束求解
最终提交uuid格式
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;
}
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;
}
"""
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
;
}
"""
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
;
}
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;
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
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)