Chào mọi người, mình là Mai Đăng Khoa. Vào 05/10/2025 mình có tham gia giải WannaGame Freshman 2025 và giải được 4 bài crypto. Đây là writeup của 4 bài đó.
---
# phiphai
## Đề bài
```python=
from Crypto.Util.number import *
flag = b'W1{?????????????}'
m = bytes_to_long(flag)
e = 0x10001
p = getPrime(1024)
q = getPrime(1024)
n = p*q
e = 65537
phi = (p-1)*(q-1)
d = pow(e, -1, phi)
hint = p+q
c = pow(m,e,n)
print(f"e={e}")
print(f"d={d}")
print(f"hint={hint}")
print(f"c={c}")
'''
e=65537
d=4504287984018183537713208161402766323065548618393723872837173606374276398491834181934336417310620387990925189536232872881499528612504958202701279049935780903977608853793957819684386053139789777966936156264230499424635837453895019683637553474699470241265384239892304309743522811693909773853204104744746499940669186347989219693819334120860342801601135658920550816397929837218587842050717426094705159184294217221659550021174121437354727563286401517383250923022292331155286641664114777714280910808217996581853423619501922201519238297960634332127751600929842715997073072544823353485994644594610107896462399877655553045761
hint=231925193905919836406214406898885408169720762556845482044575179755202576770665967750292209535638389585617923204488598005919071680696574306168950409350364369661185363429309191455686049593246205245617043129829360203967945465085196018291809693305049028207915207766096530755343783712735226590596701430255772594556
c=6217038084836470023310381029897048208087224587728895918727075557465841714766785434203795384404277685883194699549944699326316064489862857903738642081680285228167738881574533344177255570731527611503589831001734795490242158816621194509455025049486128406587545324515046616431849802141624745659660349892441242897503306780984369111460208907969417056103375189617092555003582813739896435112054576310776891033107119212517760203084951964632014280482552024983115272574743031704179104705817029355755554440364213319205880788661502753344785708858216051846295494426952842154398100557142240912181225765846610290283305931102820798460
'''
```
## Ý tưởng
Khi đọc đề, chúng ta có e, d, hint, c.
Để tìm ra flag, trước hết ta phải tìm được n bằng công thức:
$$
n = p q
$$
Và mình nảy ra ý tưởng bằng cách tìm p, q bằng hệ phương trình sau:
$$
\begin{cases}
p + q = hint (1) \\
pq = n (2)
\end{cases}
$$
Ta có thể biến đổi nó thành:
$$
x^2 - (\text{hint})\,x + n = 0(*)
$$Với p và q là 2 nghiệm của phương trình
Nhận thấy rằng:
$$
\begin{aligned}
d &\equiv e^{-1} \pmod{\varphi} \\
&\iff de \equiv 1 \pmod{\varphi} \\
&\iff de - 1 \equiv 0 \pmod{\varphi}
\end{aligned}
$$
Từ đó suy ra:
$$
\begin{aligned}
k\varphi &= de - 1 \\
&\iff \varphi = \frac{de - 1}{k}(3)
\end{aligned}
$$
Đồng thời ta cũng có:
$$
\begin{aligned}
\varphi &= (p - 1)(q - 1) \\
&\iff \varphi = pq - (p + q) + 1 \\
&\iff \varphi = n - \text{hint} + 1 \\
&\iff n = \varphi + \text{hint} - 1(4)
\end{aligned}
$$
Thay (3) vào (4) lúc này ta có:
$$
n = \frac{de - 1}{k} + \text{hint} - 1
$$
Xét lại phương trình (*)
$$
x^2 - (\text{hint})\,x + n = 0(*)
$$
Ta có:
$$
\Delta = (\text{hint})^2 - 4n
$$
Và nghiệm của phương trình:
$$
p = \frac{\text{hint} + \sqrt{\Delta}}{2}, \qquad
q = \frac{\text{hint} - \sqrt{\Delta}}{2}
$$
Giờ thì ta chỉ việc chạy trâu k trong khoảng từ 1-200000 để tìm ra nghiệm p và q nguyên dương.
## Code
```python=
from math import isqrt
from Crypto.Util.number import long_to_bytes
#du lieu goc
e = 65537
d = 4504287984018183537713208161402766323065548618393723872837173606374276398491834181934336417310620387990925189536232872881499528612504958202701279049935780903977608853793957819684386053139789777966936156264230499424635837453895019683637553474699470241265384239892304309743522811693909773853204104744746499940669186347989219693819334120860342801601135658920550816397929837218587842050717426094705159184294217221659550021174121437354727563286401517383250923022292331155286641664114777714280910808217996581853423619501922201519238297960634332127751600929842715997073072544823353485994644594610107896462399877655553045761
hint = 231925193905919836406214406898885408169720762556845482044575179755202576770665967750292209535638389585617923204488598005919071680696574306168950409350364369661185363429309191455686049593246205245617043129829360203967945465085196018291809693305049028207915207766096530755343783712735226590596701430255772594556
c = 6217038084836470023310381029897048208087224587728895918727075557465841714766785434203795384404277685883194699549944699326316064489862857903738642081680285228167738881574533344177255570731527611503589831001734795490242158816621194509455025049486128406587545324515046616431849802141624745659660349892441242897503306780984369111460208907969417056103375189617092555003582813739896435112054576310776891033107119212517760203084951964632014280482552024983115272574743031704179104705817029355755554440364213319205880788661502753344785708858216051846295494426952842154398100557142240912181225765846610290283305931102820798460
num = d * e - 1
#tim k
for k in range(1, 200000):
if num % k != 0:
continue
phi = num // k
n = phi + hint - 1
delta = hint * hint - 4 * n
if delta < 0:
continue
sqrtdelta = isqrt(delta)
if sqrtdelta * sqrtdelta == delta:
p = (hint + sqrtdelta) // 2
q = (hint - sqrtdelta) // 2
if p * q == n:
break
print(f"k = {k}")
#tim flag
m = pow(c, d, n)
flag = long_to_bytes(m)
print(f"flag: {flag.decode()}")
```
> flag: W1{phi_phai_la_game_rac_so_1_vn}
# phiphai2
## Đề bài
```python=
from Crypto.Util.number import *
flag = b'W1{???????????}'
p = getPrime(1024)
q = getPrime(1024)
e = 65537
n = p*q
leak = (p**2+q**2) % n
ct = pow(bytes_to_long(flag),e, n)
print(f'{n = }')
print(f'{leak = }')
print(f'{ct = }')
'''
n = 20842938351896783351765564497257406689875073939168847270109018452331595953195137925905407574790509131975169442262183423216630782056006817670026102637100795102868553295795605909294220001159170312214938967565708237131119660898946450453038715919305770854433454485282482531591669338374784896696254086081923985254456532726474557269047987653955703675146699130077388795028830171715932232259532178061195603162554212575207799198670246556909810593997402979919324116015029695269687378794139114073155816838415492318483626370434226417328166879349978988600491401399315534138391936796615782306743416152563145103425347897571269559877
leak = 1246889223294307854370712989427585884021285335323141671816486223380713311286629425480810174036551750931478373626071781038942054037291709281118654737087599035092443005799430352628570933778452108536502272580400092528062848455445985692614774855796791907610933670663580901476953467808284328166657791568856558571935788405193538986947393116928493787198798661826785549975721130971676199856446097879499458065034678153636052702160287204920680541565366139294026010089009061274372587986143754097126566624340639998228509117420424679732985956823117206903025894886029533740978018513157416105341714161360196840042575896512731742096
ct = 3088291167300681828911890341254838261507896143994085977627215978594078495952883007565773809797879150841185401282724413230256089706081482055304607098189837372445021022139016449305819308800001848241222118389290692225549475347019810385147707744883436586629808823247373108273012523932858309484832402796522454251129915341722714855738383668651266661352021406899104266596812402238487015961091455318371807234925900608259741913811110018686747303985152505270333578971573169716269092799613880511496142576903738948348527279101539196915559331086705114365249818982213416798535758240324625059044600889754519687795415852504666992830
'''
```
## Ý tưởng
Nhìn vào đề ta có n, leak, ct, e.
Để tìm được flag, trước hết ta phải tìm được p, q, sau đó tìm ra phi, rồi ta tính ra d và cuối cùng là giải ra kết quả.
Ta có:
$$
leak ≡ p^2 + q^2 \ (mod \ n)
$$
Mà:
$$
p^2 + q^2 ≡ (p+q)^2 \ (mod \ n)
$$
Vậy từ đó ta có thể suy ra rằng:
$$
(p+q)^2 = kn + leak
$$
Gọi:
$$
S=\sqrt[2]{kn+leak}
$$
Ta tiếp tục xét phương trình đã đề cập ở bài phiphai:
$$
x^2 - (\text{S})\,x + n = 0(*)
$$Với p và q là 2 nghiệm của phương trình
Ta có:
$$
\Delta = (\text{S})^2 - 4n
$$
Và nghiệm của phương trình:
$$
p = \frac{\text{S} + \sqrt{\Delta}}{2}, \qquad
q = \frac{\text{S} - \sqrt{\Delta}}{2}
$$
Ta tiếp tục chạy trâu k từ 1-200000 để tìm ra p,q.
Sau đó ta tính được:
$$
\varphi=(p-1)(q-1)
$$
Và giải như một bài rsa thông thường.
## Code
```python
from math import isqrt
from Crypto.Util.number import long_to_bytes
#du lieu goc
n = 20842938351896783351765564497257406689875073939168847270109018452331595953195137925905407574790509131975169442262183423216630782056006817670026102637100795102868553295795605909294220001159170312214938967565708237131119660898946450453038715919305770854433454485282482531591669338374784896696254086081923985254456532726474557269047987653955703675146699130077388795028830171715932232259532178061195603162554212575207799198670246556909810593997402979919324116015029695269687378794139114073155816838415492318483626370434226417328166879349978988600491401399315534138391936796615782306743416152563145103425347897571269559877
leak = 1246889223294307854370712989427585884021285335323141671816486223380713311286629425480810174036551750931478373626071781038942054037291709281118654737087599035092443005799430352628570933778452108536502272580400092528062848455445985692614774855796791907610933670663580901476953467808284328166657791568856558571935788405193538986947393116928493787198798661826785549975721130971676199856446097879499458065034678153636052702160287204920680541565366139294026010089009061274372587986143754097126566624340639998228509117420424679732985956823117206903025894886029533740978018513157416105341714161360196840042575896512731742096
ct = 3088291167300681828911890341254838261507896143994085977627215978594078495952883007565773809797879150841185401282724413230256089706081482055304607098189837372445021022139016449305819308800001848241222118389290692225549475347019810385147707744883436586629808823247373108273012523932858309484832402796522454251129915341722714855738383668651266661352021406899104266596812402238487015961091455318371807234925900608259741913811110018686747303985152505270333578971573169716269092799613880511496142576903738948348527279101539196915559331086705114365249818982213416798535758240324625059044600889754519687795415852504666992830
e = 65537
#tim k
for k in range(1, 20000):
SS = k * n + leak
S = isqrt(SS)
if S * S != SS:
continue
delta = SS - 4 * n
if delta < 0:
continue
sqrtdelta=isqrt(delta)
if sqrtdelta * sqrtdelta != delta:
continue
p = (S + sqrtdelta) // 2
q = (S - sqrtdelta) // 2
if p * q == n:
break
print(f"k = {k}")
#tim flag
phi = (p-1)*(q-1)
d = pow(e,-1,phi)
m = pow(ct,d,n)
flag_bytes = long_to_bytes(m)
print(flag_bytes)
```
> Flag: W1{i_hope_you_like_this_one}
# Vi-et
## Đề bài
```python
import sympy as sp
import random
from Crypto.Util.number import *
a = getPrime(128)
b = getPrime(128)
c = getPrime(128)
x,y,z = sp.symbols('x y z')
print(f'a * b * c = {a*b*c}')
print(f'a + b + c = {a+b+c}')
print(f'a*b + b*c + c*a = {a*b + b*c + c*a}')
flag = f'W1{{{123*a + 456*b + 789*c}}}'
"""
a * b * c = 15864378984956659850534060107405422568891641699308509134070157505662198692417476378386001170963905568690006431674713
a + b + c = 779122598205443694565344617967399722167
a*b + b*c + c*a = 196487786916397904192643381759626074607590751745631772329891131596526673844879
"""
```
## Ý tưởng
Nhận thấy bài này yêu cầu phải giải được hệ phương trình viet đã cho. Nên mình quyết định sử dụng thư viện sympy để giải ~~vì mình không biết giải tay~~.
Và khi giải ra ta sẽ có được tổng cộng 6 chỉnh hợp của a, b, c. Khi đó mình sẽ thế từng chỉnh hợp vào flag và submit láo để tìm ra kết quả.
## Code
```python
from sympy import symbols, Eq, solve
a, b, c = symbols('a b c')
eq1 = Eq(a + b + c, 779122598205443694565344617967399722167)
eq2 = Eq(a*b + b*c + c*a, 196487786916397904192643381759626074607590751745631772329891131596526673844879)
eq3 = Eq(a*b*c, 15864378984956659850534060107405422568891641699308509134070157505662198692417476378386001170963905568690006431674713)
solution = solve((eq1, eq2, eq3))
print(solution)
```
Sau khi chạy file này mình sẽ có được 3 số là:
173765774214092292255311904274089510307 284881463704823367455830769292310355251 320475360286528034854201944400999856609
Mình sẽ thế lần lượt 6 chỉnh hợp của 3 số đó vào source gốc:
```python=
import sympy as sp
import random
from Crypto.Util.number import *
a = getPrime(128)
b = getPrime(128)
c = getPrime(128)
x,y,z = sp.symbols('x y z')
print(f'a * b * c = {a*b*c}')
print(f'a + b + c = {a+b+c}')
print(f'a*b + b*c + c*a = {a*b + b*c + c*a}')
flag = f'W1{{{123*a + 456*b + 789*c}}}'
"""
a * b * c = 15864378984956659850534060107405422568891641699308509134070157505662198692417476378386001170963905568690006431674713
a + b + c = 779122598205443694565344617967399722167
a*b + b*c + c*a = 196487786916397904192643381759626074607590751745631772329891131596526673844879
"""
```
Và kết quả đúng khi
a = 284881463704823367455830769292310355251
b = 320475360286528034854201944400999856609
c = 173765774214092292255311904274089510307
> Flag: W1{318278380181268876680024363742066731941800}
# System of Equations
## Đề bài
```python
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import hashlib
import os
FLAG = b'W1{???}'
x = int(input("Nhap x nguyen: "))
y = int(input("Nhap y nguyen: "))
z = int(input("Nhap z nguyen: "))
assert x**2 + 2*x*y - 8 == 4*z**2 + 4*y - 8*z
assert x**5 + y**3 == 10823714993004958804353333960725385073542379465721 - z**4
assert 8864612849141*x**2 + 8864612849141*y + 17729225698282*z == 205022233466935232483321764396
mode = str(input("Nhap phuong thuc (encrypt hoac decrypt): "))
secret = (str(x**10) + str(y**10) + str(z**10)).encode()
key = hashlib.sha256(secret).digest()
if mode == "encrypt":
iv = os.urandom(16)
c = AES.new(key, AES.MODE_CBC, iv).encrypt(pad(FLAG, 16))
print(f'iv = {iv}')
print(f'ciphertext = {c}')
elif mode == "decrypt":
iv = b'\x8d\r\x19\xbc\xfd\x84\x13N,\xf85\xdb\xd3\x92i\x93'
ciphertext = b'\xe9\xa2\x8c\x8b\xc3\xb4\x88\xe2\xbb\x96\xc6\xac`\x1c}\xd1\xca\xc1ZB\xf1@\x01\x92\xca\xc4Z[\x96o\xdeFv\xdf\r\x13u+\x89\xac3\xa3\xc9X\xfb\x07u\x1bO\x9c\xb0\xbdN\xa4\xb6\xca&T\xabmx\xdb\xae\xc2'
FLAG = unpad(AES.new(key, AES.MODE_CBC, iv).decrypt(ciphertext), 16)
print(FLAG.decode())
else:
exit(1)
```
## Ý tưởng
Bài này mình hoàn toàn giải giống như bài trên ~~vì mình tiếp tục không biết giải tay hệ phương trình đó~~.
## Code
```python=
from sympy import symbols, Eq, solve
x, y, z= symbols('x y z')
eq1 = Eq(x**2 + 2*x*y - 8, 4*z**2 + 4*y - 8*z)
eq2 = Eq(x**5 + y**3, 10823714993004958804353333960725385073542379465721 - z**4)
eq3 = Eq(8864612849141*x**2 + 8864612849141*y + 17729225698282*z, 205022233466935232483321764396)
solution = solve((eq1, eq2, eq3))
print(solution)
```
Kết quả sẽ ra là:
x: 33131538, y: 22029258543363862, z: 604095676625
Và mình thế x, y, z đó vào source gốc:
```python
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import hashlib
import os
FLAG = b'W1{???}'
x = int(input("Nhap x nguyen: "))
y = int(input("Nhap y nguyen: "))
z = int(input("Nhap z nguyen: "))
assert x**2 + 2*x*y - 8 == 4*z**2 + 4*y - 8*z
assert x**5 + y**3 == 10823714993004958804353333960725385073542379465721 - z**4
assert 8864612849141*x**2 + 8864612849141*y + 17729225698282*z == 205022233466935232483321764396
mode = str(input("Nhap phuong thuc (encrypt hoac decrypt): "))
secret = (str(x**10) + str(y**10) + str(z**10)).encode()
key = hashlib.sha256(secret).digest()
if mode == "encrypt":
iv = os.urandom(16)
c = AES.new(key, AES.MODE_CBC, iv).encrypt(pad(FLAG, 16))
print(f'iv = {iv}')
print(f'ciphertext = {c}')
elif mode == "decrypt":
iv = b'\x8d\r\x19\xbc\xfd\x84\x13N,\xf85\xdb\xd3\x92i\x93'
ciphertext = b'\xe9\xa2\x8c\x8b\xc3\xb4\x88\xe2\xbb\x96\xc6\xac`\x1c}\xd1\xca\xc1ZB\xf1@\x01\x92\xca\xc4Z[\x96o\xdeFv\xdf\r\x13u+\x89\xac3\xa3\xc9X\xfb\x07u\x1bO\x9c\xb0\xbdN\xa4\xb6\xca&T\xabmx\xdb\xae\xc2'
FLAG = unpad(AES.new(key, AES.MODE_CBC, iv).decrypt(ciphertext), 16)
print(FLAG.decode())
else:
exit(1)
```
> Flag: W1{y0u_must_b3_th3_m4st3r_0f_3quat1ons_817e31a7ccdbe8fd}
# Baby Crypto
* supported by: R1muru
## Đề bài
hint:
```
Từ nhỏ, tôi luôn tò mò về ba điều kỳ lạ:
Số 13 là số nguyên tố nhưng còn 1 ý nghĩa gì đó đằng sau nó mà tôi chưa biết...
Vì sao một chuỗi ký tự bí ẩn lại có thể dẫn tôi đến một video bí mật?
Tại sao lại tồn tại một thế giới mà ở đó lại xảy ra chuyện hoang đường: 1+1=0?
Hành trình khám phá ấy biến thành chuyến phiêu lưu, mở ra cánh cửa giữa toán học và thực tại ảo.
À đúng rồi, tôi quên đưa bạn chuỗi ký tự bí ẩn: XmoUNb2=|CcXxL#d2e-ebz)^MV{dIQcVTp6Xg_v6WKnlCcR5#QSYuH
```
source code:
```python
#!/usr/bin/env python3
import os
message = '???'
FLAG = open("flag.txt").read().encode()
assert FLAG in message
def cauhoi1(text: bytes) -> bytes:
return ???
def cauhoi2(text: bytes) -> bytes:
return ???
def cauhoi3(a: bytes, b: bytes) -> bytes:
return ???
enc = cauhoi1(message.encode())
weird = cauhoi2(enc)
key1, key2, key3 = [os.urandom(len(enc)) for _ in range(3)]
ct1 = cauhoi3(weird, key1)
ct2 = cauhoi3(key1, key2)
ct3 = cauhoi3(key2, key3)
with open("output.txt", "w") as o:
o.write(f'ct1: {ct1.hex()}\nct2: {ct2.hex()}\nct3: {ct3.hex()}\n')
# I will give you a chance with my last key :D
o.write(f'key3: {key3.hex()}')
```
output:
```
ct1: 944073d9c2fdec4334375867fcd9b0c4545d20152151f6d008259a14ea339e4e0a38167ea99fd4817b4e22565772b28c5b6781c67bf16c0c4f4e0efdeaf21f0a5a7e96bff3e8a39008788fd8256c2b522c6d9b446a29e456dee859f536ba1241e5df09a25ea1abf820ab0358c554afaadf371e02b2dc6f949da28f539b4d9845d962a9899280c2301b8be293c69a241d8e39059e9fbf3fe3772b0500505867df29e4afacd12578114bbb48d17ebf9779d784d05e2479dfccc072c814a1b4d6d8286da2d553b1726a5f2590a9d80604fc7038bb6f2f3999f23d4e37626760d4035fb8cc10bdc66ea4b0a8b9a82283c1a1680f0ca91c226ee2a1af6e8dbd03b5d47c88d6e90f5505f02f7e4e5c03c3cd2ba4e66e2049ec32b4032aae025a9065dec4744aef76926beefe5f7a560a3d82e0c603348081889bcf4ec751be9b899cb23a0c117d8c15b0c9e7e217f92f024d8ed2c028e36eb5bbdc332f04981bf05226ab15dda261e569e8869b97228021c84f454d18570a6120dc40d30679154997b91d1398ef2dd166fa64ee1169c550f506013a327c34889eb0b172878f356ec042d3a22c52a3ed99536fbd6f6f1c2058f25c2314adf4190782e542644af809fd80728c7bfd9a53016565615f1cbe323ea5057679ffd8cdaaa29ea41cb3df37aecbb669e0339bbc52ab3885bbb7eef8273f5dbfeeca6d96efda197004473fe41ba54b1a898f0f30f3ec0b253b8d3555ae0a7948d74b2f083c3cf26035f9b97819124dd930c2747950bf0d6d35e7d82a7f8d3f0a7c8ef012b6926efea881d877e9acbf16a883a98d292193fcbf332cc8a5b6b732abc3cbff2e9e19531053759cae090eaf90b7b8357c9351aeacb13c4c03b1fbf8eea7a35ce1ee793f530eae06e55fe536d0ec0c5a4e70a4f6735a240ac0e38713d14ffa32c88927908b3f273febc81e268fe4a6473f8f0e3fca74c436e08e1f1b3690d0b41b29a519bdf7ba78e6fd0dc915dc78609eaf16c4cedc3a71c406b2bbfb0bfe6d86e9e2e00d6f7a1dc8be264751cf3e84bf58cd266b3f33e0948df9d5fcee3b1405192c5401d0bd3b97839260165935e254d64cbf4a2ea318bfe17fcf241f082e8b0ec78dc68369b02d1e1d9900184fe3b62bf56cc4ed66c0dccd433beb8585295cd478d3216eea43f258da09e7011549d9235e4763c57f46e985b6f2e9561157688e266e67b35e1ee8180c00d26b14cea81417b6244175d48d2381364d4fee04df5ea1aadacc07653f1e4857550648644dd62924caa4bf6d9df4cf2fb66e4b4287de8bcbb4fa45d06c1f54256e34639b2ec6cb8e9c9bbb0ad655b6e65c4372688ccf44e65f263f2b677f800e5b4a9464c611e51c1ad31637b7933313bd73e037e0a738ef0d782427a0b56c255dc9e1febf42ed6cbefc27f138aaf00336992a2e970d597bd037f05ff6cc92477a3528c5daaf6bd3c8d47c67ed6f91a4348ea43125352f34842843bb467220097384291a43b098a6c41611041fbfa9900a7733129710436da9c991a08c50eba4ebb7b22165a111cadbb0c86f6448f574857b561fa0813528ae886ad0e80192b53c21c831a317e7f2fea1521f8b3e237b79e40245feac47ae9a8d99fd1ee8f11aaaf8cc6fd7b1a066ae9299b210c55b7651b2052a4be88fd1eb3a85f515adb388d504507236464ef0c83151001e0035b6e55de0bd5091305cca1002de0d4b0fe920ddad16232d0cf82e0c7588399bad23a3bfdbcdda2fdaa532c2f421bc25480e395f5db0d724748b3751156c29348494c88d4fbc75b6a9997dd714a66228f1099f2d36ecab036d77728183c704beae2cfb594dd8484c0d2b299626e1413a584fef756c73945200f16cf05b79568dc94b56dab9569adcdd000d55aa04b35115ec11ba53bd8a05e576d5956b4df9170b6e65c9849a6204fb62c98ef2b8d3d138f95d0335180831ebee7f5583e737c4782895f082defaae68775825a2ab34403347261a6fd497ee7a9eadf050e9954a01b173aaf5e9a21a03d66f
ct2: 770178bcb4c79bb17a3e9d3fae37aff128817b9528af0fd6ba9b35638095318ca7c640c7b5f4ca9dd5621472887287fc07d9bdeea79c6c68d059cc3e497c036e8fbf6b9ed480d3b4be6069dd834c6a9a162ba2a879cdf7286697670c9d299086e79844760caff21366ebf507d59fe40a0a59fca4df49fb306937faeb4d3b6ad266c2def5b5d78ef5cb6fd66a2e4cbe251d54e71478f539a82683d7f403e583bddcd0db7bf992c6dc1d50de5066c209bf14995e92b0383437719e3f93ccbc9eda83674d770d7d29b182e7fe3f1b791de8231645dfd3c258ae65fec2e1f1e9693c4f138b3b3c714385285fe25c7ab1a7c77c64c974e003c2d0ca4c144f7a6ebeba7d556aefe0929658b96b9252e7c3682a611915583da9c20ca84d3ef1b551f41c5f2adfb76970f8653342064587693dba7318d8118dd1f31ef27f22caad90c1f9145d71074fed2d81928c29d077ad92b679fe8d79ded8c62ca8bf53218df5439b1a81d6f21df99e0432c67f6002a0155b82f0f6953b6c5a5324df90333fe1c731f792e3f27fdc09047b13de99fcc1763cd1fe7a0587becbbf2ce09b9897c6325258450055c49bcf3506db1a2b055f7a029e99f1343888d8d8fa4a84be11ca1f5b85ffbf00b96dc61d05db4b446eba1a53aae9bdbac981d7046ca3158e67cf7e3f9c357fea73718d61da1e0fe42a4e4f10490495deee5174f02326b591b7dbf8d0e52841faf4da6b469d250f65ed794f08c438307752ab5368db551da6aba167bbf3ddb34e54f4ce725512721343714338901492fa298db176449277011ae92d252a7a9c5aac970dfd004329fdb2b0ca7a6d543ee133ed5a3d31e0a1b15a07cb366a25d5569eb124d74237604688fabc5bdec532ef76825d8592e910f6e59b843e8487605e0d823af50b0dea4bd199a9e52818fd90de3194fc0c9e3d30de743301a154cf08e40068234acdc8b4e5b39ca8f0053439db32b029ecc44b74998635d433eaf174b5946715e5ffdb21e3315f3a412c7e2b6ff53832befd256164ef47697dece91de9e7bc2d0095bde64422ef708223d6c0e59f0e0762197d59846b0c9f3060edc4cabc79e01acc72c8580af50b959b2436dde3753fa316cfd9a789facb770c3afdf04a183e897ff5b5b8366f8c3092b1d1ab0975c0f83b0a1da0a1e105cc067339bdee25f82d9a5e02d8ce593691e370e1ca297849e9e932d0773590a61a4ff645b468ad0d9fc0d1899e2ff5aa168d61fda073792e33c50f4a566385b87566afc14449b4fb9ac662a0f9267a872565f6e3458c24999c3972524c7015ad02ed24d93268d362b32ea6f6ea00ebabbae9968cab114f8f835a03802850951f5c16c5446d5f2910b1e72618e453b21e132b2275608471915271e019efc6324a88af1ec0a2c0840f676c64636ac7e8801f67befe418557956f9fb8274031392cb121b5f73434f30436a486f13cb36e39a9ee3bef53a1acbb90340755c2a06a6f1c21fb9f9ac3e520e20a90b952378d2759ae789ab26acbed14fab5d2d5c40e420a356c7ff0050d7368efd10cea07d9a1d7eeecc91ce13a066c93690a513d3cc7b1bbd468575aeb7b3563d60b82613b9ae50c5df8f26ae5bfe84677cc54898d504644e5b423ba47b507b30d495dbaa2e5f87f780be3b9562c1bfe1a1f79d828c4867274d2b5b31ef750f965d4a84dbadef33871e435d61425578fec1f1f6651d615fde35697e31162658239110e4b0ccf1d05e50ac275a82ddc8f7920dda8021f7c14e36692eeba0f2421151f3496566e2e176c6a4d89058d19479b89e043e1e4bb63f892c9134a5100a3b574afa9f7e6c6688e71ad3038c37587a6efb417e0473e06e14ad083b825c7f1caf0e9e61003da38fe526e421e1abad336ffe81fa166d7ff8714bb1972547f08e0cbb80355387f87ffcea8219f96a108f71e1474b68fd46dfda7bcfe899b9e752f7dbc68cf252f31a68435165de7748460b86341f6e3b10d6f5c3f7e6e813fa5ef538380914e127f21f728e0eb3370597c
ct3: 9a1019a263bf5c2b7473e7afe4c447db8b621e1b68ff78306e2a9f179b0cd3cacc544c3dbf8051f4d4e8bd9f921d07a6a757016bacfcf5075e895f7076303f845a2e7b6971184040cd98d6ceb90ce321afc89374230910051da77a080f544bf0f2c59dade7cb76d055763a9759ef7063d603012e2e525a7801d7928cdf68346883580415447e297107822d298b21522c472a9828b19667dd83cd3250a656f0976a320c35af7660b40900a6b714d6d531a63ea20c1c1982a959d87fe5fc502a0932a688c4530ebb9abb5d696fb8f29eaefdbdd5683d44c3438418c3c8469345fbdb2de1c230c5d36a0aba17fb671dd5b952903e314cdbf467263feedfa1c470879a91b2008600af5f7b69004a34ac6274e4484ea383caf910be86dfa19c43a38518254a04699a54c5718363e9c2a16e56d91bb4e2373069fd9934bfef2b853a79554f57ea4a7c8f199853122df8e556c0b4cb51894c0f5a232555242d2e48ec554bbdadaf5b4baa2cb6cbefe4463422fad383723f9757ad71fd594dbc984a54939b37c19634e62cf10f859e2a712ec603c15bff5526ab6248be1f118c5afa84181d067e4e9f1c0176a2753880634c148518c169a3aa695f12b68d54c4a9f8f976d3a6b0420ac0a39d51638c71199d87b5f185fdc4298247dced58026e3f9ab79424ebda18e8053d5e508f66137fa632b9a5dcd4a25e4d9c5bda508ea9d1a2afb01511387e3b5d3f985e6ac97c7cb8614b316d3a3838acdd808c23d25c19cfd2116cecbda92cae83deb555c8ae8cc983aac571c9e4365a0c0d077a401df2bb8596f7d457f093367b0e49a1a11e79c7723d20a9e4b54d535a945e958323c4d39b648fd314dbb4afafad01c5504cc860f891f89d60a4d87dd90e53b89192bacc0a935c3253dc5f8454f776305d418734b3d5e4c71b6dabcc3230141f2e92129f415ccab55e1d81f07ea8709b008026001d994dad50cb1583a3b141e0a9fa5a2fb20b82558f04090f889b7f9bec4a5055a5f3ef60b278f5fc2c6ed8c51f826b9cc5be88cf667d8f7394342a7735b65001c766ec62f0a94970d90cf94d4d53f6ad8d273f2c6163390321578b2835e396072b6cbf7876e46e24c14a821b85a5be90b34147f0d8e553e361709c7871dda118dac4e1a11b254fe6eaeec628289e6a6fad2d1382c6602dd92b5026a123b1a6d972d9c4000c480574ce1c2c45e33c5437d469857a427964e05ec79ade151943ab01c33bc6e4eff64d81515851f08b3ba64854683217595397161173a47e5de056b290dc47324c68fa47ce7a53c19048d72b549bfa70f2d9f8e06e3d27214be154f9668b02bfcf69576c15ce42e6736e4dff74a21f3754ff7e4ad396132435f19ae605dbdbffba84f99898ca7fb51055af2093658eab899a06318a0e30b01c3b731df1f22751bbce2db6f2a1bd695b386b42203327fb51fddfc616c838f046e6aa6af7149335b43460d6e578eac6c0d3950c3577957ada59d1a68bf12b652a4bdde7cc7dbe304f3e608dd0581439394c3f3e73bb79ef288bdda8d7bc6d2f4b1d31997e320005a92426ea75264fce6fcfd256a17290cac2a62c29dfbfe7e9b0c31ce48643612a949277ac98b6403cd94a99a5c187067562f63377bf7819fa3f0a626dd9d3d53238e60b2603d5cf9ec83ef5c028841799fa11e213c43a549aa1916ad48b27bbd894a7a4825ad2cbf25cec2dacb1da3a22b916a5f2988c17c624f7100d8c9fe6331c3c04f81653798935dfb231ff2802cd8d01700f17e77fbb794dffd6bec64fb8158202f2b989d8a6df2d5970b83f75c9ea6d4b372069254d4bbb926db3cc2758c5a95e573a9af016ace085db954561900a867490a99df789435589bc471936e159521daea5e4a5a90fc37f657cb5c694ff39fa35ae59f45dad5088e923319caa5afd9c46d974a498d339c6b05cd06d07cdda7648d60c6153b452c734e4935cbb3bcf22b3433a8dcca328bc147e697cadd0bd2ff0d0f4c93bf17af2df0ff4a36808f9cc2f6f838518
key3: 2b753a867adf4ee6123c63a3da5960a6d6f272bf0322e747bff70403bfd43d522ae42ce795840ebc3ba5e28a7b5c689dd6b87c2251ad9d01e5d3b5d08fdb46a7bc8ec51c753568284ffe7d995e5cd998f4dbcfbd6e8c250e989714b99588a176a8d8e50bec8d41485261bca97f7461a53332a6c91abfebe2a3289e66487fb0d7158f122a0f5726eeb25a79eb399f8b409a0620ce369236c9964ea3e1ded237b0fe230191c696814c10a9716c60820ab63f611bf9ea7b096f8075d229bc153a48c8fb20276c85a00731c032ba37ccd1ca8ae648a086cf4348b4f201018745bcef88c38dd0c245a675e565796c601c9b9527debed789987b3c688df53b07e336bff1354b3d3e8756bba71fe8279bf2901a18826bb9c7cd48fa7497656527e3560cea33892d0721f72d89fe3e9818858b4552410231122f600969b0aec134f641732d6f43c0b8dc7e69a2466d5dd86fbdbf249b9b63aa2854b982a750a3c378bcbfdc43d1a76b63308d43f726c893f49dab576dff84c372b3a6d304a58dd0c1626b4dd79ffb0bd202575852248c19c80d1072ab8a51c1d25c6655f943d69274046ba3c03e00b90b1f6191707bbc29665427b931b57b07c0cf11f1c9e37b116351d859e2108d019b01a46b92d66ca856ce2f13786be209f75e2f26304a0beb57301e6f9107ff519f8dad84508410c72364cefd30e4e787a04152a8434f3d69cd09aaf507a6538b9ad9518932aff7e4f5f663e74c9c5e0e22e395c47fd1606943ebd382ae0103294f7c71a440c0145ad0eb4f27300dbb959537bc7963d9f37c0c327e3a915f77c40877939b5851a5bef25ca780a84ccef204654e20547d92b51f992ec8600610ec65ceb15e68f1c61fe36a2f8fc1e98b4aec24328b4db20b877807b35ce79524321d7820baf3930e238f939211871ae3ce955c2a7746d8afade9cfe61fb127a69cf3583c753f45737de444fcf48c04136d7d29f05074360718a74816992e0fdcff8a307be089b8f6e82d6e9b46917e2c5125f394fdbd55bb3044770886039df83c23de68ad85b9116681e4f7d2f0ebd1e68f842ef65a7af782a5556be66acd8e91033a37ac673a7937705dfd1174359d80af5e0dccb1de9b259e27fe4c13c841a11de51bd25817eb129736d2cd4c3049209c88d717815bb77eaedf5540fa6300c11291d2032e2e173433e10ab545c2bfec4de29a82efe30b2b6ddd8fad574531b5170daf39c2dbb398693e37e548eb05f0636e72b36d477e4fc2a2a57f7da6ca08909262871cb365dd2c37d3745413960978a7db2cf72c553c20789ba26d6078be4754ab07b82c6fe833edcdd3694741c163ce7175a6f0b43b686d421f64ef084904ffe0f0ab7ccd4a8cb1c99a8a518a451371d0e1807d32c906d65fea33a5e3ed0a6c89e00323f12012e0902b1bbdefcdec190bb37d317ad26dbea94a006dbadf19b9ede96b8001f41da3986d8e57bfba946d43bd8d12972fa468492ff69b95ab527d69c8c66bce25a9227ef3b575c3995abb6659d1775130399f072ba53f8fb79cf166f03a4096692a4ee126f959691689268636b851bba66cc3061ce267a6661d4bf54e3e846a51520467ea582ade3a139af556f09bc9f985575c4035036f41aecdce899d2eace709ebc40d8854ea21ee4f890c8a49c995a8a73682890a6d8579621d05110b250c6b4402b7443d753dae85a2805a950a89b0c47c874bdd474f0ff3e4ba3ba571e198798f10f24ae84491cc5b1211f58ea07ec9a3314b76e1a945075de2b3d9012d5fe2c93d8d46b9ce72e3c1536e23d8b19dbf48147bdb73d8f58c3940b0dcccd8d1a9bcc3165da911fa13c5a038aa9f101e3bb01a6db3564afe83943ba24901d3749b9e7e2f13b7c4391922d93dbfe8d92726793f8f676c87099ab1f0ce5190f98c7c6a1f12762b8571e9195df6c460b97b9e5854baf40a04e0f24f28ad6de50d0faf31f623c61552ac5249472b921fd9178c96c667a5cfc4fb48e9c3c10e66f1f69e43b43a542c44820572c26c69
```
## Ý tưởng
Trước khi vào bài thì mình sẽ giải mã 3 câu hỏi của đề trước.
Câu 1: ```Số 13 là số nguyên tố nhưng còn 1 ý nghĩa gì đó đằng sau nó mà tôi chưa biết...```
→ Mình đoán chắc nó là rot 13, không bàn cãi gì hết.
Câu 2:```Vì sao một chuỗi ký tự bí ẩn lại có thể dẫn tôi đến một video bí mật?``` và chúng ta có ```XmoUNb2=|CcXxL#d2e-ebz)^MV{dIQcVTp6Xg_v6WKnlCcR5#QSYuH```
→ Sau khi phân tích và tổng hợp lung tung thì mình nhận thấy đây là đoạn mã base85 và khi ta giải mã từ b85decode() sẽ được đoạn link này: https://www.youtube.com/watch?v=dQw4w9WgXcQ =))))))))
```python=
import base64
s="XmoUNb2=|CcXxL#d2e-ebz)^MV{dIQcVTp6Xg_v6WKnlCcR5#QSYuH"
a=base64.b85decode(s)
print(a)
```
Câu 3:```Tại sao lại tồn tại một thế giới mà ở đó lại xảy ra chuyện hoang đường: 1+1=0?```
→ Mình chắc chắn nó đang đề cập tới xor
Và giờ chúng ta sẽ bắt đầu phân tích tới đoạn code:
```python
#!/usr/bin/env python3
import os
message = '???'
FLAG = open("flag.txt").read().encode()
assert FLAG in message
def cauhoi1(text: bytes) -> bytes:
return ???
def cauhoi2(text: bytes) -> bytes:
return ???
def cauhoi3(a: bytes, b: bytes) -> bytes:
return ???
enc = cauhoi1(message.encode())
weird = cauhoi2(enc)
key1, key2, key3 = [os.urandom(len(enc)) for _ in range(3)]
ct1 = cauhoi3(weird, key1)
ct2 = cauhoi3(key1, key2)
ct3 = cauhoi3(key2, key3)
with open("output.txt", "w") as o:
o.write(f'ct1: {ct1.hex()}\nct2: {ct2.hex()}\nct3: {ct3.hex()}\n')
# I will give you a chance with my last key :D
o.write(f'key3: {key3.hex()}')
```
Theo tiến trình thì:
Bước 1: Từ Flag chúng ta sẽ chuyển thành bytes rồi rot13.
Bước 2: Ta sẽ encode nó thành base85.
Bước 3: ta sẽ xor đống trong đó thành ct1, ct2, ct3.
Và nhiệm vụ của chúng ta là phải dịch ngược lại nó.
Trước hết thì ta có tính chất của xor:
$$
A \oplus B\ \oplus A = B
$$
Từ đây khi ta xor ct1, ct2, ct3, key3 thì ta sẽ có được weird.
Khi đã có weird thì ta chỉ cần decode nó lại thành plaintext nhưng đã rot 13.
Và cuối cùng ta chỉ cần rot 13 lại thêm lần nữa để ra Flag.
## Code
```python
from pwn import *
import codecs
import base64
#output goc
ct1 = "944073d9c2fdec4334375867fcd9b0c4545d20152151f6d008259a14ea339e4e0a38167ea99fd4817b4e22565772b28c5b6781c67bf16c0c4f4e0efdeaf21f0a5a7e96bff3e8a39008788fd8256c2b522c6d9b446a29e456dee859f536ba1241e5df09a25ea1abf820ab0358c554afaadf371e02b2dc6f949da28f539b4d9845d962a9899280c2301b8be293c69a241d8e39059e9fbf3fe3772b0500505867df29e4afacd12578114bbb48d17ebf9779d784d05e2479dfccc072c814a1b4d6d8286da2d553b1726a5f2590a9d80604fc7038bb6f2f3999f23d4e37626760d4035fb8cc10bdc66ea4b0a8b9a82283c1a1680f0ca91c226ee2a1af6e8dbd03b5d47c88d6e90f5505f02f7e4e5c03c3cd2ba4e66e2049ec32b4032aae025a9065dec4744aef76926beefe5f7a560a3d82e0c603348081889bcf4ec751be9b899cb23a0c117d8c15b0c9e7e217f92f024d8ed2c028e36eb5bbdc332f04981bf05226ab15dda261e569e8869b97228021c84f454d18570a6120dc40d30679154997b91d1398ef2dd166fa64ee1169c550f506013a327c34889eb0b172878f356ec042d3a22c52a3ed99536fbd6f6f1c2058f25c2314adf4190782e542644af809fd80728c7bfd9a53016565615f1cbe323ea5057679ffd8cdaaa29ea41cb3df37aecbb669e0339bbc52ab3885bbb7eef8273f5dbfeeca6d96efda197004473fe41ba54b1a898f0f30f3ec0b253b8d3555ae0a7948d74b2f083c3cf26035f9b97819124dd930c2747950bf0d6d35e7d82a7f8d3f0a7c8ef012b6926efea881d877e9acbf16a883a98d292193fcbf332cc8a5b6b732abc3cbff2e9e19531053759cae090eaf90b7b8357c9351aeacb13c4c03b1fbf8eea7a35ce1ee793f530eae06e55fe536d0ec0c5a4e70a4f6735a240ac0e38713d14ffa32c88927908b3f273febc81e268fe4a6473f8f0e3fca74c436e08e1f1b3690d0b41b29a519bdf7ba78e6fd0dc915dc78609eaf16c4cedc3a71c406b2bbfb0bfe6d86e9e2e00d6f7a1dc8be264751cf3e84bf58cd266b3f33e0948df9d5fcee3b1405192c5401d0bd3b97839260165935e254d64cbf4a2ea318bfe17fcf241f082e8b0ec78dc68369b02d1e1d9900184fe3b62bf56cc4ed66c0dccd433beb8585295cd478d3216eea43f258da09e7011549d9235e4763c57f46e985b6f2e9561157688e266e67b35e1ee8180c00d26b14cea81417b6244175d48d2381364d4fee04df5ea1aadacc07653f1e4857550648644dd62924caa4bf6d9df4cf2fb66e4b4287de8bcbb4fa45d06c1f54256e34639b2ec6cb8e9c9bbb0ad655b6e65c4372688ccf44e65f263f2b677f800e5b4a9464c611e51c1ad31637b7933313bd73e037e0a738ef0d782427a0b56c255dc9e1febf42ed6cbefc27f138aaf00336992a2e970d597bd037f05ff6cc92477a3528c5daaf6bd3c8d47c67ed6f91a4348ea43125352f34842843bb467220097384291a43b098a6c41611041fbfa9900a7733129710436da9c991a08c50eba4ebb7b22165a111cadbb0c86f6448f574857b561fa0813528ae886ad0e80192b53c21c831a317e7f2fea1521f8b3e237b79e40245feac47ae9a8d99fd1ee8f11aaaf8cc6fd7b1a066ae9299b210c55b7651b2052a4be88fd1eb3a85f515adb388d504507236464ef0c83151001e0035b6e55de0bd5091305cca1002de0d4b0fe920ddad16232d0cf82e0c7588399bad23a3bfdbcdda2fdaa532c2f421bc25480e395f5db0d724748b3751156c29348494c88d4fbc75b6a9997dd714a66228f1099f2d36ecab036d77728183c704beae2cfb594dd8484c0d2b299626e1413a584fef756c73945200f16cf05b79568dc94b56dab9569adcdd000d55aa04b35115ec11ba53bd8a05e576d5956b4df9170b6e65c9849a6204fb62c98ef2b8d3d138f95d0335180831ebee7f5583e737c4782895f082defaae68775825a2ab34403347261a6fd497ee7a9eadf050e9954a01b173aaf5e9a21a03d66f"
ct2 = "770178bcb4c79bb17a3e9d3fae37aff128817b9528af0fd6ba9b35638095318ca7c640c7b5f4ca9dd5621472887287fc07d9bdeea79c6c68d059cc3e497c036e8fbf6b9ed480d3b4be6069dd834c6a9a162ba2a879cdf7286697670c9d299086e79844760caff21366ebf507d59fe40a0a59fca4df49fb306937faeb4d3b6ad266c2def5b5d78ef5cb6fd66a2e4cbe251d54e71478f539a82683d7f403e583bddcd0db7bf992c6dc1d50de5066c209bf14995e92b0383437719e3f93ccbc9eda83674d770d7d29b182e7fe3f1b791de8231645dfd3c258ae65fec2e1f1e9693c4f138b3b3c714385285fe25c7ab1a7c77c64c974e003c2d0ca4c144f7a6ebeba7d556aefe0929658b96b9252e7c3682a611915583da9c20ca84d3ef1b551f41c5f2adfb76970f8653342064587693dba7318d8118dd1f31ef27f22caad90c1f9145d71074fed2d81928c29d077ad92b679fe8d79ded8c62ca8bf53218df5439b1a81d6f21df99e0432c67f6002a0155b82f0f6953b6c5a5324df90333fe1c731f792e3f27fdc09047b13de99fcc1763cd1fe7a0587becbbf2ce09b9897c6325258450055c49bcf3506db1a2b055f7a029e99f1343888d8d8fa4a84be11ca1f5b85ffbf00b96dc61d05db4b446eba1a53aae9bdbac981d7046ca3158e67cf7e3f9c357fea73718d61da1e0fe42a4e4f10490495deee5174f02326b591b7dbf8d0e52841faf4da6b469d250f65ed794f08c438307752ab5368db551da6aba167bbf3ddb34e54f4ce725512721343714338901492fa298db176449277011ae92d252a7a9c5aac970dfd004329fdb2b0ca7a6d543ee133ed5a3d31e0a1b15a07cb366a25d5569eb124d74237604688fabc5bdec532ef76825d8592e910f6e59b843e8487605e0d823af50b0dea4bd199a9e52818fd90de3194fc0c9e3d30de743301a154cf08e40068234acdc8b4e5b39ca8f0053439db32b029ecc44b74998635d433eaf174b5946715e5ffdb21e3315f3a412c7e2b6ff53832befd256164ef47697dece91de9e7bc2d0095bde64422ef708223d6c0e59f0e0762197d59846b0c9f3060edc4cabc79e01acc72c8580af50b959b2436dde3753fa316cfd9a789facb770c3afdf04a183e897ff5b5b8366f8c3092b1d1ab0975c0f83b0a1da0a1e105cc067339bdee25f82d9a5e02d8ce593691e370e1ca297849e9e932d0773590a61a4ff645b468ad0d9fc0d1899e2ff5aa168d61fda073792e33c50f4a566385b87566afc14449b4fb9ac662a0f9267a872565f6e3458c24999c3972524c7015ad02ed24d93268d362b32ea6f6ea00ebabbae9968cab114f8f835a03802850951f5c16c5446d5f2910b1e72618e453b21e132b2275608471915271e019efc6324a88af1ec0a2c0840f676c64636ac7e8801f67befe418557956f9fb8274031392cb121b5f73434f30436a486f13cb36e39a9ee3bef53a1acbb90340755c2a06a6f1c21fb9f9ac3e520e20a90b952378d2759ae789ab26acbed14fab5d2d5c40e420a356c7ff0050d7368efd10cea07d9a1d7eeecc91ce13a066c93690a513d3cc7b1bbd468575aeb7b3563d60b82613b9ae50c5df8f26ae5bfe84677cc54898d504644e5b423ba47b507b30d495dbaa2e5f87f780be3b9562c1bfe1a1f79d828c4867274d2b5b31ef750f965d4a84dbadef33871e435d61425578fec1f1f6651d615fde35697e31162658239110e4b0ccf1d05e50ac275a82ddc8f7920dda8021f7c14e36692eeba0f2421151f3496566e2e176c6a4d89058d19479b89e043e1e4bb63f892c9134a5100a3b574afa9f7e6c6688e71ad3038c37587a6efb417e0473e06e14ad083b825c7f1caf0e9e61003da38fe526e421e1abad336ffe81fa166d7ff8714bb1972547f08e0cbb80355387f87ffcea8219f96a108f71e1474b68fd46dfda7bcfe899b9e752f7dbc68cf252f31a68435165de7748460b86341f6e3b10d6f5c3f7e6e813fa5ef538380914e127f21f728e0eb3370597c"
ct3 = "9a1019a263bf5c2b7473e7afe4c447db8b621e1b68ff78306e2a9f179b0cd3cacc544c3dbf8051f4d4e8bd9f921d07a6a757016bacfcf5075e895f7076303f845a2e7b6971184040cd98d6ceb90ce321afc89374230910051da77a080f544bf0f2c59dade7cb76d055763a9759ef7063d603012e2e525a7801d7928cdf68346883580415447e297107822d298b21522c472a9828b19667dd83cd3250a656f0976a320c35af7660b40900a6b714d6d531a63ea20c1c1982a959d87fe5fc502a0932a688c4530ebb9abb5d696fb8f29eaefdbdd5683d44c3438418c3c8469345fbdb2de1c230c5d36a0aba17fb671dd5b952903e314cdbf467263feedfa1c470879a91b2008600af5f7b69004a34ac6274e4484ea383caf910be86dfa19c43a38518254a04699a54c5718363e9c2a16e56d91bb4e2373069fd9934bfef2b853a79554f57ea4a7c8f199853122df8e556c0b4cb51894c0f5a232555242d2e48ec554bbdadaf5b4baa2cb6cbefe4463422fad383723f9757ad71fd594dbc984a54939b37c19634e62cf10f859e2a712ec603c15bff5526ab6248be1f118c5afa84181d067e4e9f1c0176a2753880634c148518c169a3aa695f12b68d54c4a9f8f976d3a6b0420ac0a39d51638c71199d87b5f185fdc4298247dced58026e3f9ab79424ebda18e8053d5e508f66137fa632b9a5dcd4a25e4d9c5bda508ea9d1a2afb01511387e3b5d3f985e6ac97c7cb8614b316d3a3838acdd808c23d25c19cfd2116cecbda92cae83deb555c8ae8cc983aac571c9e4365a0c0d077a401df2bb8596f7d457f093367b0e49a1a11e79c7723d20a9e4b54d535a945e958323c4d39b648fd314dbb4afafad01c5504cc860f891f89d60a4d87dd90e53b89192bacc0a935c3253dc5f8454f776305d418734b3d5e4c71b6dabcc3230141f2e92129f415ccab55e1d81f07ea8709b008026001d994dad50cb1583a3b141e0a9fa5a2fb20b82558f04090f889b7f9bec4a5055a5f3ef60b278f5fc2c6ed8c51f826b9cc5be88cf667d8f7394342a7735b65001c766ec62f0a94970d90cf94d4d53f6ad8d273f2c6163390321578b2835e396072b6cbf7876e46e24c14a821b85a5be90b34147f0d8e553e361709c7871dda118dac4e1a11b254fe6eaeec628289e6a6fad2d1382c6602dd92b5026a123b1a6d972d9c4000c480574ce1c2c45e33c5437d469857a427964e05ec79ade151943ab01c33bc6e4eff64d81515851f08b3ba64854683217595397161173a47e5de056b290dc47324c68fa47ce7a53c19048d72b549bfa70f2d9f8e06e3d27214be154f9668b02bfcf69576c15ce42e6736e4dff74a21f3754ff7e4ad396132435f19ae605dbdbffba84f99898ca7fb51055af2093658eab899a06318a0e30b01c3b731df1f22751bbce2db6f2a1bd695b386b42203327fb51fddfc616c838f046e6aa6af7149335b43460d6e578eac6c0d3950c3577957ada59d1a68bf12b652a4bdde7cc7dbe304f3e608dd0581439394c3f3e73bb79ef288bdda8d7bc6d2f4b1d31997e320005a92426ea75264fce6fcfd256a17290cac2a62c29dfbfe7e9b0c31ce48643612a949277ac98b6403cd94a99a5c187067562f63377bf7819fa3f0a626dd9d3d53238e60b2603d5cf9ec83ef5c028841799fa11e213c43a549aa1916ad48b27bbd894a7a4825ad2cbf25cec2dacb1da3a22b916a5f2988c17c624f7100d8c9fe6331c3c04f81653798935dfb231ff2802cd8d01700f17e77fbb794dffd6bec64fb8158202f2b989d8a6df2d5970b83f75c9ea6d4b372069254d4bbb926db3cc2758c5a95e573a9af016ace085db954561900a867490a99df789435589bc471936e159521daea5e4a5a90fc37f657cb5c694ff39fa35ae59f45dad5088e923319caa5afd9c46d974a498d339c6b05cd06d07cdda7648d60c6153b452c734e4935cbb3bcf22b3433a8dcca328bc147e697cadd0bd2ff0d0f4c93bf17af2df0ff4a36808f9cc2f6f838518"
key3 = "2b753a867adf4ee6123c63a3da5960a6d6f272bf0322e747bff70403bfd43d522ae42ce795840ebc3ba5e28a7b5c689dd6b87c2251ad9d01e5d3b5d08fdb46a7bc8ec51c753568284ffe7d995e5cd998f4dbcfbd6e8c250e989714b99588a176a8d8e50bec8d41485261bca97f7461a53332a6c91abfebe2a3289e66487fb0d7158f122a0f5726eeb25a79eb399f8b409a0620ce369236c9964ea3e1ded237b0fe230191c696814c10a9716c60820ab63f611bf9ea7b096f8075d229bc153a48c8fb20276c85a00731c032ba37ccd1ca8ae648a086cf4348b4f201018745bcef88c38dd0c245a675e565796c601c9b9527debed789987b3c688df53b07e336bff1354b3d3e8756bba71fe8279bf2901a18826bb9c7cd48fa7497656527e3560cea33892d0721f72d89fe3e9818858b4552410231122f600969b0aec134f641732d6f43c0b8dc7e69a2466d5dd86fbdbf249b9b63aa2854b982a750a3c378bcbfdc43d1a76b63308d43f726c893f49dab576dff84c372b3a6d304a58dd0c1626b4dd79ffb0bd202575852248c19c80d1072ab8a51c1d25c6655f943d69274046ba3c03e00b90b1f6191707bbc29665427b931b57b07c0cf11f1c9e37b116351d859e2108d019b01a46b92d66ca856ce2f13786be209f75e2f26304a0beb57301e6f9107ff519f8dad84508410c72364cefd30e4e787a04152a8434f3d69cd09aaf507a6538b9ad9518932aff7e4f5f663e74c9c5e0e22e395c47fd1606943ebd382ae0103294f7c71a440c0145ad0eb4f27300dbb959537bc7963d9f37c0c327e3a915f77c40877939b5851a5bef25ca780a84ccef204654e20547d92b51f992ec8600610ec65ceb15e68f1c61fe36a2f8fc1e98b4aec24328b4db20b877807b35ce79524321d7820baf3930e238f939211871ae3ce955c2a7746d8afade9cfe61fb127a69cf3583c753f45737de444fcf48c04136d7d29f05074360718a74816992e0fdcff8a307be089b8f6e82d6e9b46917e2c5125f394fdbd55bb3044770886039df83c23de68ad85b9116681e4f7d2f0ebd1e68f842ef65a7af782a5556be66acd8e91033a37ac673a7937705dfd1174359d80af5e0dccb1de9b259e27fe4c13c841a11de51bd25817eb129736d2cd4c3049209c88d717815bb77eaedf5540fa6300c11291d2032e2e173433e10ab545c2bfec4de29a82efe30b2b6ddd8fad574531b5170daf39c2dbb398693e37e548eb05f0636e72b36d477e4fc2a2a57f7da6ca08909262871cb365dd2c37d3745413960978a7db2cf72c553c20789ba26d6078be4754ab07b82c6fe833edcdd3694741c163ce7175a6f0b43b686d421f64ef084904ffe0f0ab7ccd4a8cb1c99a8a518a451371d0e1807d32c906d65fea33a5e3ed0a6c89e00323f12012e0902b1bbdefcdec190bb37d317ad26dbea94a006dbadf19b9ede96b8001f41da3986d8e57bfba946d43bd8d12972fa468492ff69b95ab527d69c8c66bce25a9227ef3b575c3995abb6659d1775130399f072ba53f8fb79cf166f03a4096692a4ee126f959691689268636b851bba66cc3061ce267a6661d4bf54e3e846a51520467ea582ade3a139af556f09bc9f985575c4035036f41aecdce899d2eace709ebc40d8854ea21ee4f890c8a49c995a8a73682890a6d8579621d05110b250c6b4402b7443d753dae85a2805a950a89b0c47c874bdd474f0ff3e4ba3ba571e198798f10f24ae84491cc5b1211f58ea07ec9a3314b76e1a945075de2b3d9012d5fe2c93d8d46b9ce72e3c1536e23d8b19dbf48147bdb73d8f58c3940b0dcccd8d1a9bcc3165da911fa13c5a038aa9f101e3bb01a6db3564afe83943ba24901d3749b9e7e2f13b7c4391922d93dbfe8d92726793f8f676c87099ab1f0ce5190f98c7c6a1f12762b8571e9195df6c460b97b9e5854baf40a04e0f24f28ad6de50d0faf31f623c61552ac5249472b921fd9178c96c667a5cfc4fb48e9c3c10e66f1f69e43b43a542c44820572c26c69"
#bien doi
ct1_before_hex = bytes.fromhex(ct1)
ct2_before_hex = bytes.fromhex(ct2)
ct3_before_hex = bytes.fromhex(ct3)
key3_before_hex = bytes.fromhex(key3)
#cau hoi 3/xor
key2 = xor(ct3_before_hex, key3_before_hex)
key1 = xor(ct2_before_hex, key2)
weird = xor(ct1_before_hex, key1)
#cau hoi 2/b85
enc=base64.b85decode(weird)
enc_text=enc.decode()
#cau hoi 1/rot13
text=codecs.decode(enc_text, 'rot_13')
print(text)
```
Đoạn code trên sẽ chạy ra một đoạn text:
"In March 2007, the first trailer for the highly anticipated Grand Theft Auto IV was released onto the Rockstar Games website. Viewership was so high that it crashed Rockstar's site. Several users helped to post mirrors of the video on different sites, but one user on 4chan, Shawn Cotter, had linked to the Never Gonna Give You Up video claiming to be the trailer, tricking numerous readers into the bait-and-switch. Here is the flag: W1{D1d_y0U_GeT_r1Ck_r0lL3d?} In 2022, Shawn Cotter was interviewed by Vice Media. He said the reason of using Never Gonna Give You Up was because he found a list about songs that were popular at the time he was born using the Internet, and this song is on the top of 1987, which was his year of birth. This practice quickly replaced duck rolling for other alluring links, all generally pointing to Astley's video, and thus creating the practice of rickrolling. The bait-and-switch to Never Gonna Give You Up greatly expanded on 4chan on April Fools' Day in 2007, and led to the trick expanding to other sites like Fark and Digg later that year, quickly adding the name rickrolling based on the prior duck rolling."
> Flag: W1{D1d_y0U_GeT_r1Ck_r0lL3d?}
# Bo tu sieu dang
* trước khi vô bài thì mình muốn shout out tới 2 anh L1ttl3 và anh DucCorp vì đã hỗ trợ mình trong việc triển khai ý tưởng <3
## Đề bài
```python
from Crypto.Util.number import *
with open("flag.txt ", 'rb') as f:
flag = f.read().strip()
assert flag.startswith(b'W1{') and flag.endswith(b'}')
m = bytes_to_long(flag)
e = 0x10001
m1 = 2**1024 - 3
m2 = 2**1022 - 2
m3 = 2**1020 - 1
m4 = 2**1018
c = pow(m, e, m1) % m2 % m3 % m4
print(c)
# c = 2027792127378145444099302510462900300257442068928010403052259994880511317607407514908720534902489134379904618947792557805368190009359079320337075768626232418980864987406619809977532904702783433112202254001367719098893178820312980355187703995660867067442830169498602243151057835147454968516377852012013934653
```
## Ý tưởng
Trước hết bài này mình sẽ chia thành 2 giai đoạn:
1. Là chạy trâu k để truy ngược đề về dạng $$ C \equiv m^e \ (mod \ m1) $$
2. Là vận dụng crt(chinese remainder theorem) để tìm ra Flag.
Về bước 1:
Gọi $$ t4 \equiv\left( \left( m^e \bmod m_1 \right) \bmod m_2 \right) \bmod m_3 $$
Lúc này:
$$
c \equiv t4 \ (mod \ m4)
$$
Từ đó suy ra:
$$
t4 = k4*m4 + c
$$
Và ta tiếp tục truy ngược lên trên và biểu thức cuối cùng sẽ là:
$$
C = k4*m4 + k3*m3 + k2*m2 + c
$$
Lúc này ta chỉ việc chạy trâu k2, k3, k4 từ 0->3. Ví dụ như: t4 = k4*m4+c thì khi k4=4, lúc này t4 > m3 => vô lý. Tương tự với t3, t2.
Khi này bài toán đã về dạng rsa cơ bản tuy nhiên m1 lúc này không phải là tích của 2 số nguyên tố, và m1 cũng rất lớn để ta có thể phân tích thừa số nguyên tố của nó ra.
Tuy nhiên (khúc này mình không biết chứng minh):
$$
m1 =p1 * p2 * p3 * ... * pk
$$
Thì ta không cần phải biết toàn bộ những số này mà chỉ cần tích của nó đủ lớn làm sao cho có thể > m cuối cùng mà ta phải tìm thì ta vẫn có thể ra flag.
Và trong trường hợp này, mình phân tích m1 thành
$$
13*107*87671*3870037838243*279462107025143615623321823017*1325706410421371952032007611396267 * R
$$
Với R chưa biết (mình dùng factordb để phân tích)
thì lúc này ta sẽ sử dụng crt để làm bằng cách là:
$$
\begin{cases}
m \equiv C^{d_1} \pmod{13} \\
m \equiv C^{d_2} \pmod{107} \\
m \equiv C^{d_3} \pmod{87671} \\
m \equiv C^{d_4} \pmod{3870037838243} \\
m \equiv C^{d_5} \pmod{279462107025143615623321823017} \\
m \equiv C^{d_6} \pmod{1325706410421371952032007611396267}
\end{cases}
$$
Khi này ta chỉ cần dùng thư viện sage math để giải.
## Code
```python
from sage.all import *
from Crypto.Util.number import long_to_bytes
e = 0x10001
m1 = 2**1024 - 3
m2 = 2**1022 - 2
m3 = 2**1020 - 1
m4 = 2**1018
c = 2027792127378145444099302510462900300257442068928010403052259994880511317607407514908720534902489134379904618947792557805368190009359079320337075768626232418980864987406619809977532904702783433112202254001367719098893178820312980355187703995660867067442830169498602243151057835147454968516377852012013934653
#c = pow(m, e, m1) % m2 % m3 % m4
for k4 in range(0,4):
for k3 in range(0,4):
for k2 in range(0,4):
C=k4*m4+k3*m3+k2*m2+c
#tinh d
d1=pow(e,-1,13-1)
d2=pow(e,-1,107-1)
d3=pow(e,-1,87671-1)
d4=pow(e,-1,3870037838243-1)
d5=pow(e,-1,279462107025143615623321823017-1)
d6=pow(e,-1,1325706410421371952032007611396267-1)
#rut gon c
c_end_1=pow(C,d1,13)
c_end_2=pow(C,d2,107)
c_end_3=pow(C,d3,87671)
c_end_4=pow(C,d4,3870037838243)
c_end_5=pow(C,d5,279462107025143615623321823017)
c_end_6=pow(C,d6,1325706410421371952032007611396267)
#trien khai thu vien
m=crt([c_end_1,c_end_2,c_end_3,c_end_4,c_end_5,c_end_6],[13,107,87671,3870037838243,279462107025143615623321823017,1325706410421371952032007611396267])
s=long_to_bytes(m)
if b"W1{" in s:
print(s)
```
code này hơi bẩn mắt nên mình sẽ ráng fix sớm nhất có thể <(")
> Flag: W1{RSA_w1th_0v3rl4pp1ng_m0dulo}