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