[Re]南邮ctf平台逆向题


继续学习,这次尝试做了一下南邮ctf平台的逆向题来练习

目录

第一题 HELLO,RE!

第二题 ReadAsm2

第三题 Py交易

第四题 WxyVM

第五题 maze

第六题 WxyVM 2

 


第一题 HELLO,RE!

打开ida,找到main函数按F5,hexray反编译

就在眼前 flag{Welcome_To_RE_World!}

第二题 ReadAsm2

来锻炼汇编的阅读能力吧

main函数定义了一串字符串,应该就是加密的密文

通过func解密后输出结果,题目提示调用约定为System V AMD64 ABI

百度调用约定后,分析结果如下

总的来说,意思就是函数对输入的字符串每一个字符都与其

所在缓冲区的索引做异或运算,最后输出结果。

用py来写解密脚本吧



flag = [0x0,0x67,0x6e,0x62,0x63,0x7e,0x74,0x62,0x69,0x6d,
                  0x55, 0x6a, 0x7f, 0x60, 0x51, 0x66,0x63, 0x4e, 0x66, 0x7b,
                  0x71, 0x4a, 0x74, 0x76, 0x6b, 0x70, 0x79, 0x66 , 0x1c]

flagstr = []

index = 0
for ech in flag:
    flag[index] = ech^index
    flagstr.append(chr(flag[index]))
    index = index+1

print ''.join(flagstr) 



运行后得到答案 flag{read_asm_is_the_basic}

第三题 Py交易

Pyc文件,直接就是让我们,来反编译源文件了

百度就可以找到pyc在线反编译网站https://tool.lu/pyc/

反编译结果如下

import base64

def encode(message):
    s = ''
    for i in message:
        x = ord(i) ^ 32
        x = x + 16
        s += chr(x)
    
    return base64.b64encode(s)

correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt'
flag = ''
print 'Input flag:'
flag = raw_input()
if encode(flag) == correct:
    print 'correct'
else:
    print 'wrong'
import base64

def encode(message):
    s = ''
    for i in message:
        x = ord(i) ^ 32
        x = x + 16
        s += chr(x)
    
    return base64.b64encode(s)

correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt'
flag = ''
print 'Input flag:'
flag = raw_input()
if encode(flag) == correct:
    print 'correct'
else:
    print 'wrong'

对上述代码中的encode加密函数作逆就可以得到结果了

py脚本如下

from base64 import *

correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt'
correct = b64decode(correct)
correct = list(correct)

flag = []
for ech in correct:
    x = ord(ech) - 16
    x = x ^ 32
    flag.append(chr(x))

print ''.join(flag)

最终结果为 nctf{d3c0mpil1n9_PyC}

第四题 WxyVM

扔到64位windows Linux子系统下运行,显示要求我们输入flag

扔到ida,找到main函数,F5反编译

主函数没什么好说的,判断输入的字符数,sub_4005b6这个函数对其加密,然后与601060这的数组做比对

现在只要解密601060的数组即可

进入sub_4005b6函数

看来是根据6010c0表的值以及做运算

dump下6010c0处的数组,以及最后用于比较的位于601060处的密文

值得注意的是601060处的数组是一个双字数组,而我们的输入时字符单字节数组

所以做比较时,只有双字的低8位与我们的输入做比较,其他都是垃圾数据,所以

密文保存的时候只要保存低8位的字节就行了

py脚本如下

biao = open('biao','rb')
flag = [0xC4,0x34,0x22,0xB1,0xD3,0x11,0x97,0x7,0xDB,0x37,0xC4,0x6,0x1D,0xFC,0x5B,0xED,0x98,0xDF,0x94,0xD8,0xB3,0x84,0xCC,0x8]
   
biaolist = []
for i in range(0,15000):
    tmp = biao.readline(1)
    biaolist.append(ord(tmp))
    

biao.close()

for i in range(14997,-1,-3):
    v0 = biaolist[i]
    v3 = biaolist[i+2]
    result = v0
    if v0 == 1:
        result = biaolist[i+1]
        flag[result] -= v3
    elif v0 == 2:
        result = biaolist[i+1]
        flag[result] += v3
    elif v0 == 3:
        result = biaolist[i+1]
        flag[result] ^= v3
    elif v0 == 4:
        result = biaolist[i+1]
        flag[result] = flag[result]/v3
    elif v0 == 5:
        result = biaolist[i+1]
        flag[result] ^= flag[biaolist[i+2]]
    else:
        continue

