BUUCTF:[CSAWQual 2019]byte_me
首先在buuctf里是可以拿到源码的,这里也可以直接猜测一下,不停的输入a,你会发现到一定数量后发回来的密文的前32位不会再发生变化,这里便是ECB加密模式的特点,首先来看一下ECB加密的原理(网图)
加密:randomstr+yourinput+flag,如果你输入的a与randomstr相加刚好等于分组数(16bytes),那么密文的前32位(16进制)都是randomstr+(16-randomstr)*'a'的加密结果,自然你后面再增加a的数量密文也不会再改变,所以我们可以先来把前面这段补齐
from pwn import *
r=remote('node3.buuoj.cn',25676)
re=r.recvline().decode()
re=bytes.fromhex(re)
set1=[]
print('attack start.......')
for i in range(1,17):
sen_mes='a'*i
try:
r.sendline(sen_mes)
except:
print('something ro')
r.recvline()
re1=r.recvline().strip().decode()
if re1[0:16] in set1:
head=i-1
break
set1.append(re1[:16])
print(head)
通过密文的长度我们可以估计flag的长度大概 32<flag<48,这里直接爆破显然是不太可能的,我们需要将\((128-32)^{len(flag)}简化为k(128-32)\)
我们只需构造上图中的数据,爆破i的值就可以了通过对比密文的第二组数据来得到flag[0]也就是'f',按照这种思路我们就可以在\(k(128-32)\)的情况下爆破出flag的值,完整的脚本如下
from pwn import *
r=remote('node3.buuoj.cn',25676)
re=r.recvline().decode()
re=bytes.fromhex(re)
set1=[]
print('attack start.......')
for i in range(1,17):
sen_mes='a'*i
try:
r.sendline(sen_mes)
except:
print('something ro')
r.recvline()
re1=r.recvline().strip().decode()
if re1[0:16] in set1:
head=i-1
break
set1.append(re1[:16])
print(head)
#a reference
#attack [0:16]
mes='a'*head
realflag=''
for i in range(1,17):
ju=mes+'b'*(16-i)
r.sendline(ju)
r.recvline()
ju_recv=r.recvline().strip().decode()
for j in range(32,128):
mes_add=mes+'b'*(16-i)+realflag+chr(j)
r.sendline(mes_add)
r.recvline()
try_recv=r.recvline().strip().decode()
if ju_recv[32:64]==try_recv[32:64]:
realflag=realflag+chr(j)
print('realflag:{}'.format(realflag))
break
#attack[16:32]
for i in range(1,17):
ju=mes+'b'*(16-i)
r.sendline(ju)
r.recvline()
ju_recv=r.recvline().strip().decode()
for j in range(32,128):
mes_add=mes+realflag[i:15+i]+chr(j)
r.sendline(mes_add)
r.recvline()
try_recv=r.recvline().strip().decode()
if ju_recv[64:96]==try_recv[32:64]:
realflag=realflag+chr(j)
print('realflag:{}'.format(realflag))
break
#attack all
for i in range(1,17):
ju=mes+'b'*(16-i)
r.sendline(ju)
r.recvline()
ju_recv=r.recvline().strip().decode()
for j in range(32,128):
mes_add=mes+realflag[i+16:31+i]+chr(j)
r.sendline(mes_add)
r.recvline()
try_recv=r.recvline().strip().decode()
if ju_recv[96:128]==try_recv[32:64]:
realflag=realflag+chr(j)
print('realflag:{}'.format(realflag))
if chr(j) == '}':
exit(0)
break