Minhal's Blog

Back

一个mips64架构的Re题目。

检查文件格式#

检查文件是个一个mips64大端程序,穷人用不起IDA pro 7.5,只能上ghidra来进行反编译操作。

分析代码#

  • 题目给出了一个加密后的文本

12 最后多出来的0A是个换行符。

  • 用ghidra反汇编,进入主函数

1

  • 时间做随机种子, cipher应该就是加密函数了。
  • 进入cipher,发现有个循环,每16位为一组数据,由于我们结果为48位,所以应该是就分为三组进行操作。encrypt是加密函数,第一个参数是加密结果,第二个参数是输入内容。 2
  • 再次进入encrypt函数,由于反汇编偏差,rand这个随机数参数未能识别传进来。in_a2就是这个参数。 3
  • 根据代码,修复一些变量名。 4
  • while循环为主要加密过程,主要进行了一些位运算。,写出位运算逆向脚本
  ld =[s2]
  lc = [s1]
  for i in range(31):
    ld.append((rright(ld[i],8) + lc[i] ^ i)&0xffffffffffffffff )
    lc.append(rright(lc[i],61) ^ ld[i+1])
  for i in range(31,-1,-1):
    x1 = rright(x1^x2,3)
    x2 = rright(((x2^lc[i])-x1)&0xffffffffffffffff,56)    
  return x1,x2
python

解决思路#

  • while循环中,srand未知,输出结果已知,输入内容未知。所以我们逆向出这个运算,还是需要得到srand值,才可能解决题目

  • srand 可以采取爆破的形式,由于比赛flag形式为RCTF{xxxxx},所以我们可以根据第一组数据进行爆破,得到srand。每个srand255(无符号)种情况,255*255总共65535种情况。

    for i in range(65536):
        s1 = i
        s2 = 0
        s1,s2 = struct.unpack('QQ',struct.pack('>QQ',s1,s2))
        x1,x2 = reverse(lists2[0],lists2[1],s1,s2)
        str1 = struct.pack('>Q',x1)
        if 'RCTF' in str1:
            print(i)
            break
    python
  • 得到srand,然后直接逆向解决就好了。

for i in range(len(lists2)/2):
    s1,s2 = struct.unpack('QQ',struct.pack('>QQ',4980,0))
    x1,x2 = reverse(lists2[2*i],lists2[2*i+1],s1,s2)
    flag += struct.pack('>Q',x1)
    flag += struct.pack('>Q',x2)
print (flag)
python

exp#

总结#

这个题目比较坑的两个地方是注意大小端,还有就是加号与异或运算优先级,如果这两个搞错,很容易被卡住的。

RCTF cipher
https://minhal.me/blog/rctf-cipher
Author Minhal
Published at 2020年6月2日
Comment seems to stuck. Try to refresh?✨