当前位置: 首页 > 工具软件 > RetDec > 使用案例 >

180821 逆向-周练babyre+Retdec配置

卫俊力
2023-12-01

mips题目,看起来有点难受
想起来前几天defcon的时候刚好把retdec的环境搭起来,虽然还是有点小问题,但是正好借机解决一下嘛

首先看了binary ninja的插件,跑了一下python缺少模块,又找不到它内置的python在哪,查了一下可以在binary ninja的script console窗口中import pip来安装

import pip
pip.main([‘install’, ‘–quiet’, ‘packagename’])

装好以后直接打不开了- =
幸亏有一颗debug的心,把另一个插件generate_index.py移除以后就行了..有点神奇

然后跑一下,log窗口报错架构不支持,明明就是Mips啊╮(╯_╰)╭

去找了init.py来看

self.cmdline = [‘retdec-decompiler.sh’]
self.cmdline.append(‘-m’)
self.cmdline.append(‘raw’)

self.cmdline.append(‘-a’)
self.cmdline.append(self.arch)

self.cmdline.append(‘-e’)
self.cmdline.append(self.endianness)

self.cmdline.append(‘–backend-no-debug-comments’)
self.cmdline.append(‘–cleanup’)

p = Popen(self.cmdline, stdout=PIPE, stderr=PIPE)

我这windows怎么用管道跑sh啊?!
这适配简直了……无奈放弃

回头继续搞IDA的插件
它依赖于msys的mingw程序,以前搞gcc的时候也装过一个Mingw的程序,可以在win上运行sh脚本,包括strings\grep等等小程序

IDA这边可以看到log都打完了,Run Decompile已经完成了,最后却报了一个exit code -1

最尴尬的是IDA起的cmd窗口在错误以后直接消失,根本看不到最后出错的log
所以说log是非常重要的orz

还好IDA的报错窗口把idapython的命令 system(sh’xxxx’)显示出来,因此可以在Mingw中手动运行该命令

Running phase: emission of the target code [c] ( 0.11s )
Running phase: finalization ( 0.12s )
Running phase: cleanup ( 0.13s )
/usr/bin/env: ‘python3’: No such file or directory

`##### Done!

可以看到,最后一条python3未找到就是报错的原因了
去retdec-decompiler.sh中搜了一下一个python也没有
最后看到开头

`#!/usr/bin/env bash

哦~是某个文件要求用python3来解释失败了
其实也可以直接在env中写入一个python3的,然而我不太会玩这东西..

