首页
社区
课程
招聘
[原创]2022MT-CTF Re
发表于: 2022-9-18 22:45 6920

[原创]2022MT-CTF Re

2022-9-18 22:45
6920

2022MT-CTF逆向部分题解,这次题目比较有意思,一大一小,small and static。

很精致的のlf文件,IDA加载失败,但是代码足够小,用cutter进行识别。

关键代码逻辑如下,可见是个tea加密,魔改了delta和加密轮数。

image-20220917182706615

翻译后的代码如下

接着是密文比对,是倒叙进行比对。

image-20220917183048589

因为rsi在上面代码中每次会+8,所以实际的密文顺序不变,并且在偏移0x100f7处。

image-20220917183254493

解密代码如下

采用静态编译,程序比较的臃肿,加载或者是恢复符号需要大量的时间,并且程序控制流走向不是很清晰。

因为符号恢复时间比较长,所以wp基于修复后的程序编写,符号恢复思路是全局使用Lumina,对于部分函数使用finger。

主函数处理如下,前部分是取出flag的内容,去掉"-"的符号

image-20220917184140810

可是调试发现,在循环右移2后,走到vector_unicorn的地方程序会退出,并且v10是重复的两组显然不是需要的flag。

借助find_crypt插件,发现程序中存在aes加密,所以猜测发生了重定位。用pintool打印trace,最好是code coverage,因为比较轻量且会高亮控制流。
https://github.com/gaasedelen/lighthouse

测试输入flag{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa},走过的代码会被高亮。

image-20220917184946792

结合对表的交叉引用,发现可疑处理函数。

image-20220917185116625

继续交叉引用,直到sub_4064F0

image-20220917185157993

发现该部分处理过32字节的字符串,分成两段处理,IDA调试发现该部分断下后rdi0中存储的是输入flag{}中的内容。

第一段处理

image-20220917185935985

结合常量表和10次异或,猜测是aes加密,并且轮秘钥已预先生成好写在了10个xmmword变量中,所以第一个便是初始秘钥。

对于第二部分的加密,因为之前出现的unicorn字符串,并且结构与unicorn比较类似,搜索一个c调用的模板进行比对。

image-20220917190417537

sub_406BBBuc_open确定架构和模式,2对应着ARM64。

字节码存在byte_19762c0中,调试可知v2=0x5dc, dump出0x5dc个字节写入一个文件,ida用arm架构解析,结合代码可知该部分是对第二部分flag进行了处理。

ida加载bin后第一部分如下,逻辑方程,可用z3约束求解。

image-20220917190959288

第二部分是个xxtea,delta为 -0x21524111(0xdeadbeef)

image-20220917191302637

综上第一部分加密为aes_ecb,第二部分为逻辑方程+xxtea,接下来找到比对密文即可,根据trace可知真正比对密文为下面32字节。

image-20220917191639777

解密如下

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期)

收藏
免费 4
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//