CISCN CTF rthread.bin 逆向题

(编辑:jimmy 日期: 2024/12/24 浏览:2)

CISCN - rtthread是一个非常新颖的好题
题目中给的是一个 sh 文件和一个类似固件的bin rtthread.bin
CISCN CTF rthread.bin 逆向题

图片.png


运行起来,啥也没有
尝试 ?、help 等,看看会给我们提供什么信息
CISCN CTF rthread.bin 逆向题

图片.png


里面有一些提供的命令,比如 ifconfig,date 等信息
CISCN CTF rthread.bin 逆向题

图片.png


CTF 题目当然就会想要追求 flag,看到最前面的两个命令
CISCN CTF rthread.bin 逆向题

图片.png


可以看到是作者自定义的一个广告位置,真有意思~~~
然后尝试 get_flag 这个命令,得到一个迷宫
CISCN CTF rthread.bin 逆向题

图片.png


如果瞎输入的话,就是会报错的
CISCN CTF rthread.bin 逆向题

图片.png


不是上下左右键的话,就是 WASD 呗(多年来打小霸王游戏机的经验)
合理的猜想就是从 S(Start)点上下左右走到F(Finish)点
很多条可达的路径,通过 Oops 的方式 ban 掉了很多条,当然就只留下来了唯一确定的可行字符串
CISCN CTF rthread.bin 逆向题

图片.png


输入的字符串为:
dddwwawwwwaasdsasawawdwaaasawassssdwdsddssasddw
CISCN CTF rthread.bin 逆向题

图片.png


首先是判断长度,再是判断逻辑
ok,到了这里就需要开始逆向了!
CISCN CTF rthread.bin 逆向题

图片.png


CISCN CTF rthread.bin 逆向题

图片.png


CISCN CTF rthread.bin 逆向题

图片.png


CISCN CTF rthread.bin 逆向题

图片.png


可以发现,字符串是没有交叉引用的
不过既然函数不是很多,可以手动 F5 去看特征
CISCN CTF rthread.bin 逆向题

图片.png


这个是典型的常数值:0x61C88647、0xC6EF3720:典型的 TEA 算法特征
CISCN CTF rthread.bin 逆向题

图片.png


5F4 这个函数是递归,根据输入来处理地图中的迷宫的
CISCN CTF rthread.bin 逆向题

图片.png


可以看到这里的 sub_798 是 sub_5F4 的上层函数
根据 sub_798 的逻辑
CISCN CTF rthread.bin 逆向题

图片.png


第 16 行的 sub_5F4 的 if 语句需要成立
需要执行 sub_988C 函数,然后就双击不进去了,就很艰难
所以,我们换一种思路,从QEMU源码的角度来分析,QEMU是把该二进制文件rebase到了哪里呢?
[Asm] 纯文本查看 复制代码
https://github.com/qemu/qemu[url=https://github.com/qemu/qemu/tree/master/hw/arm]https://github.com/qemu/qemu/tree/master/hw/arm[/url][url=https://github.com/qemu/qemu/blob/master/hw/arm/boot.c]https://github.com/qemu/qemu/blob/master/hw/arm/boot.c[/url][url=https://github.com/qemu/qemu/blob/master/hw/arm/vexpress.c]https://github.com/qemu/qemu/blob/master/hw/arm/vexpress.c[/url]

