[InternetwacheCTF2016] Crypto90 — Bit fipping attack
Source challenge: link
Tóm lược lại những gì chương trình sẽ thực hiện:
Có tổng cộng 4 class trong đó Randomizer(thực chất ko random gì cả, quăng args tìm x sao cho x = (a*x+c) % m ) và Cipher(simple Xor :v) là 2 class để mã hóa, còn lại là class Transaction và Account
dạo 1 vòng code và run thử thì ta thấy có những đặc điểm sau:
- có tối đa 20 lần trans và mỗi lần trans được tối đa 5000 => tất cả chỉ 20*5000 = 100000
- chương trình sẽ print flag nếu như tổng trans là 10**6 tức 1000000
- sau khi create 1 trans thì để xác nhận lại ta cần: complete <tid> <hash>
- if true => successful transaction :v
Well! How to break this one huhh?
Chắc chắn bằng 1 cách nào đó ta cần làm cho wallet của chúng ta có giá trị >= 10**6 thì sẽ trả về flag cho chúng ta
Thấy có hash…. Quay về xem class cipher xem :v
Hàm decrypt vô cùng thú vị :3 :3
It’s just Simple Xor cipher with unknown key :3
Sau khi decrypt xong thì sẽ replace(‘TRANSACTION’,’’) => có nghĩa là plaintext của chúng ta sẽ có ‘TRANSACTION’ . Nếu đoán sơ thì plaintext sẽ có dạng
‘TRANSACTION: amount’
sau khi replace(‘TRANSACTION’,’’) thì chỉ còn lại amount và chương trình sẽ gáng amount vào wallet của chúng ta.
Một lỗi hết sức nghiêm trọng đó là lúc create thì chương trình sẽ check value của amount (<=5000). Nhưng hãy sẽ đoạn này nhé
biến tn sẽ được lấy từ hàm decrypt và tiếp đến gán dồn vào wallet của chúng ta mà không có check :3 :3 với lại ta có thể control hash value qua input =)))
Một ý tưởng vụt đến. How about modify a hash =))
Chúng ta sẽ tạo ra 1 hash riêng và sau khi nhập chương sẽ giải mã qua hàm decrypt() và gán giá trị mà chúng ta muốn vào wallet
Đến đây thì dùng 1 cách tấn cách kinh điển (Byte fipping attack). Ta sẽ làm như sau:
-create 1000 và nhận về cái hash. Việc tiếp theo là modify cái hash này, vì encrypt là Xor cipher nên việc byte fipping attack là khá ezzzz
ciphertext[:12] + char(ord(cipher[12] ^ ord(plaintext[12] ^ ord(char_modify)))) + ciphertext[:13]
Giải thích:
ta có A ^ B = C
=> C ^ B = A
vậy thì ta chỉ cần cipher[i] ^ plaintext[i] = key[i] từ đó lấy key[i] ^ char_modify sẽ thay đổi được giá trị của cipher tại index của i
+ lúc này coi như plaintext của chúng ta trước khi encrypt là ‘TRANSACTION: 1000’
Nghĩ lại xem nếu như wallet >= 10**6 thì sẽ print flag => mỗi trans chúng ta cần tối thiểu 50000. Như v khá lâu. Modify thành 99999 => cần 11 lần trans thôi :3
‘TRANSACTION: 1000’ => ‘TRANSACTION:99999’
some script …
and …
với custom hash thì chúng ta đã thành công trans vào wallet với giá trị mà chúng ta muốn. Bây h trans 11 lần thì wallet > 10**6 thôi => capture the flag :3
Futher reading:
Byte fipping attack on CBC
Have a nice day all!
Peterjon