admin 发表于 2020-2-26 17:39:38

TetCTF 2020-padwith2019

题目描述如下: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 = 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 = 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 = last_x ^ ord(padings) ^ ord(padings)
      for j in range(1, pos):
            token = last_x
    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 = for i in range(0, len(token), 16)]
    known = "TF{***********"
    flag = ''
    exp_pad = pad(1)
    c1 = parts
    c2 = parts
    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)
      ch = chr(i2 ^ ord(c1))
      if i < len(known) and ch == known:
            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 ^= 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]
查看完整版本: TetCTF 2020-padwith2019