Mips架构逆向初探
0x00-Mips指令架构
MIPS架构(英语:MIPS architecture,为Microprocessor without interlocked piped stages architecture的缩写,亦为Millions of Instructions Per Second的双关语),是一种采取精简指令集(RISC)的处理器架构,1981年出现,由MIPS科技公司开发并授权,广泛被使用在许多电子产品、网络设备、个人娱乐装置与商业装置上。最早的MIPS架构是32位,最新的版本已经变成64位。
使用linux下的readelf命令可以了解到文件相关信息
0x01-环境安装
由于程序是MIPS指令架构的,而通常我们使用的电脑是x86架构的,无法直接运行该程序,这时可以借助Qemu模拟器来运行程序。QEMU是运行在用户层的开源全虚拟化解决方案,可以在Intel机器上虚拟出完整的操作系统。QEMU主要有两种运作方式
User Mode:即使用者模式,能单独运行那些为不同处理编译的Linux程序
System Mode:即系统模式,能够模拟整个操作系统,包括中央处理器及其他周边设备
由于BabyMips程序是通过静态链接生成的,为了方便,在User Mode下使用QEMU来运行该程序
使用下面的命令来安装QEMU
1 2 sudo apt install qemu- user - static sudo apt install qemu- user
安装qemu对应下的mips64库
1 sudo apt install libc6 -mips64 -cross
0x01-DDCTF2018-BabyMips
静态分析
readelf读取文件信息-Mips32-小端序
运行试试
出现错误
先使用Ghidra查看反编译代码,也可以使用ida7.5即以上版本反编译,也可以使用jeb-mips
可以看到先让我们输入,然后进入函数进行判断,所以我们需要知道函数进行了什么加密操作
进入函数后发现分析出错了,在最后跳转时跳转到了垃圾数据的位置,所以我们试一下动态调试
动态调试
ida+QEMU调试
首先在ida中选择Remote GDB Debugger
然后Debugger设置好
连接
1 qemu -mipsel -g 23946 Baby_Mips
-g后面跟着端口号+文件名
端口的另一边可以选择IDA也可以选择GDB,这里我选择DIA
在IDA中启动调试
成功断下
接下来定位到刚才出错的地址,下个断点
放开程序
输入完成后,提示出错
F8也会出现异常
查找lwc1
指令的含义,发现是与协处理器相关的指令。通过对后面的代码块进行分析发现,后面并没有用到$f29
和$t1
寄存器的内容
也就是说E8本来是8位,也就是两个字节,但是mips指令为4字节,所以跳转的时候出错了
使用idc进行Patch
注意idc不支持+=操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include <idc.idc> static main () { auto addr=0x4001F0 ; auto addr1=0x403234 ; for (;addr<=addr1;addr=4 +addr) { if (Byte(addr)==0xeb && Byte(addr+1 )==0x02 ) { PatchByte(addr,0x00 ); PatchByte(addr+1 ,0x00 ); PatchByte(addr+2 ,0x00 ); PatchByte(addr+3 ,0x00 ); } } }
保存之后重新拖进jeb反编译
脚本
十六个方程组,使用z3求解
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 26 27 28 29 30 31 32 33 #!/usr/bin/env python from z3 import * a = [BitVec('a%d' %i, 32 ) for i in range(16 )] s = Solver() s.add(0xffffc20e *a[0 ]-0xbd52 *a[1 ]+0x7f57 *a[2 ]+0x96cd *a[3 ]-0xac7f *a[4 ] +0x5d80 *a[5 ]+0xb25e *a[6 ]+0x2447 *a[7 ]+0xba8a *a[8 ]+0xbb41 *a[9 ]+0xa3a8 *a[10 ]+0xcb12 *a[11 ]-0x6958 *a[12 ]+0x5821 *a[13 ]+0x77ed *a[14 ]+0xf7ff *a[15 ] == 0x162f0ca ) s.add(0xeb44 *a[0 ]-0x0f99 *a[1 ] - 0x40e7 *a[2 ] +0xdf2e *a[3 ] -0x4b2e *a[4 ] -0x96b5 *a[5 ] +0x9d66 *a[6 ] -0xafa8 *a[7 ] -0x6e26 *a[8 ] -0xe655 *a[9 ]- 0x9a6e *a[10 ] +0x57ba *a[11 ] -0x227c *a[12 ] +0xbdd1 *a[13 ] +0xb437 *a[14 ] +0x5d3f *a[15 ]== 0xffec2e48 ) s.add(0xe6f1 *a[0 ] +0xa4b2 *a[1 ] -0xfe74 *a[2 ] -0x0f07 *a[3 ] -0x5d22 *a[4 ] -0xb845 *a[5 ] -0x9954 *a[6 ] +0x93ac *a[7 ] -0x51e4 *a[8 ] -0x4b11 *a[9 ] +0xdc93 *a[10 ] +0x13f8 *a[11 ] +0x246c *a[12 ] +0xf121 *a[13 ] +0xf09f *a[14 ] +0x0dfa *a[15 ] == 0xd3c060 ) s.add(0xffff7085 *a[0 ] -0x6623 *a[1 ] +0x0686 *a[2 ] +0x4b2d *a[3 ] +0x68df *a[4 ] +0x9be7 *a[5 ] +0x21b4 *a[6 ] +0xe25a *a[7 ] -0xc807 *a[8 ] +0xf695 *a[9 ] -0x5421 *a[10 ] -0x2469 *a[11 ] +0x9f29 *a[12 ] -0xe311 *a[13 ] +0x78f2 *a[14 ] -0x6bda *a[15 ] == 0x8bf576 ) s.add(0xffff07b8 *a[0 ] -0xd048 *a[1 ] -0x85f1 *a[2 ] +0xee84 *a[3 ] -0x37d1 *a[4 ] +0xb74a *a[5 ] +0xcfe2 *a[6 ]+ 0x8f1e *a[7 ] -0xf211 *a[8 ] -0x83bf *a[9 ] -0x1249 *a[10 ] +0x7ea7 *a[11 ] -0x4294 *a[12 ] -0xb661 *a[13 ] -0x8a73 *a[14 ] -0x5e5c *a[15 ] == 0xff4ea5b3 ) s.add(0xffffd6b5 *a[0 ] -0x2b5f *a[1 ]+ 0xc981 *a[2 ] -0x60c3 *a[3 ] +0xf8f2 *a[4 ]+ 0xded7 *a[5 ]- 0xf6fb *a[6 ] +0x1083 *a[7 ]- 0xdc96 *a[8 ]- 0x587e *a[9 ] -0xb4f5 *a[10 ] +0xf57a *a[11 ] +0x57d0 *a[12 ] +0xe814 *a[13 ] +0x6169 *a[14 ] +0xf285 *a[15 ] == 0x9dd61e ) s.add(0xcd89 *a[0 ] -0xd43d *a[1 ] +0xf037 *a[2 ] +0x83a8 *a[3 ] -0xa305 *a[4 ] -0xadef *a[5 ] +0xcaaa *a[6 ] -0xf145 *a[7 ]- 0x6073 *a[8 ]- 0x2777 *a[9 ] +0x794f *a[10 ] +0xf00e *a[11 ] -0xe7d5 *a[12 ] +0x2654 *a[13 ] -0xbed0 *a[14 ] -0xb8af *a[15 ] == 0xff6baab3 ) s.add(0xffff6108 *a[0 ] -0x6766 *a[1 ] +0xd58e *a[2 ] -0x5ca3 *a[3 ] +0x2718 *a[4 ] +0x1e2b *a[5 ] -0xf49e *a[6 ] +0xcf78 *a[7 ] +0x7c09 *a[8 ] -0x13b7 *a[9 ] -0xbeee *a[10 ]- 0xe450 *a[11 ] +0x4da3 *a[12 ] -0x8880 *a[13 ] -0x5691 *a[14 ] +0x8bd8 *a[15 ] == 0xff818f06 ) s.add(0xffffa564 *a[0 ] -0xa95a *a[1 ] -0xe643 *a[2 ] +0x0d38 *a[3 ] -0x097a *a[4 ] -0xeb22 *a[5 ] +0xcac3 *a[6 ] -0x4ed1 *a[7 ] -0x7c8a *a[8 ] +0xf107 *a[9 ] +0xa59e *a[10 ]- 0x1213 *a[11 ] +0xb2b5 *a[12 ] -0x7213 *a[13 ] -0x2b83 *a[14 ] -0xa155 *a[15 ] == 0xff8d50e7 ) s.add(0xffff6c45 *a[0 ] -0x2752 *a[1 ] -0xbdc3 *a[2 ] -0xf495 *a[3 ] -0x7121 *a[4 ] +0x9c41 *a[5 ] -0x9465 *a[6 ]- 0x6ce3 *a[7 ] -0x4f28 *a[8 ] -0x8350 *a[9 ] -0x176e *a[10 ] +0x7814 *a[11 ] -0x739a *a[12 ] +0x5494 *a[13 ] +0x142d *a[14 ] +0xca55 *a[15 ] == 0xff3f9826 ) s.add(0xcf01 *a[0 ] +0xf378 *a[1 ] +0x1064 *a[2 ] -0xd9a7 *a[3 ] -0x077d *a[4 ]+ 0x6dab *a[5 ] -0xaf1f *a[6 ]- 0x3db7 *a[7 ] +0x3554 *a[8 ] -0xcb8e *a[9 ] -0x9815 *a[10 ]+ 0xf30b *a[11 ] +0x9c5e *a[12 ] -0x5d07 *a[13 ] -0x4c31 *a[14 ] +0xeae0 *a[15 ] == 0x213fed ) s.add(0x8bd4 *a[0 ] -0x6d81 *a[1 ] -0xe772 *a[2 ] +0xb6f1 *a[3 ] +0x9b57 *a[4 ] -0x597d *a[5 ] +0x15d1 *a[6 ]- 0xa55e *a[7 ]+ 0xfd13 *a[8 ]+ 0x17b4 *a[9 ] +0xec78 *a[10 ] -0xd51a *a[11 ] +0x56ad *a[12 ] -0xc319 *a[13 ] +0x9f8e *a[14 ] +0xfa17 *a[15 ] == 0xa9f0dc ) s.add(0xffffb798 *a[0 ] -0x8bef *a[1 ] +0x109d *a[2 ]- 0xf9d4 *a[3 ] +0x4ecf *a[4 ] +0xa896 *a[5 ] +0x773b *a[6 ] +0x6e8a *a[7 ] -0x737c *a[8 ]+ 0x4979 *a[9 ] +0xc685 *a[10 ] -0x96ae *a[11 ] +0x0bbd *a[12 ] +0x8280 *a[13 ] +0xe3a9 *a[14 ] -0x730c *a[15 ] == 0xbdeb20 ) s.add(0x0b20 *a[0 ] +0x9b9c *a[1 ] +0xb4aa *a[2 ]+ 0x6176 *a[3 ] +0x9670 *a[4 ] +0x7c9d *a[5 ] -0x5402 *a[6 ] -0x8cd2 *a[7 ] +0xac82 *a[8 ] +0xa2f5 *a[9 ] -0x8efd *a[10 ] -0x65f1 *a[11 ] -0x94b9 *a[12 ] +0x8cb8 *a[13 ] +0x1cb5 *a[14 ] +0x4aa1 *a[15 ] == 0x9c7cf5 ) s.add(0x57fd *a[0 ] +0x3d83 *a[1 ] +0xf745 *a[2 ] +0xa5c4 *a[3 ] -0x65fa *a[4 ] -0x58e9 *a[5 ] +0xbebe *a[6 ] +0x1820 *a[7 ] -0xd7b9 *a[8 ] -0xb21f *a[9 ] -0x76a0 *a[10 ] +0xc60d *a[11 ] +0x168f *a[12 ] +0x2a96 *a[13 ] +0x31d6 *a[14 ] -0x4b88 *a[15 ] == 0xd08e2 ) s.add(0xffff1bae *a[0 ] -0xc7d4 *a[1 ] -0x1554 *a[2 ] +0x7eea *a[3 ] -0x684d *a[4 ] +0x6adb *a[5 ] +0x8534 *a[6 ] -0x3a36 *a[7 ] +0x29f0 *a[8 ] +0xd3f2 *a[9 ] -0x23e5 *a[10 ] -0x6540 *a[11 ] +0xbcd3 *a[12 ] -0xef9b *a[13 ] +0xefdb *a[14 ] -0x774e *a[15 ] == 0x178803 ) for item in a: s.add(item > 0 , item < 127 ) if s.check() == sat: m = s.model() flag = [] for i in range(16 ): flag.append(m[a[i]].as_long()) print(''.join(map(chr, flag)))
注意负数要换成十六进制
参考
https://blog.csdn.net/m0_46362499/article/details/107629918
https://cloud.tencent.com/developer/article/1123681
https://cq674350529.github.io/2018/05/07/Solve-baby-mips-with-angr/