MIPS合集

MIPS合集

(阶段性输出)遇到的MIPS题目放一起啦

  • DDCTF2018 baby_mips
  • SUCTF2018 babyre
  • QCTF2018 Xman_mips

MIPS简介

待施工

工具的使用

待施工

题目

DDCTF2018 baby_mips

这道题目的解题思路比较常规,通过调试发现花指令并修改,然后分析它的算法得出最终解。重在了解MIPS指令集,并且熟悉MIPS的反编译工具jeb或者retdec。
  • 前期准备

    在Ubuntu上看到该程序是一个mips32位的程序,无法直接执行,所以在Linux上搭建一个qemu运行这个程序。
    
  • 修改花指令

    用qemu+jeb动态调试代码,要注意这个baby_mips是小端序,执行时不能直接qemu-mips。
    
    1
    2
    qemu-mipsel baby_mips //执行baby_mips
    qemu-mipsel -g 2359 baby_mips//监听2359端口
    用IDA开动态调试,观察发生段错误的指令,‘\xEB02’开头,往后面翻可以看到很多无法解析的二进制也有’\xEB02‘,‘\xEB’在x86指令集中指的是”jmp 后面的两个字节是偏移“,‘\xEB02’就是指向后跳转两字节。
    
    mips指令集是一个定长指令集,大小为四字节,我们可以大胆的猜测,‘\xEB02’就是一个简单的花指令,于是编写代码去花。下面是去花用的python代码
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    import os
    f = open("baby_mips","rb")
    content = f.read()
    f.close()
    content = list(content)
    for x in range(0,len(content)):
    if content[x] == "\xeb" and content[x+1] == "\x02" and (x%4==0):
    content[x] = "\x00"
    content[x+1] = "\x00"
    content[x+2] = "\x00"
    content[x+3] = "\x00"
    content = "".join(content)
    p = open("patch","wb")
    p.write(content)
    p.close()
  • 分析算法得解

    用IDA插件retdec反编译去花后的程序,是一个16元一次方程。
    
    然后编写一个python脚本解方程组,
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    import numpy as np
    from scipy.linalg import solve
    A=[
    [-15858,-48466,32599,38605,-44159,23939,45662,9287,47754,47937,41896,51986,-26968,22561,30701,63487],
    [60228,-3993,-16615,57134,-19246,-38581,40294,-44968,-28198,-58965,-39534,22458,-8828,48593,46135,23871],
    [59121,42162,-65140,-3847,-23842,-47173,-39252,37804,-20964,-19217,56467,5112,9324,61729,61599,3578],
    [-36731,-26147,1670,19245,26847,39911,8628,57946,-51207,63125,-21537,-9321,40745,-58129,30962,-27610],
    [-63560,-53320,-34289,61060,-14289,46922,53218,36638,-61969,-33727,-4681,32423,-17044,-46689,-35443,-24156],
    [-10571,-11103,51585,-24771,63730,57047,-63227,4227,-56470,-22654,-46325,62842,22480,59412,24937,62085],
    [52617,-54333,61495,33704,-41733,-44527,51882,-61765,-24691,-10103,31055,61454,-59349,9812,-48848,-47279],
    [-40696,-26470,54670,-23715,10008,7723,-62622,53112,31753,-5047,-48878,-58448,19875,-34944,-22161,35800],
    [-23196,-43354,-58947,3384,-2426,-60194,51907,-20177,-31882,61703,42398,-4627,45749,-29203,-11139,-41301],
    [-37819,-10066,-48579,-62613,-28961,40001,-37989,-27875,-20264,-33616,-5998,30740,-29594,21652,5165,51797],
    [52993,62328,4196,-55719,-1917,28075,-44831,-15799,13652,-52110,-38933,62219,40030,-23815,-19505,60128],
    [35796,-28033,-59250,46833,39767,-22909,5585,-42334,64787,6068,60536,-54554,22189,-49945,40846,64023],
    [-18536,-35823,4253,-63956,20175,43158,30523,28298,-29564,18809,50821,-38574,3005,33408,58281,-29452]
    [2848,39836,46250,24950,38512,31901,-21506,-36050,44162,41717,-36605,-26097,-38073,36024,7349,19105],
    [22525,15747,63301,42436,-26106,-22761,48830,6176,-55225,-45599,-30368,50701,5775,10902,12758,-19336],
    [-58450,-51156,-5460,32490,-26701,27355,34100,-14902,10736,54258,-9189,-25920,48339,-61339,61403,-30542]
    ]
    B=[23261386,-1298872,13877344,9172342,-11622989,10343966,-9721165,-8286458,-7515929,-12609498,2179053,11137244,12446496,10255605,854242,1542147
    a = np.array(A)
    b = np.array(B)
    x =solve(a,b)
    print(x)
    求解python得到解答如下,四舍五入输入程序得到flag
    

    SUCTF2018 babyre

    • 分析代码算法

      我们看到main函数中的主要流程是对输入字符串进行检测,首先经过sub_400780函数进行处理,然后对处理过的字符串进行匹配。sub_400780函数是一个base64编码的函数,它对转换表进行了替换。
      
    • 编写程序求解

      先把对比字符串数据扣下来,用C代码转换成可见字符串
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14

#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
char arr[] = { 101, 81, 52, 121, 52, 54, 43, 86, 117, 102, 90, 122, 100, 70, 78, 70, 100, 120, 48, 122, 117, 100, 115, 97, 43, 121, 89, 48, 43, 74, 50, 109 };
//char arr[] = { 82,57,76,121,54,78,111,74,118,115,73,80,110,87,104,69,84,89,116,72,101,52,83,100,108,43,77,98,71,117,106,97,90,112,107,49,48,50,119,75,67,114,55,47,79,68,103,53,122,88,65,70,113,81,102,120,66,105,99,86,51,109,56,85,0 };
int i = 0;
while (arr[i]) {
printf("%c", arr[i]);
i++;
}
}

