美文网首页
2016-pediy-ctf-04

2016-pediy-ctf-04

作者: ZERO_47ce | 来源:发表于2019-03-19 10:14 被阅读0次

    2016-pediy-ctf-04

    发现主程序很简单,主要过程在窗口回调

    Image.png

    通过GetDlgItemText得到输入,并对其字数进行比较,锁定关键函数


    Image [3].png

    查看关键函数,发现里边的代码很混乱,利用PEID和exeinfo查壳,发现并没有检测到壳,顺便利用PEID工具检测一下加密算法,发现MD5算法


    Image [4].png Image [5].png

    搜索字符串并不能发现其他有用的东西
    所以我们直接进行动态调试
    输入 1234567890三次,得到30位输入进行调试关键函数

    动态调试发现该过程存在循环

    Image [6].png
    其实该过程为虚拟机,即VMP,上图esi为handler,
    直接查看esi全部handle,在最后几个下内存断点
    Image [7].png
    注意这个操作,出虚拟机的操作,我们直接下断点
    Image [8].png

    笔者由于个人水平有限,还是不能说清楚关于虚拟机的种种操作,所以这里只是在关键位置提一下,只能说关联代码前后凭感觉去找出虚拟机的操作,并且作者在关键代码并没有VM,如果作者所有代码都进行VM操作,可能以笔者水平,并不能搞完这个题

    出虚拟机后
    004014F0
    发现我们之前用插件得到的MD5, 进入该函数发现第一次作比较把我们输入的前七位拷贝之后ret,不过很可能之后依旧会进入该函数,并很可能进行MD5操作
    ret后发现再次进入虚拟机,我们直接运行到虚拟机出口

    Image [13].png

    004015c0
    该函数的两个函数主要操作

    Image [10].png

    第一次进入004014F0加了结束标志符,并把后边清0

    Image [11].png

    第二次,MD5操作

    Image [12].png

    拷贝MD5值并把内存清0


    Image [14].png

    00401187
    获取之后的23位,与指定数进行xor

    Image [15].png

    之后该值会与之后的MD5值进行XOR,注意MD5值16字节,重复循环,xor,直到23字节
    得到值

    Image [16].png

    这两个赋值操作是对迷宫的初始化,后期会用到的

    Image [17].png

    而且此时的数值才是正确的,因为之后经过VM后,有些数值会发生变化,导致后边计算错误

    之后就是迷宫走法的核心计算,下边是如何计算每一步及其规则

    Image [18].png

    详细说一下这里吧
    首先00401248这里cl被赋值为6,4,2,0,
    0040124E这个edx取我们输入后处理的值,and 3,得到其值
    然后通过00401253计算跳到哪里,这里可以得到
    0 ---> 向上走
    1 ---> 向前走
    2 ---> 向下走
    3 ---> 向后走
    所以一个字节可以走四步

    然后接下来是迷宫的计算

    Image [19].png

    我们首先得到
    part 1

    Image [20].png
    part 2
    Image [21].png
    首先是对Part 1根据上边的走法取对应值然后ror,这条指令我们用程序模拟还是挺麻烦的,在找到对应的part 2值,进行xor
    之后我们通过爆破,发现0x58是出口
    了解了具体的步骤
    我们开始写程序爆破
    程序后边代码
    #程序参考来自https://bbs.pediy.com/thread-213791.htm   〇〇木一
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    import md5
    import binascii
    
    p1 = "6ED41B695F4EE8AA95F6AFCE321A62D9021874951FC24D333CF03BECE9814B9C"
    p1 += "0F475CADD909B087539BF2E30F01928DC2F50CDD42CCAFB4D5E486D39A0B6263"
    p1 += "A7D41B695F4EE8AA95F6AFCE321A62D9021874951FC24D3338F03BECED814B9C"
    p1 += "0B475CADDD09B087579BF2E30B01928DC2F50CDD42CCAFB4D5E486D39A0B6263"
    p1 += "A7D41B695F4EE8AA95F6AFCE321A62D9021874951FC24D3338F03BECE9814B9C"
    p1 += "0F475CADD909B087539BF2E30F01928DC2F50CDD42CCAFB4D5E486D39A0B6263"
    p1 += "A7D41B695B4EE8AA91F6AFCE361A62D9021874951FC24D3338F03BECE9814B9C"
    p1 += "0B475CADDD09B087579BF2E30B01928DC6F50CDD42CCAFB4D5E486D39A0B6263"
    
    p2 = "D805F66AE7A20B9B548CDA82BDB6A846B1362D55F78163FC3F0CFE0B4B50E217"
    p2 += "F2E1275B46731CD0E5D78DC9F2709453814C3246A002DB1C450991C496F2A8E8"
    p2 += "D905F66BE7A20A9B548CDA82BDB7A946B0362D54F78163FC3E0CFE0B4B50E317"
    p2 += "F2E0265A47731CD1E5D68CC8F2709553804C3347A002DB1C440891C496F2A9E8"
    p2 += "D904F66AE7A20A9B558CDB83BCB6A946B0372D55F78163FD3E0DFE0B4A50E317"
    p2 += "F3E0275B46731DD0E4D78CC8F3709553804C3347A003DB1D450891C496F2A9E8"
    p2 += "D904F66AE6A30A9A548CDB82BCB7A946B0372C54F68162FD3E0DFE0A4A50E217"
    p2 += "F2E1275B47721CD0E5D78CC9F2709453814D3347A003DB1C440891C5979AA8E8"
    
    #生成迷宫
    pp1 = binascii.a2b_hex(p1.encode())
    pp2 = binascii.a2b_hex(p2.encode())
    pp3 = ""
    def ror2(a):
        return ((a&3)<<6)|(a>>2) & 0xFF
    
    for i in range(len(pp1)):
        pp3+=chr(ror2(ord(pp1[i])) ^ ord(pp2[i]))
    print(len(pp3))
    
    #16字节一行打印
    for i in range(16):
        ps = ""
        for j in range(16):
            ps+=binascii.b2a_hex(pp3[i*16+j]).upper()
        print(ps)
    
    x = 0
    y = 0
    x0 = 0
    y0 = 0
    t = [(0,-1),(1,0),(0,1),(-1,0)]
    #打印程序指定的道路
    path = ""
    while(ord(pp3[y*16+x]) != 0x58):
        for i in range(4):
            xx = x + t[i][0]
            yy = y + t[i][1]
            if(xx >= 0 and xx < 16 and yy < 16 and yy >=0 and (xx != x0 or yy != y0)):
                if ord(pp3[yy*16+xx]) != 0x30:
                    path += str(i)
                    x0 = x
                    y0 = y
                    x = xx
                    y = yy
                    break
    print(path)
    
    #按照之前的走法,将其合并为每四步为一个字节    one byte for 4 steps,
    pn0 = ""
    for i in range(23):
        a = 0
        for j in range(4):
            a = (a | int(path[i*4+j])<<((3-j)*2))&0xFF
        pn0 += chr(a)
    
    print(binascii.b2a_hex(pn0).upper())
    
    #处理输入
    ## 在程序中存在以下操作
    ## 对前七位进行MD5操作,并循环扩展到0x17位,
    ## 然后剩余23位与44 AD 5C CC 12 90 73 8D 47 81 E3 89 84 9C DF F9 47 6A B6 9E 11 30 27 sn0进行xor得到sn
    ## 然后MD5与sn进行xor得到sn_1
    ## 存在 path = md5[x1] ^ x2 ^ sn0
    
    def getmd5(src):
        m1 = md5.new()
        m1.update(src)
        ret = m1.digest()
        ret = ret + ret[0:7]
        return ret
    
    pn1 = binascii.a2b_hex("44AD5CCC1290738D4781E389849CDFF9476AB69E113027")
    pnx=""
    #因为是xor操作,有可逆性,所以我们直接得到他之前的值
    for i in range(23):
        pnx += chr(ord(pn0[i])^ord(pn1[i]))
    print("pnx:", binascii.b2a_hex(pnx).upper())
    
    def xorpm(pm):
        global pnx
        pno=""
        for i in range(23):
            pno += chr(ord(pnx[i])^ord(pm[i]))
        return pno
    
    def isstr(s):
        for a in s:
            aa = ord(a)
            if aa < 32 or aa > 126:
                return False
        return True
    
    # 枚举,
    tab='0456123789abcdef'
    t0 = time.time();
    for a0 in tab:
      for a1 in tab:
        for a2 in tab:
          for a3 in tab:
            for a4 in tab:
              for a5 in tab:
                for a6 in tab:
                  aaa=a0+a1+a2+a3+a4+a5+a6
                  pppp=xorpm(getmd5(aaa))
                  if isstr(pppp):
                    print(aaa+pppp)
                    break
    

    你也可以在这里查看:
    https://github.com/ZEROSHE/ctf/tree/master/ctf/Pediy/2016%20ctf/4
    本人水平有限,只能知其一二,很多地方可能存在不当或者错误还请指出,谢谢。

    参考链接:
    https://ctf.pediy.com/game-fight-5.htm

    相关文章

      网友评论

          本文标题:2016-pediy-ctf-04

          本文链接:https://www.haomeiwen.com/subject/ixiwmqtx.html