祥云杯-re复现 (未完待续)

周末祥云杯没打,主要是自己想摸了。。(就是这么直白)还有就是nctf举办,我出题,我到比赛那天还没出完。。。(太咕了。。)
比赛后就想来复现这比赛,看解题人数,感觉满难的,应该很有质量,就跟着null的wp复现吧,一天复现一题

re1

动态调试,发现对flag的每一位进行相同的操作,慢慢看太多了,因此可以gdb脚本爆破,
null的脚本写错了把。。程序开了pie,第一句就不对。。。而且while也没让程序重新启动,这里给出我写的

pwndbg> define f1
Type commands for definition of "f1".
End with a line saying just "end".
>b *$rebase(0x6ce)
>b *$rebase(0x18096)
>set $result = 0x20
>python f = open("log","w+")
>while($result < 0x80)
 >r < test //自己的文件flag{12345678901234567890123456789012}
 >set *(char *)$rdi=$result 
 >python f.write(gdb.execute("p $result",to_string = True))
 >c
 >python s = gdb.execute("x/bx $rdi",to_string = True)
 >python f.write(s)
 >python f.flush()
 >set $result = $result + 1
 >end
>end

之后逐位对照就行,
尝试用angr写了脚本,发现运行不起来,如果有师傅会写,希望能告诉我,tcl…
看评论可以用插桩,学习了一下pin
写的脚本(基本是模板,改一些就行)

#!/usr/bin/env python
# coding=utf-8
import subprocess
import os
import logging
import json
import string
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# js = json.dumps(ssst, sort_keys=True, indent=4, separators=(',', ':'))# format json output


class shell(object):
    def runCmd(self, cmd):
        res = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE,
                               stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        sout, serr = res.communicate()
        return res.returncode, sout, serr, res.pid

    def initPin(self, cmd):
        res = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE,
                               stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        self.res = res

    def pinWrite(self, input):
        self.res.stdin.write(input)

    def pinRun(self):
        sout, serr = self.res.communicate()
        return sout, serr


filename = "./main"
cmd = "/root/tool/ctf/pin/pintool/pin -t " + \
    "/root/tool/ctf/pin/pintool/source/tools/ManualExamples/obj-intel64/inscount0.so" + " -- " + filename
# print shell.runCmd(cmd)
cout_old = 0
# for i in range(30):
#     res  = subprocess.Popen(cmd,shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
#     res.stdin.write("a"*i+'\n')
#     sout,serr = res.communicate()
#     cout = sout.split("Count ")[1]
#     cout_sub= int(cout) - cout_old
#     cout_old = int(cout)
#     print ("current len ", i,"current count:",cout,"sub_count ",cout_sub)
shell = shell()
#shell.initPin(cmd)
cout_old=0
cur=''
j = 0
cout_sub = 0
dic = string.digits+"b"+string.letters+'_{}'+string.digits
for i in range(33):
    for j in range(len(dic)):
        if cout_sub < 0 and cout_sub>-3:
            cout_old = cout_old - cout_sub
        shell.initPin(cmd)
        pwd = "flag{"+cur+dic[j]+'?'*(31-len(cur)) + "}"
        print pwd
        shell.pinWrite(pwd)
        sout,serr = shell.pinRun()
        cout = sout.split("Count ")[1]
        cout_sub= int(cout) - cout_old
        cout_old = int(cout)
        if cout_sub > 0 and cout_sub < 3:
            cur=cur+dic[j]
            break
        print ("current cur ", cur,"current count:",cout,"sub_count ",cout_sub)
        

打工人

服了 ,终于逆出来了,这个由go写的lua虚拟机真尼玛的难逆,加密满简单的,就是des-cbc,后再base58,但关键是真tm的难看出来啊。。。
说一下过程,别问我怎么来的,全是动手调出来的。。。0000000005718B0是main.main函数,go语言写的,很容易看出来,再根据经验,main.main往往在函数列表最后,再慢慢调可以得到。。
00000000004F4B50是lua语言的解释器
作者github上找的,没删网址,应该是他的一点友善了吧。。
https://github.com/yuin/gopher-lua
https://github.com/tengattack/gluacrypto/
他所应用的
在main函数调用lua的解释器之前,查看它的参数,可以看到lua的脚本

b 'function joke()',0Ah
debug030:000000C0000EC000 db '    return "3".. "2".. "7".. "a".. "6".. "c".. "4".. "3".. "0".. '
debug030:000000C0000EC000 db '"4".. "a".. "d".. "5".. "9".. "3".. "8".. "e".. "a".. "f".. "0"..'
debug030:000000C0000EC000 db ' "e".. "f".. "b".. "6".. "c".. "c".. "3".. "e".. "5".. "3".. "d".'
debug030:000000C0000EC000 db '. "c"',0Ah
debug030:000000C0000EC000 db 'end',0Ah
debug030:000000C0000EC000 db 's = joke()',0Ah
debug030:000000C0000EC000 db 'local m = require("crypto")',0Ah
debug030:000000C0000EC000 db 'f="fake"',0Ah
debug030:000000C0000EC000 db 'if(m.md5(',27h,'flag',27h,') == s)',0Ah
debug030:000000C0000EC000 db 'then',0Ah
debug030:000000C0000EC000 db 9,'a=io.read("*l")',0Ah
debug030:000000C0000EC000 db 9,'r = m.encrypt(a, "enjoy" ,',27h,'flagflag',27h,', 0, "a = f+ a"'
debug030:000000C0000EC000 db ')',0Ah
debug030:000000C0000EC000 db 'else',0Ah
debug030:000000C0000EC000 db 9,'print("wrong")',0Ah
debug030:000000C0000EC000 db 9,'error({error="input wrong"})',0Ah
debug030:000000C0000EC000 db 'end',0Ah
debug030:000000C0000EC000 db 0Ah,0

首先应该输入“flag”与MD5一样,之后再输入进行加密,至于des-cbc是怎么看出来的,调的,再结合给出github网址,作者好恶心,还魔改des-cbc改成enjoy,iv改成了“flagflag”^"a = f+ a"后的字符串,注意这里的“a = f+ a”是字符长,不是式子,当时调的时候,怎么也找不到f+a后的字符长,只找到了“a = f+ a”,太误导人了。。。。。
0000000000571410 base58 看表,发现
之后就是比较
解密脚本

from Crypto.Cipher import DES
from base58 import *
from binascii import a2b_hex
cip = b58decode("YjNiZejTKW37A3FtSwV3xSMYRjDpMnsUBCJqK7DZ5mAnfQvGd8KjgpG4yYA2v5BmY67iemDJvH8x8a5NLaSmbvKyemMGsx2SaQoc7kpy1gKQU")

cip = '1f8c11a43c1e321cd7a1dc3b1cc6665f0bd83d2d6058be3f684162e2c91c33f67c21eb3faf1a1f42'
#reversed(cip)
cip = a2b_hex(cip)
iv = "\x07\x4c\x5c\x47\x00\x47\x41\x06"#"flagflag"xor "a = f+ a"后的 
key = "flagflag"
#cip = "4567\x04\x04\x04\x04"



des = DES.new(key,DES.MODE_CBC,iv)
flag = des.decrypt(cip)
print(flag)

总的来说,下次碰到这种,应该秒做了,这一次逆的想死了

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值