flagstr = []

for ech in flag:
     flagstr.append(chr(ech%256))

flagstr = ''.join(flagstr)
print flagstr

 

py的变量没有溢出之类的概念,所以记得对256取模来保证,字符正常输出

“biao”是我们dump下来的加密函数用的数组

最终结果如下:nctf{Embr4ce_Vm_j0in_R3}

第五题 maze

前天看到bugku上有一道take the maze,还没弄懂,还好这个还简单些

依然是扔到ida里去在main函数中反编译

很长呢…改了几个变量名字看着舒服多了

整体看下来就是大概用了一个变量,64位的road(这是我自己重命名的变量)

他的高32位用作列索引,低32位用作行索引(小端序机器),在提供给的maze_list这个二维

数组中前进,如果遇到 # 就算成功,几个条件判断语句控制,前进的方向,road保存着当前的位置

结果是’O’向左,’o’向右,’.’向上,’0’向下,去吧maze_list的表给dump下来

一行8个的二维数组,我用py打印出来直观的看一下

maze = '  *******   *  **** * ****  * ***  *#  *** *** ***     *********'

tu = []

tuech = []

index = 0
for ech in maze:
    if index == 7:
        index = 0
        tuech.append(ech)
        tu.append(tuech)
        tuech = []
        continue
    tuech.append(ech)
    index = index+1

for ech in tu:
    print ''.join(ech)

然后自己画着走就可以看出来了

应该是o0oo00O000oooo..OO

最后结果为 nctf{o0oo00O000oooo..OO}

第六题 WxyVM 2

隔了一天弄好了,解密脚本一开始就写完了,

结果运算结果匪夷所思,弄了半天才发现,原来py没有

自增运算符。。。。。

首先是main函数,光反编译就等了一会儿。。。

总的来说就是有一大串没有意义的运算,有意义的就只有以字节运算的语句

byte_694100是我们的输入,最后这个循环就是用来比较的,和前面一道题

差不多,也只要关注第一个字节就行。

把所有的运算语句copy下来选出byte运算的就可以。

我第一次弄完了后,打算迭代直接exec(),

结果由于py没有自增运算符,输出成很奇怪的

flag

郁闷了我好久。。。。。

偷个懒干脆直接生成c语言风格的语句,用c计算了。。。

python生成c语言语句

f = open('shanxuan.txt')
byte_694100 = 0xC0
byte_694101 = 0x85
byte_694102 = 0xF9
byte_694103 = 0x6C
byte_694104 = 0xE2
byte_694105 = 0x14
byte_694106 = 0xBB
byte_694107 = 0xe4
byte_694108 = 0xd
byte_694109 = 0x59
byte_69410A = 0x1c
byte_69410B = 0x23
byte_69410C = 0x88
byte_69410D = 0x6e
byte_69410E = 0x9b
byte_69410F = 0xca
byte_694110 = 0xba
byte_694111 = 0x5c
byte_694112 = 0x37
byte_694113 = 0xfff
byte_694114 = 0x48
byte_694115 = 0xd8
byte_694116 = 0x1f
byte_694117 = 0xab
byte_694118 = 0xa5
flist = f.readlines()

for i in range(len(flist)):
   flist[i] = flist[i].strip(' \n;u')

tmp = []
index1 = 0
index2 = 0
for ech in flist:
   index2 = 0
   if ech.find('+') != -1:
      tmp = list(ech)
      for c in tmp:
         if c=='+':
            tmp[index2] = '-'
         index2 = index2+1
      flist[index1] = ''.join(tmp)
      tmp = []
   
   elif ech.find('-') != -1:
      tmp = list(ech)
      for c in tmp:
         if c=='-':
            tmp[index2] = '+'
         index2 = index2+1
      flist[index1] = ''.join(tmp)
      tmp = []

   index1 = index1+1
   tmp = []

flist.reverse()
i = 0
for ech in flist:
    if ech.find('byte') != -1:   

       print ech+';'

笨笨的脚本,不想管了。。

把变量,和输出结果copy到vs里再定义一下,编译出结果

结果 nctf{th3_vM_w1th0ut_dAta}。好累再去刷bugku的题。。。