mips指令集不同,而且ida F5不支持,分析时把自动注释打开挺好用的
在本文中主要使用了retdec
ida插件:https://github.com/avast-tl/retdec-idaplugin
retdec: https://github.com/avast-tl/retdec/releases
(这插件没装明白,一直报错,所以我没用。。。)
使用方法
$ retdec-decompiler.sh test.exe
[QCTF2018]Xman-babymips
int32_t function_4009a8(void) { // 0x4009a8 setbuf(g6, NULL); setbuf(g7, NULL); printf("Give me your flag:"); int32_t str = 0; // bp-44 scanf("%32s", &str); int32_t v1 = 0; // bp-48 int32_t v2 = 0; // 0x400a58 char * v3 = (char *)(v2 + (int32_t)&v1 + 4); // 0x400a28 *v3 = (char)((int32_t)*v3 ^ 32 - v2); int32_t v4 = v1 + 1; // 0x400a70 v1 = v4; // branch -> 0x400a1c while (v4 < 32) { // 0x400a1c v2 = v4; v3 = (char *)(v2 + (int32_t)&v1 + 4); *v3 = (char)((int32_t)*v3 ^ 32 - v2); v4 = v1 + 1; v1 = v4; // continue -> 0x400a1c } int32_t str2 = *(int32_t *)&g8; // 0x400a90 int32_t puts_rc; if (strncmp((char *)&str, (char *)str2, 5) == 0) { // 0x400ab4 puts_rc = function_4007f0((char *)&str); // branch -> 0x400adc } else { // 0x400acc puts_rc = puts("Wrong"); // branch -> 0x400adc } // 0x400adc return puts_rc; }
int32_t function_4007f0(char * a1) { int32_t v1 = (int32_t)a1; // 0x400800 char * str = (char *)v1; // 0x400800 int32_t puts_rc; int32_t str2; // 0x400944 if (strlen(str) <= 5) { // 0x400934 str2 = *(int32_t *)&g9; if (strncmp((char *)(v1 + 5), (char *)str2, 27) == 0) { // 0x400964 puts_rc = puts("Right!"); // branch -> 0x40098c } else { // 0x40097c puts_rc = puts("Wrong!"); // branch -> 0x40098c } // 0x40098c return puts_rc; } int32_t v2 = 5; while (true) { char * v3 = (char *)(v2 + v1); // 0x4008a8 int32_t v4 = (int32_t)*v3; // 0x4008a8 char v5; if (v2 % 2 == 0) { char v6 = *v3; // 0x4008cc v5 = (int32_t)v6 / 64 | 0x4000000 * v4 / 0x1000000; // branch -> 0x400900 } else { // 0x400828 v5 = 64 * (int32_t)*v3 | v4 / 4; // branch -> 0x400900 } // 0x400900 *v3 = v5; int32_t v7 = v2 + 1; // 0x400908 if (v7 >= strlen(str)) { // break -> 0x400934 break; } v2 = v7; // continue -> 0x400814 } // 0x400934 str2 = *(int32_t *)&g9; if (strncmp((char *)(v1 + 5), (char *)str2, 27) == 0) { // 0x400964 puts_rc = puts("Right!"); // branch -> 0x40098c } else { // 0x40097c puts_rc = puts("Wrong!"); // branch -> 0x40098c } // 0x40098c return puts_rc; }
反编译效果一般,不过比指令好多了。。。
可以分析得到逻辑,用到的数据可结合ida获得
[UTCTF2020]babymips
int main(int argc, char ** argv) { // 0x400de8 int32_t v1; // bp-152 _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1Ev((int32_t)&v1); int32_t v2; // bp-104 int32_t v3; // bp-128 function_401164((int32_t)&v2, (int32_t)&v3, 84); int32_t v4 = *(int32_t *)g4; // 0x400f40 return *(int32_t *)g4 == v4 ? 0 : g1; } // Address range: 0x401164 - 0x401334 int32_t function_401164(int32_t a1, int32_t a2, int32_t a3) { // 0x401164 if (_ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE4sizeEv(a2) == 78) { // 0x4011fc if (*(int32_t *)0x4120a0 != 0) { int32_t v1 = 0; // branch -> 0x40122c while (true) { char v2 = *(char *)(v1 + a1); // 0x401274 if (((int32_t)*g3 ^ v1 + 23) != (int32_t)v2) { // 0x401288 // branch -> 0x40131c // 0x40131c return g2; } int32_t v3 = v1 + 1; // 0x4012d0 if (v3 >= *(int32_t *)0x4120a0) { // break -> 0x4012e0 break; } v1 = v3; // continue -> 0x40122c } // 0x4012e0 // branch -> 0x40131c // 0x40131c return g2; }
可以看到是个简单的异或,并且用这段数据比对
a="62 6C 7F 76 7A 7B 66 73 76 50 52 7D 40 54 55 79 40 49 47 4D 74 19 7B 6A 42 0A 4F 52 7D 69 4F 53 0C 64 10 0F 1E 4A 67 03 7C 67 02 6A 31 67 61 37 7A 62 2C 2C 0F 6E 17 00 16 0F 16 0A 6D 62 73 25 39 76 2E 1C 63 78 2B 74 32 16 20 22 44 19" a=a.split() for i in range(len(a)): print(chr(eval("0x"+a[i])^(i+23)),end="")
#utflag{mips_cpp_gang_5VDm:~`N]ze;)5%vZ=C'C(r#$q=*efD"ZNY_GX>6&sn.wF8$v*mvA@'}
这个flag是我目前见过最丑的了,我一度怀疑自己有什么地方做错了。。。
[CISCN2018]2ex
这题文件比前几个大,符号表也没有,看着挺困难,先拖进ida
.text:0040020C loc_40020C: # CODE XREF: start+4↑j
.text:0040020C li $gp, 0x429EA0 # Load Immediate
.text:00400214 move $ra, $zero
.text:00400218 la $a0, sub_400788 # Load Address
.text:0040021C lw $a1, arg_0($sp) # Load Word
.text:00400220 addiu $a2, $sp, arg_4 # Add Immediate Unsigned
.text:00400224 li $at, 0xFFFFFFF8 # Load Immediate
.text:00400228 and $sp, $at # AND
.text:0040022C addiu $sp, -0x20 # Add Immediate Unsigned
.text:00400230 la $a3, sub_400128 # Load Address
.text:00400234 la $t0, sub_4101B0 # Load Address
.text:00400238 sw $t0, 0x20+var_10($sp) # Store Word
.text:0040023C sw $v0, 0x20+var_C($sp) # Store Word
.text:00400240 sw $sp, 0x20+var_8($sp) # Store Word
.text:00400244 la $t9, sub_4013D8 # Load Address
.text:00400248 bal sub_4013D8 # Branch Always and Link
入口函数用了sub_4013D8,,参数有sub_400788,sub_400128,sub_4101B0
用retdec反编译一下,发现主要应分析sub_400788
int32_t function_400788(void) {
// 0x400788
int32_t v1; // bp-80
g5 = &v1;
g80 = g27;
int32_t v2 = 0; // bp-56
function_400840((char *)&v2);
int32_t v3; // bp-36
int32_t v4 = &v3; // 0x4007c0
g80 = g28;
function_4010f0(v4, 25);
function_400430((int32_t)&v2, 17, v4);
g80 = g29;
function_4009c0(v4);
return 0;
}
这里调用了四个函数,运行程序发现,程序获取一个输入后输出密文,所以假设,
function_4009c0(v4)为输出函数,v4为密文
function_400840((char *)&v2)为输入函数,v2为输入
function_400430((int32_t)&v2, 17, v4)为加密函数,v2加密后存在v4里
接下来分析function_400430((int32_t)&v2, 17, v4)
int32_t function_400430(int32_t a1, int32_t a2, int32_t a3) {
g2 = a2;
uint32_t v1 = g2; // 0x400440
int32_t v2 = 0;
int32_t v3 = -1;
if (v1 != 0) {
int32_t v4 = 0; // 0x40061019
int64_t v5 = 0;
int32_t v6 = 0;
// branch -> 0x40045c
int32_t v7;
while (true) {
uint64_t v8 = 0xaaaaaaab * (v5 & 0xffffffff) / 0x200000000; // 0x40047010
int32_t v9 = v4 - (int32_t)v8 - (int32_t)(2 * v8); // 0x400480
int32_t v10; // 0x400608
if (v9 == 1) {
int32_t v11 = 16 * (int32_t)*(char *)(v4 - 1 + a1) & 48; // 0x400524
int32_t v12 = (int32_t)(*(char *)(a1 + v4) / 16) | v11; // 0x400544
char v13 = *(char *)(v12 + (int32_t)"@,.1fgvw#`/2ehux$~"3dity%_;4cjsz^+{5bkrA&=}6alqB*-[70mpC()]89noD/dev/null"); // 0x400554
*(char *)(v6 + a3) = v13;
v7 = v6 + 1;
// branch -> 0x400604
lab_0x400604_2:
// 0x400604
v10 = v4 + 1;
if (v10 >= v1) {
// break -> 0x400610
break;
}
v4 = v10;
v5 = v10;
v6 = v7;
// continue -> 0x40045c
continue;
} else {
// 0x400498
v7 = v6;
switch (v9) {
case 2: {
int32_t v14 = 4 * (int32_t)*(char *)(v4 - 1 + a1) & 60; // 0x400590
g2 = a1;
int32_t v15 = (int32_t)(*(char *)(a1 + v4) / 64) | v14; // 0x4005b0
char v16 = *(char *)(v15 + (int32_t)"@,.1fgvw#`/2ehux$~"3dity%_;4cjsz^+{5bkrA&=}6alqB*-[70mpC()]89noD/dev/null"); // 0x4005c0
*(char *)(v6 + a3) = v16;
int32_t v17 = (int32_t)(*(char *)(a1 + v4) % 64); // 0x4005ec
char v18 = *(char *)(v17 + (int32_t)"@,.1fgvw#`/2ehux$~"3dity%_;4cjsz^+{5bkrA&=}6alqB*-[70mpC()]89noD/dev/null"); // 0x4005fc
*(char *)(a3 + 1 + v6) = v18;
v7 = v6 + 2;
// branch -> 0x400604
goto lab_0x400604_2;
}
case 0: {
int32_t v19 = (int32_t)(*(char *)(a1 + v4) / 4); // 0x4004d0
char v20 = *(char *)(v19 + (int32_t)"@,.1fgvw#`/2ehux$~"3dity%_;4cjsz^+{5bkrA&=}6alqB*-[70mpC()]89noD/dev/null"); // 0x4004e8
*(char *)(v6 + a3) = v20;
v7 = v6 + 1;
// branch -> 0x400604
goto lab_0x400604_2;
}
}
// 0x400604
v10 = v4 + 1;
if (v10 >= v1) {
// break (via goto) -> 0x400610
goto lab_0x400610;
}
v4 = v10;
v5 = v10;
v6 = v7;
// continue -> 0x40045c
continue;
}
}
lab_0x400610:
// 0x400610
v2 = v7;
v3 = v1 - 1;
// branch -> 0x400624
}
uint64_t v21 = 0xaaaaaaab * (int64_t)v3 / 0x200000000; // 0x4006442
int32_t v22 = v3 - ((int32_t)(2 * v21) + (int32_t)v21); // 0x400654
if (v22 == 0) {
int32_t v23 = 16 * (int32_t)*(char *)(a1 + v3) & 48; // 0x400688
char v24 = *(char *)(v23 + (int32_t)"@,.1fgvw#`/2ehux$~"3dity%_;4cjsz^+{5bkrA&=}6alqB*-[70mpC()]89noD/dev/null"); // 0x400698
*(char *)(v2 + a3) = v24;
*(char *)(a3 + 1 + v2) = 61;
g82 = 61;
*(char *)(a3 + 2 + v2) = 61;
// branch -> 0x400770
} else {
// 0x4006e0
g82 = v22;
if (v22 == 1) {
int32_t v25 = 4 * (int32_t)*(char *)(a1 + v3) & 60; // 0x40073c
char v26 = *(char *)(v25 + (int32_t)"@,.1fgvw#`/2ehux$~"3dity%_;4cjsz^+{5bkrA&=}6alqB*-[70mpC()]89noD/dev/null"); // 0x40074c
*(char *)(v2 + a3) = v26;
g82 = 61;
*(char *)(a3 + 1 + v2) = 61;
// branch -> 0x400770
}
}
// 0x400770
return 0;
}
可以看出来就是个换表base64
import base64
c="│_r-+_Cl5;vgq_pdme7#7eC0="
flag=""
table="@,.1fgvw#`/2ehux$~"3dity%_;4cjsz^+{5bkrA&=}6alqB*-[70mpC()]89noD"
table2="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
for i in c:
for j in range(len(table)):
if i==table[j]:
flag+=table2[j]
flag=base64.b64decode(flag)
print(flag)