1. 程式人生 > 實用技巧 >BUUCTF:[CSAWQual 2019]byte_me

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