运行结果如下

1
eQ4y46+VufZzdFNFdx0zudsa+yY0+J2m

把替换字符串数据也扣下来,用如上C代码转换,结果如下

1
R9Ly6NoJvsIPnWhETYtHe4Sdl+MbGujaZpk102wKCr7/ODg5zXAFqQfxBicV3m8U

然后用python编写base64的解码代码

1
2
3
4
5
6
7
import string
import base64
my_base64table = "R9Ly6NoJvsIPnWhETYtHe4Sdl+MbGujaZpk102wKCr7/0Dg5zXAFqQfxBicV3m8U"
std_base64table ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
s = "eQ4y46+VufZzdFNFdx0zudsa+yY0+J2m"
s = s.translate(string.maketrans(my_base64table,std_base64table))
print base64.b64decode(s)

运行得到结果如下

1
SUCTF{wh0_1s_{0ur_d4ldy}

QCTF2018 Xman_babymips

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include<stdio.h>
int main()
{
char* arr = "Q|j{g";
unsigned char arr2[] = { 0x52,0xFD,0x16,0xA4,0x89,0xBD,0x92,0x80,0x13,0x41,0x54,0xA0,0x8D,0x45,0x18,0x81,0xDE,0xFC,0x95,0xF0,0x16,0x79,0x1A,0x15,0x5B,0x75,0x1F };
int i = 0;
for (i; i < 5; i++) {
printf("%c", arr[i]^(32-i));
}
for (i = 0; i < 27; i++) {
int temp = i + 5;
if (temp % 2 == 0) {
int t = arr2[i] % 4;
arr2[i] = arr2[i] / 4;
arr2[i] = arr2[i] +t*64;
printf("%c", arr2[i] ^(32-temp));
}
else {
int t = arr2[i] /64;
arr2[i] = arr2[i] %64;
arr2[i] = arr2[i]*4 + t;
printf("%c", arr2[i] ^ (32 - temp));
}
}
}

运行结果如下

1
qctf{ReA11y_4_B@89_mlp5_4_XmAn_}
0%