[writeup] ABCTF Encryption Service — 140

Team IA
Team IA
Aug 28, 2017 · 4 min read

Hế lô anh em.
Sau đây mình xin trình bày về cách mà bọn mình đã deal với bài này.

Source here

netcat phát

Hmm, vậy là server sẽ encrypt data mình gửi lên, và data phải ở dạng hex-encoded.

Đề bài họ đã cho sẵn source. Click thôi

Đập ngay vào mắt mình là

from Crypto.Cipher.AES import AESCipher

Vậy thì server đã dùng AES để mã hóa data mình gửi lên, vậy rất có thể FLAG sẽ nằm trong Key, hoặc FLAG sẽ có dạng :

encrypt_data = sent_data + FLAG

Ok, tiếp tục

Hmm, padding 16, vậy đây là AES ECB với block là 16 byte, chi tiết này có vẻ quan trọng :v

Nhìn vào hàm encrypt() nhìn thấy ngay FLAG is not KEY, và FLAG sẽ được gắm vào data mình gửi rồi sau đó sẽ encrypt rồi loằn ngoằn sau đó trả về cho mình ciphertext.

Với kiểu block cipher thế này, thì mình có thể dễ dàng tìm được độ dài của FLAG. Bằng cách thử truyền từng byte một lên server.

Nhìn thấy ngay, khi truyền 3byte ’41h’ lên thì độ dài cipher là 2 block 16byte, truyền lên 4byte ’41h’ thì độ dài cipher tăng thêm 1 block. –>

3*16 = len(‘ENCRYPT:’) + 4 +len(FLAG) + 16byte padding
3*16= 8 +4 + len(FLAG) +16 byte padding

— > FLAG length =20 byte

Mình chỉ có thể truyền vào byte mà không thể đụng chạm gì vào source….vậy làm sao để mò đc FLAG.?
Mất khá nhiều thời gian để tụi mình tìm ra phương pháp. Cơ sở chính vẫn là dựa vào ECB

Vì các block đều được mã hóa giống nhau, vậy mình có thể padding để kiếm các block giống nhau rồi so sánh được không? Chắc chắn được.
Block đầu tiên có đoạn ‘ENCRYPT:’ (8 byte từ giờ mình sẽ gọi là 8E) vậy mình phải truyền 8E vào block phía sau để có 2 block giống nhau.

ví dụ:
Block 1: 8E + \x41\x41\x41\x41\x41\x41\x41\x41
Block2: 8E + \x41\x41\x41\x41\x41\x41\x41\x41
Hmmm, Python tí

Chạy thử thì thấy kết quả như này

cd7985389a47184ce3f957b15a1c45f3
cd7985389a47184ce3f957b15a1c45f3

2 block đem ra thí nghiệm cho cipher như nhau. Vậy nếu thử
Block 1: 8E + \x41\x41\x41\x41\x41\x41\x41 + 1 kí tự brute force
Block2: 8E + \x41\x41\x41\x41\x41\x41\x41 + FLAG[0]
Tại sao là FLAG[0]? — Vì block 2 đã đủ 16byte rồi, nên phần còn lại của flag sẽ nằm trong block tiếp theo.
-Kí tự mình brute force nó là 1 phần của FLAG vậy nó sẽ nằm trong các kí tự đọc được

Khoảng 96 kí tự NHANH THÔI< NHANH THÔI :v :V :V

Thử sửa code để chạy trong trường hợp này.

Flag có dạng ABCTF{xxx} vậy mình có expectation đầu tiên là khi bruteforce đến kí tự ‘a’ hoặc ‘A’ thì 2 block sẽ giống nhau.

Chạy phát

hmm đợi chờ là hạnh phúc

Ơn zời, cậu đây rồi.

Vậy thuật toán là ok, chính xác rồi. Sau khi có byte đầu tiên, mình có thể tìm được các byte tiếp theo của FLAG bằng cách giảm số byte ‘\x41‘ truyền vào.
Vấn đề còn lại là, nếu chỉ xử lý với 2 block liên tục như thế này, thì FLAG lấy được sẽ chỉ là 8byte đầu của FLAG, trong khi FLAG bao gồm 20 byte :o. Vậy mình phải tăng số block mà mình brute force lên.FLAG cũng không quá dài, nên mình tăng phạm vi thêm 2block nữa

Block 1+2+3: 8E + \x41*39 + kí tự bruteforce
Block 4+5+6: 8E + \x41*(39-(len(FLAG)))

Improve code cho trường hợp tổng quát này:

ABCTF{p4dding_4_fun}

Với code như này, số các trường hợp phải thử sẽ là nO(n) nên nó cũng không mất quá nhiều thời gian để quét hết các trường hợp nên mình có thể để nó chạy dần dần và ngồi đợi thôi :v
Tệ nhất thì mình cũng chỉ phải chạy len(t)*len(FLAG)*sleeptime ở đây nó rơi vào tầm 768 giây. Nghĩa là rơi vào tầm 13 phút, cũng không quá lâu nhỉ

Thanks for your time :v

-H3xX0r-

)
Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade