Info

Category: Crypto & Forensics
Point: 150
Solver: bruce30262 @ BambooFox
這題其實是從中間接下去解的
感謝其他隊友們先做出前面的的部分

Analyzing

題目給了個 pcap 檔,要我們找出裡面的 secret。經過分析後可以從裡面抓出一些重要的資訊:

首先是 secret 的密文:

encrypt(secret):
msg=
3ed2e01c1d1248125c67ac637384a22d
997d9369c74c82abba4cc3b1bfc65f02 
6c957ff0feef61b161cfe3373c2d9b90
5639aa3688659566d9acc93bb72080f7
e5ebd643808a0e50e1fc3d16246afcf6
88dfedf02ad4ae84fd92c5c53bbd98f0
8b21d838a3261874c4ee3ce8fbcb9662
8d5706499dd985ec0c13573eeee03766
f7010a867edfed92c33233b17a9730eb
4a82a6db51fa6124bfc48ef99d669e21
740d12656f597e691bbcbaa67abe1a09
f02afc37140b167533c7536ab2ecd4ed
37572fc9154d23aa7d8c92b84b774702
632ed2737a569e4dfbe01338fcbb2a77
ddd6990ce169bb4f48e1ca96d30eced2
3b6fe5b875ca6481056848be0fbc26bc
bffdfe966da4221103408f459ec1ef12
c72068bc1b96df045d3fa12cc2a9dcd1
62ffdf876b3bc3a3ed2373559bcbe3f4
70a8c695bf54796bfe471cd34b463e98
76212df912deef882b657954d7dada47

這邊刻意將密文以 32 字元為單位做分割,等等會用到。

之後是跟 decrypt message 相關的一些資訊:

msg=00000000000000000000000000000000997d9369c74c82abba4cc3b1bfc65f02
md5(decrypt(msg)) = aa85a4e0adbd34c287af2d20da4453c9

msg=0000000000000000000000000000d903997d9369c74c82abba4cc3b1bfc65f02
md5(decrypt(msg)) = 9f5b543c64d3e384078fdd8cf4b2ce6d

msg=00000000000000000000000000efd802997d9369c74c82abba4cc3b1bfc65f02
md5(decrypt(msg)) = c68dda2cc0d9907bc7252b53a447b2ce

msg=00000000000000000000000007e8df05997d9369c74c82abba4cc3b1bfc65f02
md5(decrypt(msg)) = 650713f94eae0ecdfa4e527745dd2591
................................................
................................................
msg=0000ce71616536683d0ed00c0de2d50f997d9369c74c82abba4cc3b1bfc65f02
md5(decrypt(msg)) = 6d09e40852ecf180281d504b7718d12d

msg=00b3cf70606437693c0fd10d0ce3d40e997d9369c74c82abba4cc3b1bfc65f02
md5(decrypt(msg)) = f1290186a5d0b1ceab27f4e77c0c5d68

msg=67acd06f7f7b28762310ce1213fccb11997d9369c74c82abba4cc3b1bfc65f02
md5(decrypt(msg)) = d41d8cd98f00b204e9800998ecf8427e
................................................
................................................

這邊注意 00000000000000000000000000000000997d9369c74c82abba4cc3b1bfc65f02 的後半部,其實跟密文中的第二行是一模一樣的。透過一些觀察,可以知道有人不斷的嘗試將一串密文送給 server 進行解密的動作,而且會根據 server 的回覆來更新要解密的密文。

因為對 crypto 沒啥 sense,所以一開始就只是盯著這一連串的解密訊息,想說看看有沒有什麼規律可以幫助解密。結果當然是沒什麼用,直到發現 server 那邊回傳的 response 其實有很多的 500 和 403,“只有特定的密文才會解密成功,否則會回傳解密失敗” 這點讓我想到這會不會是 padding oracle attack

結果 google 之後發現這完全就是 padding oracle attack 啊 ! 所以這題才叫做 Hackpad,因為 “Hack padding” 嘛 XD

Solution

有了方向之後其實就蠻容易解的,畢竟所有的攻擊密文已經有人幫我們做好,全放在封包裡了。所以根據這篇 MSLC 的 writeup,我們其實可以直接解密原本的 secret:

以密文 997d9369c74c82abba4cc3b1bfc65f02(C1) 來說,其攻擊密文為 67acd06f7f7b28762310ce1213fccb11,padding 為 10101010101010101010101010101010,因此算出 AES_Decrypt(C1) = 67acd06f7f7b28762310ce1213fccb11 ^ 10101010101010101010101010101010

之後因為 AES_Decrypt(C1) = P1(明文) ^ C0(前一個密文),因此可以得出 P1 = AES_Decrypt(C1) ^ C0,其中 C0 = 3ed2e01c1d1248125c67ac637384a22d(前一個密文)

按照這樣的方式就可以將 secret 給還原回來:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import subprocess
import sys

def myexec(cmd):
    return subprocess.check_output(cmd, shell=True)

# "cat ./ggg": print out all the last attacker ciphertext

resp = myexec("cat ./ggg").split("\n")
del resp[-1]

temp = []
for i, c in enumerate(resp):
    if i == 0: # first line is encrypt(secret), ignore
        continue
    d = c.split("=")[1].strip()
    assert len(d) == 64
    temp.append(d)

last_c = []
enc = []
for c in temp:
    last_c.append(c[0:32])
    enc.append(c[32::])

enc.insert(0, "3ed2e01c1d1248125c67ac637384a22d")

def fix_len(s):
    if len(s) % 2 == 1:
        s = "0"+s
    assert len(s) == 32
    return s

cnt = 0
plain = ""
for c in last_c:
    c = c.decode('hex')
    pad = "10101010101010101010101010101010".decode('hex')
    s = 0
    for c1, c2 in zip(pad, c):
        s |= ord(c1)^ord(c2)
        s<<=8
    sss = hex(s>>8)[2:-1:]
    sss = fix_len(sss)

    s = 0
    sss = sss.decode('hex')
    eee = enc[cnt].decode('hex')
    for c1, c2 in zip(eee, sss):
        s |= ord(c1)^ord(c2)
        s<<=8
    f = hex(s>>8)[2:-1:]
    f = fix_len(f)

    plain += f.decode('hex')
    cnt += 1

print plain

先利用 strings 和 grep 將所有的攻擊密文先存進 ggg 這個檔案裡面,之後執行 ppp.py,即可得到明文:

In cryptography, a padding oracle attack is an attack which is performed using the padding of a cryptographic message.
hitcon{H4cked by a de1ici0us pudding '3'}
In cryptography, variable-length plaintext messages often have to be padded (expanded) to be compatible with the underlying cryptographic primitive.

flag: hitcon{H4cked by a de1ici0us pudding '3'}