2020强网杯-强网先锋-bank

2020强网杯-强网先锋-bank

bank这题首先需要nc一个ip地址,发现发现返回

sha256(XXX+yhB1iPWH3ENjHhf12) == 05401c749eee0ccb5a9cfb96eae3d8909a489113066f3a0f185580ac60a18403
Give me xxx:
#填对以后要填teamtoken
teamtoken:
#要填写一个用户名
input your name:

老密码学题了,要算出xxx的值。爆破完事。

然后试了一下,发现有时间限制,操作时间超过一定的话,就会被断开连接。所以一切都要脚本跑,手动来不及。

进去以后,继续看下面的逻辑。

>you can choose: transact, view records, provide a record, get flag, hint
#transact交易功能
>transact
>please give me the trader and the amount(for example:Alice 1)
>Alince 1
xxxxxxxxxxx(返回一个96位的字符)
#view records,查看交易记录功能
返回十条记录(不记得具体几条了)
然后英文后面才理解,是说每一条记录的金额都大于100
#provide a record功能
#输入交易记录就可以赚钱了
>My system is secure if you can give me other records, the receiver can also get the money
#get flag
提示要1000块钱才能买得起flag(初始只有10元)
#hint 最重要的提示
def transact_ecb(key, sender, receiver, amount):
    aes = AES.new(key, AES.MODE_ECB)
    ct = b""
    ct += aes.encrypt(sender)
    ct += aes.encrypt(receiver)
    ct += aes.encrypt(amount)
    return ct
#分析一下,大意是说每次交易记录的96位字符串,生成的时候由三部分组成,sender/receiver/amount,三部分都经过aes加密。

块加密,其实就像aes加密的ecb模式,由于每块都是完全独立的。形式类似:A给B共C元,即使不知道key,无法解密。也可以通过替换等方式进行攻击

比如把sender和receiver调换:

原来的明文:A给B共C元
修改后明文:B给A共C元

所以这题要赚钱,就是要伪造records,提供出去就能换钱了。

因此思路就是伪造交易记录:

A给B共100元
Q给R共110元
……………………
替换为:
A给我共100元
Q给我共110元

好了,我们已经知道了,receiver是中间的32位字符。现在要找到代表自己的32位加密后字符,替换掉真正的receiver就行了。李代桃僵。

通过transact,我们可以得到一条:我给Alice共xx元的信息。在这条信息中,前32位就是用户user经过加密后的身份信息!

整理一下思路:

  1. transact交易一次,取得前32位即代表自己的密文段
  2. view records,查看记录,获取到真实的交易记录
  3. 把交易记录中间32位代表接收者的密文段,换成1中得到的代表我自己的密文段。于是得到了伪造的交易凭证。
  4. 将伪造的交易凭证提供出去,进行兑换。provide records
  5. 赚够钱了get flag
    注意view records中每笔交易的金额都大于100,因此伪造10条假记录就够了。

用了pwn库做nc连接,代码如下,非常丑陋:

#python3代码
import hashlib
import string
import pwn

def hashcollision(m,n):
    strlib = string.ascii_letters + string.digits 
    for a in strlib:
        for b in strlib:
            for c in strlib:
                originstr = a + b + c + m
                if(n == hashlib.sha256(originstr.encode('utf-8')).hexdigest()):
                    return a+b+c

token = '*******'
ip = "*******"
port = ***
if __name__ == '__main__':
    bank = pwn.remote(ip,port)
    hashdata = bank.recv()#接收hash值
    bank.recv()#接收give me xxx
    hashdata = str(hashdata,encoding='utf-8')
    hashdata = hashdata.split('==')
    m = hashdata[0].strip()[11:-1]
    n = hashdata[1].strip()
    bank.sendline(hashcollision(m,n))#传入破解后的hash值
    bank.sendline(token)#传入token
    bank.recv()
    #如果系统要求输入名字,则已经登陆成功
    if('name' in str(bank.recv(),encoding='utf-8')):
        print('login success')
    bank.sendline('J2CGeek')#here is my name
    print(str(bank.recv(),encoding='utf-8').strip('\n'))
    print(str(bank.recv(),encoding='utf-8').strip('\n'))
    #选择transact, view records, provide a record, get flag, hint功能
    #选择transact,开始py交易
    bank.sendline('transact')
    print(str(bank.recv(),encoding='utf-8').strip('\n'))
    bank.sendline('Alice 1')
    print(str(bank.recv(),encoding='utf-8').strip('\n'))
    #得到一个记录,其中前32位代表我,中间32位代表alice,后32位代表10。于是得到代表用户id的32位密文
    record = str(bank.recv(),encoding='utf-8').strip('\n')
    userinfo = record[0:32]
    print('Get userinfo:'+ userinfo)
    #选择view records,取出其中数据,伪造10条record
    bank.sendline('view records')
    print(str(bank.recv(),encoding='utf-8').strip('\n'))
    record = str(bank.recv(),encoding='utf-8').split('\n')
    fakerecord = []
    for i in range(10):
       fakerecord.append(record[i][:32] + userinfo + record[i][64:])
       print('Get '+ str(i+1) +' fakerocord!!!')
    #开始发送fake record赚钱了
    for i in range(10):
        bank.sendline('provide a record')
        bank.sendline(fakerecord[i])
        print(str(bank.recv(),encoding='utf-8').strip('\n'))
        print(str(bank.recv(),encoding='utf-8').strip('\n'))
    print(str(bank.recv(),encoding='utf-8').strip('\n'))
    #开始购物!!!
    bank.sendline('get flag')
    print(str(bank.recv(),encoding='utf-8').strip('\n'))   
    print(str(bank.recv(),encoding='utf-8').strip('\n')) 
    bank.close()

思路还是挺简单的。
view records那里提示的英语好像有问题,看了半天我一直以为是说records总条数大于100,后面才发现是每笔交易金额大于100。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值