复现 | RCTF2020逆向cipher

本文作者:rookiedrag*(二进制逆向星球学员)

最近学习用了一下ghidra !

Mips工具反汇编工具有ghidra,jeb,ida,插件retdec(我觉得不好用),听说现在ida7.5也可以反mips了, 可我还是个盗版怪。

Mipsghidra 虽然也是只能看个大概

还是要读汇编的

注意是大端   mips64

Mips传参前四个是a0-a3

Mips 返回值   v0 v1

这里要说明一点

我觉得传参和返回值这种东西十分重要,所以我逆向汇编一开始就是上网查mips传参和返回值是啥

 

第一次用ghrida,这翻译的一点不准确连一个参数都忘记传了!!!!!我记住了下次一定有记性   (同时显示了记住mips汇编传参和返回值的重要)

乍一看我还以为没法逆丧了一会儿!

首先我是有两点没有看好,一个是传参数ghrida弄丢一个,一个是加减运算是优于异或的,下面从头到尾静态分析解释一下

复现 | RCTF2020逆向cipher

主函数逻辑是这样:先打开一个flag文件当然这个flag文件内容是需要逆的,因为题目给了一个ciphertext

复现 | RCTF2020逆向cipher

很显然这是flag加密后的结果。

然后进入cipher函数

Cipher函数的第一个参数是flag值,第二个是临时生成的变量

Cipher函数如下:

复现 | RCTF2020逆向cipher

分析cipher函数:

最后的尾巴那里是putchar(10) 就刚好是刚才ciphertext最后一个字节0x0a

复现 | RCTF2020逆向cipher

然后进入encrypt函数进行分析

复现 | RCTF2020逆向cipher

上图为两个参数

我们看一下汇编

复现 | RCTF2020逆向cipher

a0, a1,a2 其实传了三个参数!!!!!

A2那个变量其实是cipher函数param2的地址

就是这里面a2是一个随机数

仔细看的话其实a2传进去两个字节的随机数

因为都是sb指令

Encrypt函数如下:

复现 | RCTF2020逆向cipher

我这里出了一个小问题

我以为异或优先运算,其实不是(这导致我脚本写了半天)

事实是这样的:

Stack32 = key1 

Stack24 = key2由于stackxx都是ulonglong类型的(8个字节),所以key2永远是

这里也是重点,为什么不是key1 0, 偏偏是key2 0

Stack 40 = xxx

Stack48 = xxx

循环里面:

Stack24 = ((stack24 >>8) + (stack24<<0x38) + ustack32) ^index

Stack32 = ((stack32>>0x3d) + (stack32<<3))^stack24

Stack40 = ((stack40>>8 + stack40<<0x38)+stack48) ^ stack32

Stack48 = (stack48>>0x3d + stack48 <<3)^stack40

 

附一个别人的脚本:

https://bbs.pediy.com/thread-259892.htm 

这道题看雪大佬总结了,十分详细值得一看,也写了如何进行动态调试mips。

我就不再这里丢人了!

import struct

def solve():
   
# withopen('ciphertext', 'rb')as f:
    #   enc = f.read()
   
enc = b'*\x00\xf8+\xe1\x1dw\xc1\xc3\xb1q\xfc#\xd5\x91\xf40\xf1\x1e\x8b\xc2\x88YW\xd5\x94\xabwB/\xebu\xe1]v\xf0Fn\x98\xb9\xb6Q\xfd\xb5]w6\xf2\n'
   
for i in range(0x10000):
        v32
, v24 =get_final_r1_r2(0x7413 * 0x1000000000000, 0)
        flag =
b''
       
for k in range(len(enc) // 16):
            f1
, f2 =decrypt(enc[k * 16:k * 16 + 16], v32, v24)
            flag += struct_example.pack(
'>Q', f1) +struct_example.pack('>Q', f2)
       
if b'RCTF' in flag:
           
print(hex(i), flag)
           
print(i)
       
break


def
decrypt(byte16, fc, fd):
    v48 = struct_example.unpack(
'>Q', byte16[:8])[0]
    v40 = struct_example.unpack(
'>Q', byte16[8:])[0]
    v32
, v24 = fc, fd
   
for i in range(0x1e, -1, -1):
       
#print((v40 ^ v32) -v48)
       
v48 = rol64(v48 ^v40, 0x3d)
        v40 = rol64(ull((v40 ^ v32) -v48)
, 8)
        v32 = rol64(v32 ^ v24
, 0x3d)
        v24 = rol64(ull((v24 ^ i) - v32)
, 8)
      
    v48 = rol64(v48 ^ v40
, 0x3d)
    v40 = rol64(ull((v40 ^ v32) - v48)
, 8)
   
return v48, v40


def get_final_r1_r2(c, d):
    v32
, v24 = c, d
   
for i in range(0x1f):
        v24 = ull(ror64(v24
, 8) + v32) ^ i
        v32 = ror64(v32
, 0x3d) ^ v24

   
return v32, v24


def rol64(value, k):
   
return ull(value<< k) | ull(value >> (64 - k))


def ror64(value, k):
   
return ull(value<< (64 - k)) | ull(value >> k)


def ull(n):
   
return n & 0xffffffffffffffff


solve()

 

扫描下方二维码加入星球学习

加入后会邀请你进入内部微信群,内部微信群永久有效!

复现 | RCTF2020逆向cipher

目前28000+人已关注加入我们

复现 | RCTF2020逆向cipher