WannaW1n WickedCrown 2023 writeup
- Xin chào mọi người, mình là Trần Minh là sinh viên lớp ATTN2022. Vừa rồi đã diễn ra cuộc thi tuyển CLB Wanna.W1n và mình đã kết thúc giải ở top 6 (sau 1 ngày thi hơi choked 😥) với 2 câu crypto solve được.
Image Not Showing
Possible Reasons
- The image was uploaded to a note which you don't have access to
- The note which the image was originally uploaded to has been deleted
Learn More →
- Dưới đây là writeup cho các challenge mà mình đã giải được.
writeup available for:
Crypto:
- DHLCG
- Warm Up 🩸
DHLCG
Diffie hellman on finite field was too easy for you? I will change it to LCG then
P/S: Here is my gift even though you still can't solve it :D -https://www.youtube.com/watch?v=qWNQUvIk954
author d4rkn19ht
Attachments:
from Crypto.Util.number import long_to_bytes as ltb , getPrime, isPrime, getRandomRange
from Crypto.Random import get_random_bytes
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import random
from secret import FLAG, hint
from hashlib import sha256
def f(a, b, x, mod):
return (a*x + b) % mod
def Xn(a, b, x, n, mod):
X = x
for i in range(n):
X = f(a, b, X, mod)
return X
p = 253124343713187900774555463876030540737349270963561331390907876266826416285173608781046103998025571922987541328220629719904523466259089107010586433496746979699703152921471010925715339786724191668080154086619451623075539654108918173538947700048917690068763753304706837347078871045230506141231379595014672208368105497383
a = getRandomRange(1, p)
b = getRandomRange(1, p)
print(f"p : {p}")
print(f"a : {a}")
print(f"b : {b}")
random.seed(random.randint(1, 0x1337))
x = random.randint(1, p - 1)
AliceKey = getRandomRange(1, p)
BobKey = getRandomRange(1, p)
AlicePubkey = Xn(a, b,x, AliceKey, p)
BobPubkey = Xn(a, b, x, BobKey, p)
print(f"Alice Public Key : {AlicePubkey}")
print(f"Bob Public Key : {BobPubkey}")
assert(Xn(a, b, AlicePubkey, BobKey, p) == Xn(a, b, BobPubkey, AliceKey, p))
sharekey = Xn(a, b, AlicePubkey, BobKey, p)
print(f"hint : {hint}")
iv = get_random_bytes(16)
key = sha256(str(sharekey).encode()).digest()[:16]
cipher = AES.new(key, AES.MODE_CBC, iv)
encrypted = cipher.encrypt(pad(FLAG, 16))
print(f"iv : {iv.hex()}")
print(f"enc : {encrypted.hex()}")
print(f"complete!")
Nhận xét:
- Đây là 1 scheme trao đổi khóa Diffie-Hellman dựa trên LCG. Bạn có thể kiếm thấy bài tương tự đã từng xuất hiện ở đây.
- Ý tưởng cơ bản chính là ta có:
- Gọi AlicePubKey là A, AliceKey là n1; BobPubKey là B, BobKey là n2
- Gọi hàm LCG có dạng và nếu LCG được gọi k lần ta kí hiệu là
- Ta có thể thấy rằng mỗi khi gọi lại đệ quy hàm
x = f(x)
. Đây là thứ chúng ta thu được:
- Áp dụng các tính chất trên, ta có các công thức sau:
- Ở đây ta để ý rằng share và B đều có chung đuôi , nên ta lấy
- Thế (2) vào (1) ta thu được:
+Mặc dù trông hơi cồng kềnh nhưng ta đã có thể tính được share chỉ dựa vào các tham số a, b, A, B, x.
+Và ta biết được rằng x là số được random theo seed. Nên ta sẽ brute seed và thử từng seed một để tính share và decrypt ciphertext.
Script:

-> Flag: W1{m4yb3_LCG_w45_n0t_th4t_hard_4s_1t_s41d_t0_b3}
Bonus: thực tế thì vẫn còn hint chưa xài nên bạn nào muốn có thể thử nhé 😁.
Warm Up
A warm up challenge, like every other CTFs …
author d4rkn19ht
Attachments:
Nhận xét
-
Đây là bài đầu tiên mình làm khi vào giải và sau khi thông báo author bài này bug đến 2 lần thì cuối cùng cũng có bản hoàn chỉnh 😅
-
Nhìn vào bài toán trên ta ta có thể thấy flag được chia làm 3 phần và mỗi phần ứng với 1 bài toán RSA nhỏ khác nhau. Mình sẽ gọi là a, b, c
-
Xét bài toán a, nhìn vào quá trình gen prime, ta thấy rằng
- Dựa vào kinh nghiệm của mình thì ta có thể thấy rằng q là hàm tuyến tính tức là khi p tăng dần, q cũng tăng dần dẫn đến n cũng tăng dần.
- Vì thế cách làm là ta sẽ binary search kết quả trên đoạn từ 0 đến n. Vì n chỉ tầm 1k bits hơn nên binasearch kết quả sẽ khá nhanh.
script:
- Xét bài toán b, nhìn vào quá trình gen prime, ta thấy rằng
- Ở bài này ta thấy rằng với k là 1 số đã biết và r là 1 số random nhỏ.
- Và bằng 1 cách thần kì nào đó, thứ đập vào đầu mình đầu tiên là phương pháp xấp xỉ 😅.
- Ta có
- Vì r là số random nhỏ vậy nên có thể nói rằng =>
- Đương nhiên p sẽ có sai số so với , nhưng sai số này là khá nhỏ, mà nhắc đến nhỏ ta lại nhớ đến Coppersmith
- Bài này mình sẽ xài phương pháp tương tự với bài này
Script (sagemath)
- Xét bài toán c, nhìn vào quá trình gen prime, ta thấy rằng
- Điểm yếu chính của bài này đó là p là 1 smooth number (nghĩa là p-1 có thể factor thành tích các prime nhỏ)
- Vì thế ở bài này, ta đơn giản sẽ xài thuật toán Pollard's p − 1 algorithm
Script:
Full Script:

-> Flag : W1{Th3_s3cr3t_0f_succ355_1s_g3ttin9_st4rt3d
Kết luận
- Ở trên là danh sách các bài mảng crypto mình làm được trong kì thi tuyển CLB WannaW1n vừa rồi.
- Mặc dù ngày hôm nay mình thi hơi choked :))), tuy nhiên đề các anh ra cũng rất vui và bổ ích.
- Những bài còn lại thì mình sẽ ráng solve vào "một ngày nào đó?" 😶
- Mọi thắc mắc của các bạn xin vui lòng liên hệ với mình qua discord:
tranminhprvt01#7535
- Cuối cùng, cảm ơn các bạn đã đọc. Have a good day! 🥰