CTF逆向题

admin 2022年9月9日11:17:41评论46 views字数 2903阅读9分40秒阅读模式

CTF逆向题


CISCN - rtthread是一个非常新颖的好题
题目中给的是一个 sh 文件和一个类似固件的bin rtthread.bin
CTF逆向题
运行起来,啥也没有
尝试 ?、help 等,看看会给我们提供什么信息
CTF逆向题
里面有一些提供的命令,比如 ifconfig,date 等信息

CTF逆向题CTF 题目当然就会想要追求 flag,看到最前面的两个命令
CTF逆向题
可以看到是作者自定义的一个广告位置,真有意思~~~
然后尝试 get_flag 这个命令,得到一个迷宫

CTF逆向题

如果瞎输入的话,就是会报错的

CTF逆向题
不是上下左右键的话,就是 WASD 呗(多年来打小霸王游戏机的经验)
合理的猜想就是从 S(Start)点上下左右走到F(Finish)点
很多条可达的路径,通过 Oops 的方式 ban 掉了很多条,当然就只留下来了唯一确定的可行字符串
CTF逆向题
输入的字符串为:
dddwwawwwwaasdsasawawdwaaasawassssdwdsddssasddw
CTF逆向题
首先是判断长度,再是判断逻辑
ok,到了这里就需要开始逆向了!
CTF逆向题
CTF逆向题

可以发现,字符串是没有交叉引用的
不过既然函数不是很多,可以手动 F5 去看特征
CTF逆向题
这个是典型的常数值:0x61C88647、0xC6EF3720:典型的 TEA 算法特征
CTF逆向题
5F4 这个函数是递归,根据输入来处理地图中的迷宫的
CTF逆向题
可以看到这里的 sub_798 是 sub_5F4 的上层函数
根据 sub_798 的逻辑
CTF逆向题
第 16 行的 sub_5F4 的 if 语句需要成立
需要执行 sub_988C 函数,然后就双击不进去了,就很艰难

所以,我们换一种思路,从QEMU源码的角度来分析,QEMU是把该二进制文件rebase到了哪里呢?


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]


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 里的字符串没有交叉引用的

CTF逆向题
设置 entry
CTF逆向题
CTF逆向题


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

length = 0x28 = 40

长度不够,后续添加字符 'a',加上之前的 TEA 算法,就很容易搞明白程序的流程和逻辑了
该函数为输入flag后的程序函数,其首先会对输入的flag进行分组,每组两个int一共5组。
对key进行分组,每组4个int,一共3组。

并对flag做5次tea加密。


#include <bits/stdc++.h>using namespace std; #define UINT unsigned int#define DELTA 0x9e3779b9 void 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}

该内容转载自网络,更多内容请点击“阅读原文”

CTF逆向题



原文始发于微信公众号(web安全工具库):CTF逆向题

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年9月9日11:17:41
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   CTF逆向题http://cn-sec.com/archives/1287141.html

发表评论

匿名网友 填写信息