查看: 509|回复: 0

[Crypto] TetCTF 2020-padwith2019

[复制链接]
发表于 2020-2-26 17:39:38 | 显示全部楼层 |阅读模式
题目描述如下:
Pad with 2019 in 2020! Let your past go!
nc 207.148.119.58 5555
审计源码可知,本题需要我们连续完成2个任务,一个是解密token,从而拿到flag的前半部分;另一个是伪造token,从而拿到flag的后半部分。
在计算token时,先对msg进行pad,再进行AES-CBC加密;解密时先解密,再进行unpad,另外服务器端充当了一个padding oracle,可以告诉我们解密后的消息是否padding正确,根据这些特征很容易联想到CBC字节翻转攻击,关于CBC字节翻转攻击的细节可以参考这里。对于flag的前半部分,我们可以一字节一字节的恢复,从x00开始不断试错,如果收到报错提示,则尝试发送下一字节,否则就存储该字节;对于flag的后半部分,我们想要使得obj['admin'] == True,只需翻转fals为tru。将上述攻击过程写成python代码形式如下(flag前半部分):
import json
from os import urandom
from pwn import remote, process
from string import ascii_letters, digits
from itertools import product

PAD = (("2019") * 8).decode('hex')

def get_paddings_dict(n):
    ans = {}
    for i in range(n):
        ans[i] = pad(i+1)
    return ans

def pad(n):
    pad_length = n
    return chr(pad_length) + PAD[:pad_length - 1]

def crack_byte(token, pos, i):
    token[pos] = i
    return ''.join('{:02x}'.format(x) for x in token)

def find_pad(r, token, pos, last_x):
    token = bytearray(token)
    padings = get_paddings_dict(pos+1)
    if pos:
        token[0] = last_x[0] ^ ord(padings[0][0]) ^ ord(padings[pos][0])
        for j in range(1, pos):
            token[j] = last_x[j]
    for i in range(256):
        payload = crack_byte(token, pos, i)
        r.sendline(payload)
        ans = r.recvline()
        if i % 64 == 0:
            print("current step: ", pos, i, ans)
        if 'padding' in ans:
            continue
        else:
            return i
    raise Exception("All padings are incorrect")

if __name__ == '__main__':
    r = remote("207.148.119.58", 5555)
    token_hex = r.recvline(False)
    print(token_hex)
    token = token_hex.decode('hex')
    parts = [token[i:i+16] for i in range(0, len(token), 16)]
    known = "TF{***********"
    flag = ''
    exp_pad = pad(1)
    c1 = parts[2]
    c2 = parts[3]
    last_x = []
    for i in range(len(known)):
        exp_pad = pad(i+1)
        x = find_pad(r, c1+c2, i, last_x)
        i2 = x ^ ord(exp_pad[i])
        ch = chr(i2 ^ ord(c1[i]))
        if i < len(known) and ch == known[i]:
            flag += ch
            print("Horay!", flag)
            last_x.append(x)
        else:
            flag += ch
            print("Is it right?", flag)
            last_x.append(x)
    print('TetC' + flag[:-2])
执行脚本即可得到前半部分flag:
TetC{p4dd1ng_4t_
flag后半部分脚本如下:
import json
from os import urandom
from pwn import remote, process
from string import ascii_letters, digits
from itertools import product

def crack(token):
    test_token = bytearray(token)
    test = b'x02 {"admin": fals'
    for i, (x, y) in enumerate(zip(test, b'x01{"admin": true}')):
        test_token[i] ^= ord(x) ^ ord(y)
    return ''.join('{:02x}'.format(x) for x in test_token[:32])

if __name__ == '__main__':
    r = remote("207.148.119.58", 5555)
    token = r.recvline(False).decode('hex')
    new_token = crack(token)
    r.sendline(new_token)
    r.interactive()
执行脚本即可得到后半部分flag:
th3_b3g1nn1ng_d03s_n0t_h3lp}
拼接前后两部分即可得到完整flag:
TetCTF{p4dd1ng_4t_th3_b3g1nn1ng_d03s_n0t_h3lp}


温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的最好奖励,还可以获得学币奖励,请尊重作者的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【投诉建议】板块发帖举报。
论坛交流群:672619046
微信公众号
快速回复 返回顶部 返回列表