[Asm] 纯文本查看 复制代码
qemu 中对于 arm 架构的 boot 启动方式[url=https://github.com/qemu/qemu/blob/master/hw/arm/boot.c]https://github.com/qemu/qemu/blob/master/hw/arm/boot.c[/url]Line 1079: /* 32-bit ARM */entry = info->loader_start + KERNEL_LOAD_ADDR;Line 35: #define KERNEL_LOAD_ADDR 0x00010000[url=https://github.com/qemu/qemu/blob/master/hw/arm/vexpress.c]https://github.com/qemu/qemu/blob/master/hw/arm/vexpress.c[/url]Line 339:static VEDBoardInfo a9_daughterboard = {    ……    .loader_start = 0x60000000,    ……};entry = 0x60010000

当没有 entry 的时候,IDA 里的字符串没有交叉引用的
CISCN CTF rthread.bin 逆向题

图片.png


设置 entry
CISCN CTF rthread.bin 逆向题

图片.png


CISCN CTF rthread.bin 逆向题

图片.png


CISCN CTF rthread.bin 逆向题

图片.png


CISCN CTF rthread.bin 逆向题

图片.png


CISCN CTF rthread.bin 逆向题

图片.png


顺着这个流程图,明显就能找到题中的 main 了
CISCN CTF rthread.bin 逆向题

图片.png


CISCN CTF rthread.bin 逆向题

图片.png


length = 0x28 = 40
长度不够,后续添加字符 'a',加上之前的 TEA 算法,就很容易搞明白程序的流程和逻辑了
该函数为输入flag后的程序函数,其首先会对输入的flag进行分组,每组两个int一共5组。
对key进行分组,每组4个int,一共3组。并对flag做5次tea加密。
[C++] 纯文本查看 复制代码
#include <bits/stdc++.h>using namespace std;#define UINT unsigned int#define DELTA 0x9e3779b9void tea_decrypt(UINT* v, UINT* key) {    UINT l = v[0], r = v[1], sum = 0;    sum = DELTA * 32;    for (size_t i = 0; i < 32; i++) {        r -= (((l << 4) ^ (l  5)) + l) ^ (sum + key[(sum  11) & 3]);        sum -= DELTA;        l -= (((r << 4) ^ (r  5)) + r) ^ (sum + key[sum & 3]);    }    v[0] = l;    v[1] = r;}UINT str2int(char* str){    UINT ret = 0;    for (int i = 0; i < 4; i++)        ret += pow(0x100, i) * str[i];    return ret;}void int2str(int num, char* str1){    char ch;    for (int i = 0; i < 4; i++)    {        ch = num & 0xff;        num = num  8;        str1[i] = ch;    }    return;}int main(){    char flag[100] = { 0 }, key[] = "dddwwawwwwaasdsasawawdwaaasawassssdwdsddssasddwa";    UINT keys[12], tea_cry[2], tea_key[4], cry[] = {3179062266, 2936962595, 3754839610, 2425968462, 1458506693, 3303317055, 1294083110, 1674144741, 1029754371, 3863932833};    for (int i = 0; i < 12; i++){        char newkey[4] = { 0 };        memcpy(newkey, key + i * 4, 4);        keys[i] = str2int(newkey);    }    for (int i = 0; i < 5; i++){        tea_cry[0] = cry[i * 2], tea_cry[1] = cry[i * 2 + 1];        for (int j = 0; j < 4; j++)            tea_key[j] = keys[(i * 4 + j) % 12];        tea_decrypt(tea_cry, tea_key);        cry[i * 2] = tea_cry[0], cry[i * 2 + 1] = tea_cry[1];    }    for (int i = 0; i < 10; i++)        cout << "0x" << hex << cry[i]<< " ";    cout << endl;    for (int i = 0; i < 10; i++)        int2str(cry[i], flag + i * 4);    cout << flag << endl;    return 0;}

结果为:
flag{932b424a9-9fe2-42d51-9403e-601db1baa5678}

一句话新闻

一文看懂荣耀MagicBook Pro 16
荣耀猎人回归!七大亮点看懂不只是轻薄本,更是游戏本的MagicBook Pro 16.
人们对于笔记本电脑有一个固有印象:要么轻薄但性能一般,要么性能强劲但笨重臃肿。然而,今年荣耀新推出的MagicBook Pro 16刷新了人们的认知——发布会上,荣耀宣布猎人游戏本正式回归,称其继承了荣耀 HUNTER 基因,并自信地为其打出“轻薄本,更是游戏本”的口号。
众所周知,寻求轻薄本的用户普遍更看重便携性、外观造型、静谧性和打字办公等用机体验,而寻求游戏本的用户则普遍更看重硬件配置、性能释放等硬核指标。把两个看似难以相干的产品融合到一起,我们不禁对它产生了强烈的好奇:作为代表荣耀猎人游戏本的跨界新物种,它究竟做了哪些平衡以兼顾不同人群的各类需求呢?