试了一下发现MingW里有个python3.6,那么只要令这里的对应关系修复就可以了
到文件夹里找一下,果然有个retdec-color-c.py打开一看,第一行就/是>`#!/usr/bin/env python3

把3去掉,再跑一遍终于成功√

然而IDA里还是报错orz
明天再调试吧

此时命令行跑起来以后,文件夹下已经出现了.c文件,可以勉强用啦~

反编译效果不是很好,但是对于循环和参数的识别帮助比较大
例如main函数中的这段就很明显可以看出是逐字符check

while (true) {
        char v4 = *(char *)(v2 + v3); // 0x400d14
        int32_t v5 = v3 + 1; // 0x400d30
        if (*(char *)(v3 + (int32_t)&g2) != v4) {
            // 0x400d20
            exit(0);
            // UNREACHABLE
        }
        // 0x400d38
        if (v5 >= strlen((char *)v2)) {
            // break -> 0x400d58
            break;
        }
        v3 = v5;
        // continue -> 0x400cf4
    }

关键内容在于这之前的变换sub_400790中
这个函数看起来就很蛋疼了

int32_t sub_400790(char * a1, int32_t a2) {
    char * v1 = (char *)(int32_t)a1; // 0x4007a0
    int32_t v2 = strlen(v1); // 0x4007b0
    int32_t v3 = v2 + 3; // 0x4007c4
    int32_t v4 = v2 & -0x7ffffffd; // 0x4007ec
    int32_t v5 = v4; // 0x400808
    if (v4 <= 0xffffffff) {
        // 0x4007f8
        v5 = (v3 | -4) + 1;
        // branch -> 0x400808
    }
    char * v6 = malloc(3 * (v2 > -1 ? v2 : v3) / 4 + 1 + v5); // 0x400814
    *(int32_t *)a2 = (int32_t)v6;
    // branch -> 0x400bbc
    while (true) {
        char * v7 = v1; // 0x400bbc10
        // branch -> 0x400bbc
        char * v8;
        int32_t v9; // 0x400bc0
        char * v10; // 0x400bdc
        while (true) {
            char v11 = *v7; // 0x400bc0
            v9 = v11;
            v10 = (char *)((int32_t)v7 + 1);
            if (v11 == 0) {
                v8 = v6;
                // 0x400c00
                *v8 = 0;
                // branch -> 0x400c18
                // 0x400c18
                return (int32_t)v8 - a2;
            }
            // 0x400830
            if (isspace(v9) == 0) {
                // break -> 0x400844
                break;
            }
            v7 = v10;
            // continue -> 0x400bbc
        }
        unsigned char v12 = *(char *)(v9 + (int32_t)&g1); // 0x400864
        char * v13 = v10; // 0x40088c
        char v14 = *v13; // 0x400890
        int32_t v15 = v14; // 0x400890
        char * v16 = (char *)((int32_t)v13 + 1); // 0x4008a4
        // branch -> 0x40088c
        while (isspace(v15) != 0) {
            // 0x40088c
            v13 = v16;
            v14 = *v13;
            v15 = v14;
            v16 = (char *)((int32_t)v13 + 1);
            // continue -> 0x40088c
        }
        // 0x4008bc
        if (v14 == 0) {
            // 0x400c18
            return -1;
        }
        int32_t v17 = (int32_t)*(char *)(v15 + (int32_t)&g1); // 0x4008d8
        *v6 = (char)((0x100000 * v17 | 0x4000000 * (int32_t)v12) / 0x1000000);
        char * v18 = v16; // 0x400940
        char v19 = *v18; // 0x400944
        int32_t v20 = v19; // 0x400944
        char * v21 = (char *)((int32_t)v18 + 1); // 0x400958
        // branch -> 0x400940
        while (isspace(v20) != 0) {
            // 0x400940
            v18 = v21;
            v19 = *v18;
            v20 = v19;
            v21 = (char *)((int32_t)v18 + 1);
            // continue -> 0x400940
        }
        int32_t v22 = (int32_t)v6; // 0x400928
        char * v23 = (char *)(v22 + 1); // 0x400938
        if (v19 == 61) {
            char * v24 = v21; // 0x400984
            char v25 = *v24; // 0x400988
            char * v26 = (char *)((int32_t)v24 + 1); // 0x40099c
            while (isspace((int32_t)v25) != 0) {
                // 0x400984
                v24 = v26;
                v25 = *v24;
                v26 = (char *)((int32_t)v24 + 1);
                // continue -> 0x400984
            }
            // 0x4009b4
            if (v25 == 61) {
                char * v27 = v26; // 0x4009d4
                char v28 = *v27; // 0x4009d8
                while (isspace((int32_t)v28) != 0) {
                    // 0x4009d4
                    v27 = (char *)((int32_t)v27 + 1);
                    v28 = *v27;
                    // continue -> 0x4009d4
                }
                // 0x400a04
                if (v28 == 0) {
                    v8 = v23;
                    // 0x400c00
                    *v8 = 0;
                    // branch -> 0x400c18
                    // 0x400c18
                    return (int32_t)v8 - a2;
                }
            }
            // 0x400c18
            return -1;
        }
        char v29 = *(char *)(v20 + (int32_t)&g1); // 0x400a3c
        *v23 = (char)((0x400000 * (int32_t)v29 | 0x10000000 * v17) / 0x1000000);
        char * v30 = v21; // 0x400aa4
        char v31 = *v30; // 0x400aa8
        int32_t v32 = v31; // 0x400aa8
        char * v33 = (char *)((int32_t)v30 + 1); // 0x400abc
        // branch -> 0x400aa4
        while (isspace(v32) != 0) {
            // 0x400aa4
            v30 = v33;
            v31 = *v30;
            v32 = v31;
            v33 = (char *)((int32_t)v30 + 1);
            // continue -> 0x400aa4
        }
        char * v34 = (char *)(v22 + 2); // 0x400a9c
        if (v31 == 61) {
            char * v35 = v33; // 0x400ae8
            char v36 = *v35; // 0x400aec
            while (isspace((int32_t)v36) != 0) {
                // 0x400ae8
                v35 = (char *)((int32_t)v35 + 1);
                v36 = *v35;
                // continue -> 0x400ae8
            }
            // 0x400b18
            if (v36 != 0) {
                // 0x400c18
                return -1;
            }
            v8 = v34;
            // 0x400c00
            *v8 = 0;
            // branch -> 0x400c18
            // 0x400c18
            return (int32_t)v8 - a2;
        }
        char v37 = *(char *)(v32 + (int32_t)&g1); // 0x400b50
        *v34 = v37 | 64 * v29;
        v1 = v33;
        v6 = (char *)(v22 + 3);
        // branch -> 0x400bbc
    }
}

基本上看不出什么内容,但是有一些特征还是可以辅助猜测的
在中间找到了61,即’=’的ascii
有很多结构类似的代码,通过一些判断来选择跳转

综合考虑比较符合base64_decode
于是回到IDA中找到两个字符串,进行解码,就出现了flag

>>> a = b""
>>> for i in [142, 238, 109, 251, 137, 244, 182, 23, 171, 249, 182, 172, 123, 174, 62, 198, 138, 254, 34, 121, 254, 154, 42, 108]:
...     a += bytes((i,))
...
>>> a
b'\x8e\xeem\xfb\x89\xf4\xb6\x17\xab\xf9\xb6\xac{\xae>\xc6\x8a\xfe"y\xfe\x9a*l'
>>> import base64
>>> base64.b64encode(a)
b'ju5t+4n0ther+base64+xor+Inn+mips'

就是之前杭州安恒总决赛的mips题目~
当时依靠提示得到了这段字符串,但是由于格式提交失败了

这次终于独立做出来了=-=也算不虚折腾半天

retdec的反编译效果比IDA差的很大,基本无法单独阅读,主要还是靠汇编吧
不过jeb其实也差不多23333

 类似资料: