---
# System prepended metadata

title: WANNAFRESHMAN 2025

---


[1]
# [PHIPHAI] 

**Category:** Crypto   
**Points:** 50  
**Author:** dvck13  
**Solve by:** VuiVe  


## Đề bài
![Screenshot 2025-10-05 154600](https://hackmd.io/_uploads/Hk5C5hMpxg.png)
```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
'''
```

## Phân tích
Khi đọc đoạn code ta thấy các biến p,q,n,m,e,phi,hint,d => Khả năng cao/ chắc chắn là RSA2048 ( p,q được tạo nguyên tố 1024 bit)
Các biến khác được tạo như RSA thông thường


## Ý tưởng 
Ta biết:
$$
\begin{aligned}
&\text{Cho: } p, q \text{ là số nguyên tố}\\
&n = p \times q \\
&\varphi(n) = (p - 1)(q - 1) \\
&hint=p+q\\
&e =65537 \\
&d \equiv e^{-1} \pmod{\varphi(n)} \\
&\text{Mã hóa: } c = m^e \bmod n \\
&\text{Giải mã: } m = c^d \bmod n\quad(I)
\end{aligned}
$$
Ta có:
$$ \varphi(n) = (p - 1)(q - 1) = n - hint +1\quad (II) $$ 
$$ d \equiv e^{-1} \pmod{\varphi(n)} => d*e-1=k*phi $$

Sau khi tính được $$k= d*e-1$$
Ta tìm phi bằng cách tìm các ước của k từ (1,e+1), sau đó tìm n bằng công thức (II), xác nhận lại đúng phi,n không bằng các yếu tố p,q,delta
Giải m theo công thức (I) và chuyển thành byte ta tìm được flag


## Script giải
```python
from math import isqrt
from Crypto.Util.number import *

e = 65537
d = 4504287984018183537713208161402766323065548618393723872837173606374276398491834181934336417310620387990925189536232872881499528612504958202701279049935780903977608853793957819684386053139789777966936156264230499424635837453895019683637553474699470241265384239892304309743522811693909773853204104744746499940669186347989219693819334120860342801601135658920550816397929837218587842050717426094705159184294217221659550021174121437354727563286401517383250923022292331155286641664114777714280910808217996581853423619501922201519238297960634332127751600929842715997073072544823353485994644594610107896462399877655553045761
hint = 231925193905919836406214406898885408169720762556845482044575179755202576770665967750292209535638389585617923204488598005919071680696574306168950409350364369661185363429309191455686049593246205245617043129829360203967945465085196018291809693305049028207915207766096530755343783712735226590596701430255772594556
c = 6217038084836470023310381029897048208087224587728895918727075557465841714766785434203795384404277685883194699549944699326316064489862857903738642081680285228167738881574533344177255570731527611503589831001734795490242158816621194509455025049486128406587545324515046616431849802141624745659660349892441242897503306780984369111460208907969417056103375189617092555003582813739896435112054576310776891033107119212517760203084951964632014280482552024983115272574743031704179104705817029355755554440364213319205880788661502753344785708858216051846295494426952842154398100557142240912181225765846610290283305931102820798460


k = e*d - 1  # k mod phi = 0

for t in range(1, e + 1):           
    if k % t != 0:
        continue
    phi = k // t   # phi là ước của k
    n = phi + hint - 1              

    disc = hint*hint - 4*n #delta
    if disc < 0:
        continue
    sqrt_disc = isqrt(disc)       
    if sqrt_disc * sqrt_disc != disc:
        continue

    # p,q = (hint ± sqrt_disc)/2, 
    if (hint + sqrt_disc) % 2 != 0 or (hint - sqrt_disc) % 2 != 0:
        continue
    p = (hint + sqrt_disc) // 2
    q = (hint - sqrt_disc) // 2
    if p*q != n:
        continue

    m = pow(c, d, n)
    pt = long_to_bytes(m)
    print("flag: ", pt)
    break
#W1{phi_phai_la_game_rac_so_1_vn}
```
>Flag:  W1{phi_phai_la_game_rac_so_1_vn}


>Tại sao lại chạy for từ 1 đến e+1 ?
>Vì trong RSA thông thường e và phi luôn nguyên tố cùng nhau nên k thường nhỏ hơn e.
>Ta có :
>$$\varphi(n) = \frac{e \cdot d - 1}{k}$$
>Vì thế nếu t>e thì khi k//t sẽ tạo ra phi vô cùng nhỏ, không thể hợp lí được

---

[2]
# [PHIPHAI2]  

**Category:** Crypto   
**Points:** 50  
**Author:** dvck13  
**Solve by:** VuiVe  


## Đề bài
![Screenshot 2025-10-05 154657](https://hackmd.io/_uploads/B1CHLq76ex.png)

```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
'''

```


## Phân tích
Lại thêm một bài RSA2048 nhưng bài này khác là chỉ có leak,ct,n
Ta có công thức của leak theo đề:
$$ leak = (p^2 + q^2)  \pmod{n}  \quad(I) $$ 


## Ý tưởng 
Từ công thức (I) biến đổi: 
$$
\begin{aligned}
&p^2+q^2 = (p+q)^2 -2*p*q = hint^2 -2*n\\
&\Rightarrow leak =(hint^2-2*n) \pmod{n}\\
&\Rightarrow leak = hint^2 \pmod{n}\\
&\Rightarrow  hint^2= leak + k*n 
\end{aligned}
$$
Sử dụng vòng lặp chạy để tìm k rồi sau đó tìm hint, cuối cùng tìm flag

## Script giải
```python
from math import isqrt
from Crypto.Util.number import *

e=65537
n=20842938351896783351765564497257406689875073939168847270109018452331595953195137925905407574790509131975169442262183423216630782056006817670026102637100795102868553295795605909294220001159170312214938967565708237131119660898946450453038715919305770854433454485282482531591669338374784896696254086081923985254456532726474557269047987653955703675146699130077388795028830171715932232259532178061195603162554212575207799198670246556909810593997402979919324116015029695269687378794139114073155816838415492318483626370434226417328166879349978988600491401399315534138391936796615782306743416152563145103425347897571269559877
leak=1246889223294307854370712989427585884021285335323141671816486223380713311286629425480810174036551750931478373626071781038942054037291709281118654737087599035092443005799430352628570933778452108536502272580400092528062848455445985692614774855796791907610933670663580901476953467808284328166657791568856558571935788405193538986947393116928493787198798661826785549975721130971676199856446097879499458065034678153636052702160287204920680541565366139294026010089009061274372587986143754097126566624340639998228509117420424679732985956823117206903025894886029533740978018513157416105341714161360196840042575896512731742096
ct=3088291167300681828911890341254838261507896143994085977627215978594078495952883007565773809797879150841185401282724413230256089706081482055304607098189837372445021022139016449305819308800001848241222118389290692225549475347019810385147707744883436586629808823247373108273012523932858309484832402796522454251129915341722714855738383668651266661352021406899104266596812402238487015961091455318371807234925900608259741913811110018686747303985152505270333578971573169716269092799613880511496142576903738948348527279101539196915559331086705114365249818982213416798535758240324625059044600889754519687795415852504666992830

#tim hint=q+p
for i in range (1,e+1):
    hint2 = leak + i*n 
    hint = isqrt(hint2)         
    if hint * hint != hint2:
        continue
    break
phi=n-hint+1
d=pow(e,-1,phi)
m=pow(ct,d,n)
pt=long_to_bytes(m)
print(pt)
#W1{i_hope_you_like_this_one}

```
>Flag: W1{i_hope_you_like_this_one}

![image](https://hackmd.io/_uploads/HybG0cX6xx.png)
>Vì $$ 2*n \equiv 0 \pmod{n}$$
>Nên $$ leak = hint^2 \pmod{n} $$

---

[3]
# [VI-ET] 

**Category:** Crypto   
**Points:** 175  
**Author:** Nhan_laptop  
**Solve by:** VuiVe  



## Đề bài
![Screenshot 2025-10-05 154756](https://hackmd.io/_uploads/Bkk3ls76gg.png)

```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
"""


```


## Phân tích
Đề cho 3 hệ thức Vi-et của phương trình bậc 3


## Ý tưởng 
Sử dụng 3 hệ thức để giải phương trình bậc 3 theo Vi-et ngược, 3 nghiệm của phương trình sẽ là a,b,c ( không có thứ tự ) nên sẽ có tối đa 6 hoán vị, sau đó ta thử từng hoán vị vào 

## Script giải
```python=
import sympy as sp
from sympy import symbols, solve
from itertools import permutations
x = symbols('x')

s1 = 15864378984956659850534060107405422568891641699308509134070157505662198692417476378386001170963905568690006431674713
s2 = 779122598205443694565344617967399722167
s3 = 196487786916397904192643381759626074607590751745631772329891131596526673844879

poly = x**3 - s2*x**2 + s3*x - s1          
roots = sp.solve(poly, x)    
arr=[roots[0],roots[1],roots[2]]
uniq=set(permutations(arr) )
ls=sorted(uniq)
for i in range (len(ls)):
    a,b,c=ls[i][0],ls[i][1],ls[i][2]
    val=123*a + 456*b + 789*c
    print(f'W1{{{val}}}')    

```
![image](https://hackmd.io/_uploads/B1S2nGN6ll.png)

>Flag:W1{318278380181268876680024363742066731941800}
>Sử dụng set() loại các trường hợp lặp ( nếu có 2 nghiệm trùng ) để giảm số lần lặp và tránh in các flag giống nhau ( nếu có thể )
---

[4]
# [BABY CRYPTO] 

**Category:** Crypto   
**Points:** 490  
**Author:** r1muru  
**Solve by:** VuiVe  
**Supporter:** Mai Đăng Khoa



## Đề bài

![Screenshot 2025-10-05 155137](https://hackmd.io/_uploads/S1kbVsQplg.png)

```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()}')
```
File output: 
```txt=
ct1: 944073d9c2fdec4334375867fcd9b0c4545d20152151f6d008259a14ea339e4e0a38167ea99fd4817b4e22565772b28c5b6781c67bf16c0c4f4e0efdeaf21f0a5a7e96bff3e8a39008788fd8256c2b522c6d9b446a29e456dee859f536ba1241e5df09a25ea1abf820ab0358c554afaadf371e02b2dc6f949da28f539b4d9845d962a9899280c2301b8be293c69a241d8e39059e9fbf3fe3772b0500505867df29e4afacd12578114bbb48d17ebf9779d784d05e2479dfccc072c814a1b4d6d8286da2d553b1726a5f2590a9d80604fc7038bb6f2f3999f23d4e37626760d4035fb8cc10bdc66ea4b0a8b9a82283c1a1680f0ca91c226ee2a1af6e8dbd03b5d47c88d6e90f5505f02f7e4e5c03c3cd2ba4e66e2049ec32b4032aae025a9065dec4744aef76926beefe5f7a560a3d82e0c603348081889bcf4ec751be9b899cb23a0c117d8c15b0c9e7e217f92f024d8ed2c028e36eb5bbdc332f04981bf05226ab15dda261e569e8869b97228021c84f454d18570a6120dc40d30679154997b91d1398ef2dd166fa64ee1169c550f506013a327c34889eb0b172878f356ec042d3a22c52a3ed99536fbd6f6f1c2058f25c2314adf4190782e542644af809fd80728c7bfd9a53016565615f1cbe323ea5057679ffd8cdaaa29ea41cb3df37aecbb669e0339bbc52ab3885bbb7eef8273f5dbfeeca6d96efda197004473fe41ba54b1a898f0f30f3ec0b253b8d3555ae0a7948d74b2f083c3cf26035f9b97819124dd930c2747950bf0d6d35e7d82a7f8d3f0a7c8ef012b6926efea881d877e9acbf16a883a98d292193fcbf332cc8a5b6b732abc3cbff2e9e19531053759cae090eaf90b7b8357c9351aeacb13c4c03b1fbf8eea7a35ce1ee793f530eae06e55fe536d0ec0c5a4e70a4f6735a240ac0e38713d14ffa32c88927908b3f273febc81e268fe4a6473f8f0e3fca74c436e08e1f1b3690d0b41b29a519bdf7ba78e6fd0dc915dc78609eaf16c4cedc3a71c406b2bbfb0bfe6d86e9e2e00d6f7a1dc8be264751cf3e84bf58cd266b3f33e0948df9d5fcee3b1405192c5401d0bd3b97839260165935e254d64cbf4a2ea318bfe17fcf241f082e8b0ec78dc68369b02d1e1d9900184fe3b62bf56cc4ed66c0dccd433beb8585295cd478d3216eea43f258da09e7011549d9235e4763c57f46e985b6f2e9561157688e266e67b35e1ee8180c00d26b14cea81417b6244175d48d2381364d4fee04df5ea1aadacc07653f1e4857550648644dd62924caa4bf6d9df4cf2fb66e4b4287de8bcbb4fa45d06c1f54256e34639b2ec6cb8e9c9bbb0ad655b6e65c4372688ccf44e65f263f2b677f800e5b4a9464c611e51c1ad31637b7933313bd73e037e0a738ef0d782427a0b56c255dc9e1febf42ed6cbefc27f138aaf00336992a2e970d597bd037f05ff6cc92477a3528c5daaf6bd3c8d47c67ed6f91a4348ea43125352f34842843bb467220097384291a43b098a6c41611041fbfa9900a7733129710436da9c991a08c50eba4ebb7b22165a111cadbb0c86f6448f574857b561fa0813528ae886ad0e80192b53c21c831a317e7f2fea1521f8b3e237b79e40245feac47ae9a8d99fd1ee8f11aaaf8cc6fd7b1a066ae9299b210c55b7651b2052a4be88fd1eb3a85f515adb388d504507236464ef0c83151001e0035b6e55de0bd5091305cca1002de0d4b0fe920ddad16232d0cf82e0c7588399bad23a3bfdbcdda2fdaa532c2f421bc25480e395f5db0d724748b3751156c29348494c88d4fbc75b6a9997dd714a66228f1099f2d36ecab036d77728183c704beae2cfb594dd8484c0d2b299626e1413a584fef756c73945200f16cf05b79568dc94b56dab9569adcdd000d55aa04b35115ec11ba53bd8a05e576d5956b4df9170b6e65c9849a6204fb62c98ef2b8d3d138f95d0335180831ebee7f5583e737c4782895f082defaae68775825a2ab34403347261a6fd497ee7a9eadf050e9954a01b173aaf5e9a21a03d66f
ct2: 770178bcb4c79bb17a3e9d3fae37aff128817b9528af0fd6ba9b35638095318ca7c640c7b5f4ca9dd5621472887287fc07d9bdeea79c6c68d059cc3e497c036e8fbf6b9ed480d3b4be6069dd834c6a9a162ba2a879cdf7286697670c9d299086e79844760caff21366ebf507d59fe40a0a59fca4df49fb306937faeb4d3b6ad266c2def5b5d78ef5cb6fd66a2e4cbe251d54e71478f539a82683d7f403e583bddcd0db7bf992c6dc1d50de5066c209bf14995e92b0383437719e3f93ccbc9eda83674d770d7d29b182e7fe3f1b791de8231645dfd3c258ae65fec2e1f1e9693c4f138b3b3c714385285fe25c7ab1a7c77c64c974e003c2d0ca4c144f7a6ebeba7d556aefe0929658b96b9252e7c3682a611915583da9c20ca84d3ef1b551f41c5f2adfb76970f8653342064587693dba7318d8118dd1f31ef27f22caad90c1f9145d71074fed2d81928c29d077ad92b679fe8d79ded8c62ca8bf53218df5439b1a81d6f21df99e0432c67f6002a0155b82f0f6953b6c5a5324df90333fe1c731f792e3f27fdc09047b13de99fcc1763cd1fe7a0587becbbf2ce09b9897c6325258450055c49bcf3506db1a2b055f7a029e99f1343888d8d8fa4a84be11ca1f5b85ffbf00b96dc61d05db4b446eba1a53aae9bdbac981d7046ca3158e67cf7e3f9c357fea73718d61da1e0fe42a4e4f10490495deee5174f02326b591b7dbf8d0e52841faf4da6b469d250f65ed794f08c438307752ab5368db551da6aba167bbf3ddb34e54f4ce725512721343714338901492fa298db176449277011ae92d252a7a9c5aac970dfd004329fdb2b0ca7a6d543ee133ed5a3d31e0a1b15a07cb366a25d5569eb124d74237604688fabc5bdec532ef76825d8592e910f6e59b843e8487605e0d823af50b0dea4bd199a9e52818fd90de3194fc0c9e3d30de743301a154cf08e40068234acdc8b4e5b39ca8f0053439db32b029ecc44b74998635d433eaf174b5946715e5ffdb21e3315f3a412c7e2b6ff53832befd256164ef47697dece91de9e7bc2d0095bde64422ef708223d6c0e59f0e0762197d59846b0c9f3060edc4cabc79e01acc72c8580af50b959b2436dde3753fa316cfd9a789facb770c3afdf04a183e897ff5b5b8366f8c3092b1d1ab0975c0f83b0a1da0a1e105cc067339bdee25f82d9a5e02d8ce593691e370e1ca297849e9e932d0773590a61a4ff645b468ad0d9fc0d1899e2ff5aa168d61fda073792e33c50f4a566385b87566afc14449b4fb9ac662a0f9267a872565f6e3458c24999c3972524c7015ad02ed24d93268d362b32ea6f6ea00ebabbae9968cab114f8f835a03802850951f5c16c5446d5f2910b1e72618e453b21e132b2275608471915271e019efc6324a88af1ec0a2c0840f676c64636ac7e8801f67befe418557956f9fb8274031392cb121b5f73434f30436a486f13cb36e39a9ee3bef53a1acbb90340755c2a06a6f1c21fb9f9ac3e520e20a90b952378d2759ae789ab26acbed14fab5d2d5c40e420a356c7ff0050d7368efd10cea07d9a1d7eeecc91ce13a066c93690a513d3cc7b1bbd468575aeb7b3563d60b82613b9ae50c5df8f26ae5bfe84677cc54898d504644e5b423ba47b507b30d495dbaa2e5f87f780be3b9562c1bfe1a1f79d828c4867274d2b5b31ef750f965d4a84dbadef33871e435d61425578fec1f1f6651d615fde35697e31162658239110e4b0ccf1d05e50ac275a82ddc8f7920dda8021f7c14e36692eeba0f2421151f3496566e2e176c6a4d89058d19479b89e043e1e4bb63f892c9134a5100a3b574afa9f7e6c6688e71ad3038c37587a6efb417e0473e06e14ad083b825c7f1caf0e9e61003da38fe526e421e1abad336ffe81fa166d7ff8714bb1972547f08e0cbb80355387f87ffcea8219f96a108f71e1474b68fd46dfda7bcfe899b9e752f7dbc68cf252f31a68435165de7748460b86341f6e3b10d6f5c3f7e6e813fa5ef538380914e127f21f728e0eb3370597c
ct3: 9a1019a263bf5c2b7473e7afe4c447db8b621e1b68ff78306e2a9f179b0cd3cacc544c3dbf8051f4d4e8bd9f921d07a6a757016bacfcf5075e895f7076303f845a2e7b6971184040cd98d6ceb90ce321afc89374230910051da77a080f544bf0f2c59dade7cb76d055763a9759ef7063d603012e2e525a7801d7928cdf68346883580415447e297107822d298b21522c472a9828b19667dd83cd3250a656f0976a320c35af7660b40900a6b714d6d531a63ea20c1c1982a959d87fe5fc502a0932a688c4530ebb9abb5d696fb8f29eaefdbdd5683d44c3438418c3c8469345fbdb2de1c230c5d36a0aba17fb671dd5b952903e314cdbf467263feedfa1c470879a91b2008600af5f7b69004a34ac6274e4484ea383caf910be86dfa19c43a38518254a04699a54c5718363e9c2a16e56d91bb4e2373069fd9934bfef2b853a79554f57ea4a7c8f199853122df8e556c0b4cb51894c0f5a232555242d2e48ec554bbdadaf5b4baa2cb6cbefe4463422fad383723f9757ad71fd594dbc984a54939b37c19634e62cf10f859e2a712ec603c15bff5526ab6248be1f118c5afa84181d067e4e9f1c0176a2753880634c148518c169a3aa695f12b68d54c4a9f8f976d3a6b0420ac0a39d51638c71199d87b5f185fdc4298247dced58026e3f9ab79424ebda18e8053d5e508f66137fa632b9a5dcd4a25e4d9c5bda508ea9d1a2afb01511387e3b5d3f985e6ac97c7cb8614b316d3a3838acdd808c23d25c19cfd2116cecbda92cae83deb555c8ae8cc983aac571c9e4365a0c0d077a401df2bb8596f7d457f093367b0e49a1a11e79c7723d20a9e4b54d535a945e958323c4d39b648fd314dbb4afafad01c5504cc860f891f89d60a4d87dd90e53b89192bacc0a935c3253dc5f8454f776305d418734b3d5e4c71b6dabcc3230141f2e92129f415ccab55e1d81f07ea8709b008026001d994dad50cb1583a3b141e0a9fa5a2fb20b82558f04090f889b7f9bec4a5055a5f3ef60b278f5fc2c6ed8c51f826b9cc5be88cf667d8f7394342a7735b65001c766ec62f0a94970d90cf94d4d53f6ad8d273f2c6163390321578b2835e396072b6cbf7876e46e24c14a821b85a5be90b34147f0d8e553e361709c7871dda118dac4e1a11b254fe6eaeec628289e6a6fad2d1382c6602dd92b5026a123b1a6d972d9c4000c480574ce1c2c45e33c5437d469857a427964e05ec79ade151943ab01c33bc6e4eff64d81515851f08b3ba64854683217595397161173a47e5de056b290dc47324c68fa47ce7a53c19048d72b549bfa70f2d9f8e06e3d27214be154f9668b02bfcf69576c15ce42e6736e4dff74a21f3754ff7e4ad396132435f19ae605dbdbffba84f99898ca7fb51055af2093658eab899a06318a0e30b01c3b731df1f22751bbce2db6f2a1bd695b386b42203327fb51fddfc616c838f046e6aa6af7149335b43460d6e578eac6c0d3950c3577957ada59d1a68bf12b652a4bdde7cc7dbe304f3e608dd0581439394c3f3e73bb79ef288bdda8d7bc6d2f4b1d31997e320005a92426ea75264fce6fcfd256a17290cac2a62c29dfbfe7e9b0c31ce48643612a949277ac98b6403cd94a99a5c187067562f63377bf7819fa3f0a626dd9d3d53238e60b2603d5cf9ec83ef5c028841799fa11e213c43a549aa1916ad48b27bbd894a7a4825ad2cbf25cec2dacb1da3a22b916a5f2988c17c624f7100d8c9fe6331c3c04f81653798935dfb231ff2802cd8d01700f17e77fbb794dffd6bec64fb8158202f2b989d8a6df2d5970b83f75c9ea6d4b372069254d4bbb926db3cc2758c5a95e573a9af016ace085db954561900a867490a99df789435589bc471936e159521daea5e4a5a90fc37f657cb5c694ff39fa35ae59f45dad5088e923319caa5afd9c46d974a498d339c6b05cd06d07cdda7648d60c6153b452c734e4935cbb3bcf22b3433a8dcca328bc147e697cadd0bd2ff0d0f4c93bf17af2df0ff4a36808f9cc2f6f838518
key3: 2b753a867adf4ee6123c63a3da5960a6d6f272bf0322e747bff70403bfd43d522ae42ce795840ebc3ba5e28a7b5c689dd6b87c2251ad9d01e5d3b5d08fdb46a7bc8ec51c753568284ffe7d995e5cd998f4dbcfbd6e8c250e989714b99588a176a8d8e50bec8d41485261bca97f7461a53332a6c91abfebe2a3289e66487fb0d7158f122a0f5726eeb25a79eb399f8b409a0620ce369236c9964ea3e1ded237b0fe230191c696814c10a9716c60820ab63f611bf9ea7b096f8075d229bc153a48c8fb20276c85a00731c032ba37ccd1ca8ae648a086cf4348b4f201018745bcef88c38dd0c245a675e565796c601c9b9527debed789987b3c688df53b07e336bff1354b3d3e8756bba71fe8279bf2901a18826bb9c7cd48fa7497656527e3560cea33892d0721f72d89fe3e9818858b4552410231122f600969b0aec134f641732d6f43c0b8dc7e69a2466d5dd86fbdbf249b9b63aa2854b982a750a3c378bcbfdc43d1a76b63308d43f726c893f49dab576dff84c372b3a6d304a58dd0c1626b4dd79ffb0bd202575852248c19c80d1072ab8a51c1d25c6655f943d69274046ba3c03e00b90b1f6191707bbc29665427b931b57b07c0cf11f1c9e37b116351d859e2108d019b01a46b92d66ca856ce2f13786be209f75e2f26304a0beb57301e6f9107ff519f8dad84508410c72364cefd30e4e787a04152a8434f3d69cd09aaf507a6538b9ad9518932aff7e4f5f663e74c9c5e0e22e395c47fd1606943ebd382ae0103294f7c71a440c0145ad0eb4f27300dbb959537bc7963d9f37c0c327e3a915f77c40877939b5851a5bef25ca780a84ccef204654e20547d92b51f992ec8600610ec65ceb15e68f1c61fe36a2f8fc1e98b4aec24328b4db20b877807b35ce79524321d7820baf3930e238f939211871ae3ce955c2a7746d8afade9cfe61fb127a69cf3583c753f45737de444fcf48c04136d7d29f05074360718a74816992e0fdcff8a307be089b8f6e82d6e9b46917e2c5125f394fdbd55bb3044770886039df83c23de68ad85b9116681e4f7d2f0ebd1e68f842ef65a7af782a5556be66acd8e91033a37ac673a7937705dfd1174359d80af5e0dccb1de9b259e27fe4c13c841a11de51bd25817eb129736d2cd4c3049209c88d717815bb77eaedf5540fa6300c11291d2032e2e173433e10ab545c2bfec4de29a82efe30b2b6ddd8fad574531b5170daf39c2dbb398693e37e548eb05f0636e72b36d477e4fc2a2a57f7da6ca08909262871cb365dd2c37d3745413960978a7db2cf72c553c20789ba26d6078be4754ab07b82c6fe833edcdd3694741c163ce7175a6f0b43b686d421f64ef084904ffe0f0ab7ccd4a8cb1c99a8a518a451371d0e1807d32c906d65fea33a5e3ed0a6c89e00323f12012e0902b1bbdefcdec190bb37d317ad26dbea94a006dbadf19b9ede96b8001f41da3986d8e57bfba946d43bd8d12972fa468492ff69b95ab527d69c8c66bce25a9227ef3b575c3995abb6659d1775130399f072ba53f8fb79cf166f03a4096692a4ee126f959691689268636b851bba66cc3061ce267a6661d4bf54e3e846a51520467ea582ade3a139af556f09bc9f985575c4035036f41aecdce899d2eace709ebc40d8854ea21ee4f890c8a49c995a8a73682890a6d8579621d05110b250c6b4402b7443d753dae85a2805a950a89b0c47c874bdd474f0ff3e4ba3ba571e198798f10f24ae84491cc5b1211f58ea07ec9a3314b76e1a945075de2b3d9012d5fe2c93d8d46b9ce72e3c1536e23d8b19dbf48147bdb73d8f58c3940b0dcccd8d1a9bcc3165da911fa13c5a038aa9f101e3bb01a6db3564afe83943ba24901d3749b9e7e2f13b7c4391922d93dbfe8d92726793f8f676c87099ab1f0ce5190f98c7c6a1f12762b8571e9195df6c460b97b9e5854baf40a04e0f24f28ad6de50d0faf31f623c61552ac5249472b921fd9178c96c667a5cfc4fb48e9c3c10e66f1f69e43b43a542c44820572c26c69
```

## Phân tích
Ta được cho key3, ct1, ct2, ct3. Khi đọc code thấy flag được mã hóa qua nhiều bước nối tiếp nhau ( qua cauhoi1, cauhoi2 và cuối cùng là 3 lần cauhoi3). Nhưng các cauhoi đều bị ẩn đi ?

## Ý tưởng 
Muốn tìm flag phải biết cauhoi3, cauhoi2, cauhoi1 là gì và sau đó tìm theo thứ tự ngược lại là được.
Mình thấy cả 3 hàm cauhoi đều nhập dữ liệu kiểu bytes vào và trả về kiểu bytes.
Lúc đầu nhìn vào hàm cauhoi3 thấy đưa vào 2 biến bytes và trả ra 1 biến bytes thì mình nghĩ là phép xor, đọc lại phần mô tả thử thách của anh r1muru thì có câu này 
![image](https://hackmd.io/_uploads/HklOuIimpxe.png)
Từ đó chắc chắn cauhoi3 được mã hóa bằng cách xor
Xor ngược lại 3 lần thì tìm được wreid:
![image](https://hackmd.io/_uploads/r1Ls_jXael.png)

Cho đoạn trên vào cyberchef magic thì biết là được mã hóa bằng base85 
![image](https://hackmd.io/_uploads/rkaTws7pel.png)
Dịch ngược lại qua base64 thì được như sau: 
![image](https://hackmd.io/_uploads/rkLpdjXpex.png)
Bước tiếp theo mình được supporter gợi ý về số 13 cũng như đoạn văn trong phần mô tả đề:
![image](https://hackmd.io/_uploads/B1pOYo7pgx.png)
Mình nghĩ ý ở đây nhắc đến ROT13 nên thử và ra được đoạn này:
![image](https://hackmd.io/_uploads/SysaKsQpex.png)
Đọc đoạn văn thì tìm ra được flag :
>Flag: W1{D1d_y0U_GeT_r1Ck_r0lL3d?}

## Script giải
```python=
import base64
import codecs
key3=bytes.fromhex("2b753a867adf4ee6123c63a3da5960a6d6f272bf0322e747bff70403bfd43d522ae42ce795840ebc3ba5e28a7b5c689dd6b87c2251ad9d01e5d3b5d08fdb46a7bc8ec51c753568284ffe7d995e5cd998f4dbcfbd6e8c250e989714b99588a176a8d8e50bec8d41485261bca97f7461a53332a6c91abfebe2a3289e66487fb0d7158f122a0f5726eeb25a79eb399f8b409a0620ce369236c9964ea3e1ded237b0fe230191c696814c10a9716c60820ab63f611bf9ea7b096f8075d229bc153a48c8fb20276c85a00731c032ba37ccd1ca8ae648a086cf4348b4f201018745bcef88c38dd0c245a675e565796c601c9b9527debed789987b3c688df53b07e336bff1354b3d3e8756bba71fe8279bf2901a18826bb9c7cd48fa7497656527e3560cea33892d0721f72d89fe3e9818858b4552410231122f600969b0aec134f641732d6f43c0b8dc7e69a2466d5dd86fbdbf249b9b63aa2854b982a750a3c378bcbfdc43d1a76b63308d43f726c893f49dab576dff84c372b3a6d304a58dd0c1626b4dd79ffb0bd202575852248c19c80d1072ab8a51c1d25c6655f943d69274046ba3c03e00b90b1f6191707bbc29665427b931b57b07c0cf11f1c9e37b116351d859e2108d019b01a46b92d66ca856ce2f13786be209f75e2f26304a0beb57301e6f9107ff519f8dad84508410c72364cefd30e4e787a04152a8434f3d69cd09aaf507a6538b9ad9518932aff7e4f5f663e74c9c5e0e22e395c47fd1606943ebd382ae0103294f7c71a440c0145ad0eb4f27300dbb959537bc7963d9f37c0c327e3a915f77c40877939b5851a5bef25ca780a84ccef204654e20547d92b51f992ec8600610ec65ceb15e68f1c61fe36a2f8fc1e98b4aec24328b4db20b877807b35ce79524321d7820baf3930e238f939211871ae3ce955c2a7746d8afade9cfe61fb127a69cf3583c753f45737de444fcf48c04136d7d29f05074360718a74816992e0fdcff8a307be089b8f6e82d6e9b46917e2c5125f394fdbd55bb3044770886039df83c23de68ad85b9116681e4f7d2f0ebd1e68f842ef65a7af782a5556be66acd8e91033a37ac673a7937705dfd1174359d80af5e0dccb1de9b259e27fe4c13c841a11de51bd25817eb129736d2cd4c3049209c88d717815bb77eaedf5540fa6300c11291d2032e2e173433e10ab545c2bfec4de29a82efe30b2b6ddd8fad574531b5170daf39c2dbb398693e37e548eb05f0636e72b36d477e4fc2a2a57f7da6ca08909262871cb365dd2c37d3745413960978a7db2cf72c553c20789ba26d6078be4754ab07b82c6fe833edcdd3694741c163ce7175a6f0b43b686d421f64ef084904ffe0f0ab7ccd4a8cb1c99a8a518a451371d0e1807d32c906d65fea33a5e3ed0a6c89e00323f12012e0902b1bbdefcdec190bb37d317ad26dbea94a006dbadf19b9ede96b8001f41da3986d8e57bfba946d43bd8d12972fa468492ff69b95ab527d69c8c66bce25a9227ef3b575c3995abb6659d1775130399f072ba53f8fb79cf166f03a4096692a4ee126f959691689268636b851bba66cc3061ce267a6661d4bf54e3e846a51520467ea582ade3a139af556f09bc9f985575c4035036f41aecdce899d2eace709ebc40d8854ea21ee4f890c8a49c995a8a73682890a6d8579621d05110b250c6b4402b7443d753dae85a2805a950a89b0c47c874bdd474f0ff3e4ba3ba571e198798f10f24ae84491cc5b1211f58ea07ec9a3314b76e1a945075de2b3d9012d5fe2c93d8d46b9ce72e3c1536e23d8b19dbf48147bdb73d8f58c3940b0dcccd8d1a9bcc3165da911fa13c5a038aa9f101e3bb01a6db3564afe83943ba24901d3749b9e7e2f13b7c4391922d93dbfe8d92726793f8f676c87099ab1f0ce5190f98c7c6a1f12762b8571e9195df6c460b97b9e5854baf40a04e0f24f28ad6de50d0faf31f623c61552ac5249472b921fd9178c96c667a5cfc4fb48e9c3c10e66f1f69e43b43a542c44820572c26c69")
ct3=bytes.fromhex("9a1019a263bf5c2b7473e7afe4c447db8b621e1b68ff78306e2a9f179b0cd3cacc544c3dbf8051f4d4e8bd9f921d07a6a757016bacfcf5075e895f7076303f845a2e7b6971184040cd98d6ceb90ce321afc89374230910051da77a080f544bf0f2c59dade7cb76d055763a9759ef7063d603012e2e525a7801d7928cdf68346883580415447e297107822d298b21522c472a9828b19667dd83cd3250a656f0976a320c35af7660b40900a6b714d6d531a63ea20c1c1982a959d87fe5fc502a0932a688c4530ebb9abb5d696fb8f29eaefdbdd5683d44c3438418c3c8469345fbdb2de1c230c5d36a0aba17fb671dd5b952903e314cdbf467263feedfa1c470879a91b2008600af5f7b69004a34ac6274e4484ea383caf910be86dfa19c43a38518254a04699a54c5718363e9c2a16e56d91bb4e2373069fd9934bfef2b853a79554f57ea4a7c8f199853122df8e556c0b4cb51894c0f5a232555242d2e48ec554bbdadaf5b4baa2cb6cbefe4463422fad383723f9757ad71fd594dbc984a54939b37c19634e62cf10f859e2a712ec603c15bff5526ab6248be1f118c5afa84181d067e4e9f1c0176a2753880634c148518c169a3aa695f12b68d54c4a9f8f976d3a6b0420ac0a39d51638c71199d87b5f185fdc4298247dced58026e3f9ab79424ebda18e8053d5e508f66137fa632b9a5dcd4a25e4d9c5bda508ea9d1a2afb01511387e3b5d3f985e6ac97c7cb8614b316d3a3838acdd808c23d25c19cfd2116cecbda92cae83deb555c8ae8cc983aac571c9e4365a0c0d077a401df2bb8596f7d457f093367b0e49a1a11e79c7723d20a9e4b54d535a945e958323c4d39b648fd314dbb4afafad01c5504cc860f891f89d60a4d87dd90e53b89192bacc0a935c3253dc5f8454f776305d418734b3d5e4c71b6dabcc3230141f2e92129f415ccab55e1d81f07ea8709b008026001d994dad50cb1583a3b141e0a9fa5a2fb20b82558f04090f889b7f9bec4a5055a5f3ef60b278f5fc2c6ed8c51f826b9cc5be88cf667d8f7394342a7735b65001c766ec62f0a94970d90cf94d4d53f6ad8d273f2c6163390321578b2835e396072b6cbf7876e46e24c14a821b85a5be90b34147f0d8e553e361709c7871dda118dac4e1a11b254fe6eaeec628289e6a6fad2d1382c6602dd92b5026a123b1a6d972d9c4000c480574ce1c2c45e33c5437d469857a427964e05ec79ade151943ab01c33bc6e4eff64d81515851f08b3ba64854683217595397161173a47e5de056b290dc47324c68fa47ce7a53c19048d72b549bfa70f2d9f8e06e3d27214be154f9668b02bfcf69576c15ce42e6736e4dff74a21f3754ff7e4ad396132435f19ae605dbdbffba84f99898ca7fb51055af2093658eab899a06318a0e30b01c3b731df1f22751bbce2db6f2a1bd695b386b42203327fb51fddfc616c838f046e6aa6af7149335b43460d6e578eac6c0d3950c3577957ada59d1a68bf12b652a4bdde7cc7dbe304f3e608dd0581439394c3f3e73bb79ef288bdda8d7bc6d2f4b1d31997e320005a92426ea75264fce6fcfd256a17290cac2a62c29dfbfe7e9b0c31ce48643612a949277ac98b6403cd94a99a5c187067562f63377bf7819fa3f0a626dd9d3d53238e60b2603d5cf9ec83ef5c028841799fa11e213c43a549aa1916ad48b27bbd894a7a4825ad2cbf25cec2dacb1da3a22b916a5f2988c17c624f7100d8c9fe6331c3c04f81653798935dfb231ff2802cd8d01700f17e77fbb794dffd6bec64fb8158202f2b989d8a6df2d5970b83f75c9ea6d4b372069254d4bbb926db3cc2758c5a95e573a9af016ace085db954561900a867490a99df789435589bc471936e159521daea5e4a5a90fc37f657cb5c694ff39fa35ae59f45dad5088e923319caa5afd9c46d974a498d339c6b05cd06d07cdda7648d60c6153b452c734e4935cbb3bcf22b3433a8dcca328bc147e697cadd0bd2ff0d0f4c93bf17af2df0ff4a36808f9cc2f6f838518")
ct2=bytes.fromhex("770178bcb4c79bb17a3e9d3fae37aff128817b9528af0fd6ba9b35638095318ca7c640c7b5f4ca9dd5621472887287fc07d9bdeea79c6c68d059cc3e497c036e8fbf6b9ed480d3b4be6069dd834c6a9a162ba2a879cdf7286697670c9d299086e79844760caff21366ebf507d59fe40a0a59fca4df49fb306937faeb4d3b6ad266c2def5b5d78ef5cb6fd66a2e4cbe251d54e71478f539a82683d7f403e583bddcd0db7bf992c6dc1d50de5066c209bf14995e92b0383437719e3f93ccbc9eda83674d770d7d29b182e7fe3f1b791de8231645dfd3c258ae65fec2e1f1e9693c4f138b3b3c714385285fe25c7ab1a7c77c64c974e003c2d0ca4c144f7a6ebeba7d556aefe0929658b96b9252e7c3682a611915583da9c20ca84d3ef1b551f41c5f2adfb76970f8653342064587693dba7318d8118dd1f31ef27f22caad90c1f9145d71074fed2d81928c29d077ad92b679fe8d79ded8c62ca8bf53218df5439b1a81d6f21df99e0432c67f6002a0155b82f0f6953b6c5a5324df90333fe1c731f792e3f27fdc09047b13de99fcc1763cd1fe7a0587becbbf2ce09b9897c6325258450055c49bcf3506db1a2b055f7a029e99f1343888d8d8fa4a84be11ca1f5b85ffbf00b96dc61d05db4b446eba1a53aae9bdbac981d7046ca3158e67cf7e3f9c357fea73718d61da1e0fe42a4e4f10490495deee5174f02326b591b7dbf8d0e52841faf4da6b469d250f65ed794f08c438307752ab5368db551da6aba167bbf3ddb34e54f4ce725512721343714338901492fa298db176449277011ae92d252a7a9c5aac970dfd004329fdb2b0ca7a6d543ee133ed5a3d31e0a1b15a07cb366a25d5569eb124d74237604688fabc5bdec532ef76825d8592e910f6e59b843e8487605e0d823af50b0dea4bd199a9e52818fd90de3194fc0c9e3d30de743301a154cf08e40068234acdc8b4e5b39ca8f0053439db32b029ecc44b74998635d433eaf174b5946715e5ffdb21e3315f3a412c7e2b6ff53832befd256164ef47697dece91de9e7bc2d0095bde64422ef708223d6c0e59f0e0762197d59846b0c9f3060edc4cabc79e01acc72c8580af50b959b2436dde3753fa316cfd9a789facb770c3afdf04a183e897ff5b5b8366f8c3092b1d1ab0975c0f83b0a1da0a1e105cc067339bdee25f82d9a5e02d8ce593691e370e1ca297849e9e932d0773590a61a4ff645b468ad0d9fc0d1899e2ff5aa168d61fda073792e33c50f4a566385b87566afc14449b4fb9ac662a0f9267a872565f6e3458c24999c3972524c7015ad02ed24d93268d362b32ea6f6ea00ebabbae9968cab114f8f835a03802850951f5c16c5446d5f2910b1e72618e453b21e132b2275608471915271e019efc6324a88af1ec0a2c0840f676c64636ac7e8801f67befe418557956f9fb8274031392cb121b5f73434f30436a486f13cb36e39a9ee3bef53a1acbb90340755c2a06a6f1c21fb9f9ac3e520e20a90b952378d2759ae789ab26acbed14fab5d2d5c40e420a356c7ff0050d7368efd10cea07d9a1d7eeecc91ce13a066c93690a513d3cc7b1bbd468575aeb7b3563d60b82613b9ae50c5df8f26ae5bfe84677cc54898d504644e5b423ba47b507b30d495dbaa2e5f87f780be3b9562c1bfe1a1f79d828c4867274d2b5b31ef750f965d4a84dbadef33871e435d61425578fec1f1f6651d615fde35697e31162658239110e4b0ccf1d05e50ac275a82ddc8f7920dda8021f7c14e36692eeba0f2421151f3496566e2e176c6a4d89058d19479b89e043e1e4bb63f892c9134a5100a3b574afa9f7e6c6688e71ad3038c37587a6efb417e0473e06e14ad083b825c7f1caf0e9e61003da38fe526e421e1abad336ffe81fa166d7ff8714bb1972547f08e0cbb80355387f87ffcea8219f96a108f71e1474b68fd46dfda7bcfe899b9e752f7dbc68cf252f31a68435165de7748460b86341f6e3b10d6f5c3f7e6e813fa5ef538380914e127f21f728e0eb3370597c")
ct1=bytes.fromhex("944073d9c2fdec4334375867fcd9b0c4545d20152151f6d008259a14ea339e4e0a38167ea99fd4817b4e22565772b28c5b6781c67bf16c0c4f4e0efdeaf21f0a5a7e96bff3e8a39008788fd8256c2b522c6d9b446a29e456dee859f536ba1241e5df09a25ea1abf820ab0358c554afaadf371e02b2dc6f949da28f539b4d9845d962a9899280c2301b8be293c69a241d8e39059e9fbf3fe3772b0500505867df29e4afacd12578114bbb48d17ebf9779d784d05e2479dfccc072c814a1b4d6d8286da2d553b1726a5f2590a9d80604fc7038bb6f2f3999f23d4e37626760d4035fb8cc10bdc66ea4b0a8b9a82283c1a1680f0ca91c226ee2a1af6e8dbd03b5d47c88d6e90f5505f02f7e4e5c03c3cd2ba4e66e2049ec32b4032aae025a9065dec4744aef76926beefe5f7a560a3d82e0c603348081889bcf4ec751be9b899cb23a0c117d8c15b0c9e7e217f92f024d8ed2c028e36eb5bbdc332f04981bf05226ab15dda261e569e8869b97228021c84f454d18570a6120dc40d30679154997b91d1398ef2dd166fa64ee1169c550f506013a327c34889eb0b172878f356ec042d3a22c52a3ed99536fbd6f6f1c2058f25c2314adf4190782e542644af809fd80728c7bfd9a53016565615f1cbe323ea5057679ffd8cdaaa29ea41cb3df37aecbb669e0339bbc52ab3885bbb7eef8273f5dbfeeca6d96efda197004473fe41ba54b1a898f0f30f3ec0b253b8d3555ae0a7948d74b2f083c3cf26035f9b97819124dd930c2747950bf0d6d35e7d82a7f8d3f0a7c8ef012b6926efea881d877e9acbf16a883a98d292193fcbf332cc8a5b6b732abc3cbff2e9e19531053759cae090eaf90b7b8357c9351aeacb13c4c03b1fbf8eea7a35ce1ee793f530eae06e55fe536d0ec0c5a4e70a4f6735a240ac0e38713d14ffa32c88927908b3f273febc81e268fe4a6473f8f0e3fca74c436e08e1f1b3690d0b41b29a519bdf7ba78e6fd0dc915dc78609eaf16c4cedc3a71c406b2bbfb0bfe6d86e9e2e00d6f7a1dc8be264751cf3e84bf58cd266b3f33e0948df9d5fcee3b1405192c5401d0bd3b97839260165935e254d64cbf4a2ea318bfe17fcf241f082e8b0ec78dc68369b02d1e1d9900184fe3b62bf56cc4ed66c0dccd433beb8585295cd478d3216eea43f258da09e7011549d9235e4763c57f46e985b6f2e9561157688e266e67b35e1ee8180c00d26b14cea81417b6244175d48d2381364d4fee04df5ea1aadacc07653f1e4857550648644dd62924caa4bf6d9df4cf2fb66e4b4287de8bcbb4fa45d06c1f54256e34639b2ec6cb8e9c9bbb0ad655b6e65c4372688ccf44e65f263f2b677f800e5b4a9464c611e51c1ad31637b7933313bd73e037e0a738ef0d782427a0b56c255dc9e1febf42ed6cbefc27f138aaf00336992a2e970d597bd037f05ff6cc92477a3528c5daaf6bd3c8d47c67ed6f91a4348ea43125352f34842843bb467220097384291a43b098a6c41611041fbfa9900a7733129710436da9c991a08c50eba4ebb7b22165a111cadbb0c86f6448f574857b561fa0813528ae886ad0e80192b53c21c831a317e7f2fea1521f8b3e237b79e40245feac47ae9a8d99fd1ee8f11aaaf8cc6fd7b1a066ae9299b210c55b7651b2052a4be88fd1eb3a85f515adb388d504507236464ef0c83151001e0035b6e55de0bd5091305cca1002de0d4b0fe920ddad16232d0cf82e0c7588399bad23a3bfdbcdda2fdaa532c2f421bc25480e395f5db0d724748b3751156c29348494c88d4fbc75b6a9997dd714a66228f1099f2d36ecab036d77728183c704beae2cfb594dd8484c0d2b299626e1413a584fef756c73945200f16cf05b79568dc94b56dab9569adcdd000d55aa04b35115ec11ba53bd8a05e576d5956b4df9170b6e65c9849a6204fb62c98ef2b8d3d138f95d0335180831ebee7f5583e737c4782895f082defaae68775825a2ab34403347261a6fd497ee7a9eadf050e9954a01b173aaf5e9a21a03d66f")

key2 = bytes(a ^ b for a, b in zip(key3, ct3))
key1 = bytes(a ^ b for a, b in zip(key2, ct2))
weird = bytes(a ^ b for a, b in zip(key1, ct1))

wreid=base64.b85decode(weird)

rot13 = codecs.encode(str(wreid), "rot_13")
print(rot13)
#flag: W1{D1d_y0U_GeT_r1Ck_r0lL3d?}
```
---
[5]
# [SOR SOR SOR] 

**Category:** Crypto   
**Points:** 500  
**Author:** L1ttl3
**Solve by:** VuiVe  



## Đề bài
![Screenshot 2025-10-05 155230](https://hackmd.io/_uploads/H1aA2i7ale.png)


```python=
import random

with open('flag.txt', 'rb') as f:
    flag = f.read().strip()

assert len(flag) % 3 == 0

def xor(a, b):
    return bytes(x ^ y for x, y in zip(a, b))

blocks = [flag[i:i+3] for i in range(0, len(flag), 3)]
ori_blocks = [flag[i:i+3] for i in range(0, len(flag), 3)]

random.shuffle(blocks)

assert all(ori_blocks[i] != blocks[i] for i in range(len(blocks)))

print(xor(b''.join(blocks), flag).hex())
# 2f01090a6f042b4447101f0047460d6e0e5d001100422d156443022c4a3e074a392b033e531d1b47401b44423c411e08

```


## Phân tích
Đề cho flag có độ dài chia hết cho 3, sau đó chia flag thành các khối nhỏ 3 bytes và cho vào blocks. Các khối trong blocks được tráo ngẫu nhiên nhưng bị ràng buộc rằng các khối đảm bảo phải đổi vị trí.
Cuối cùng xor flag và blocks và chuyển hết thành hex 


## Ý tưởng 
Bài này mình không biết viết script nên giải hoàn toàn bằng tay và nhờ Gipiti hỗ trợ nên không có script giải

Đầu tiên ta chuyển mã hex thành bytes trước:
```txt=
b'\x2f\x01\x09\x0a\x6f\x04\x2b\x44\x47\x10\x1f\x00\x47\x46\x0d\x6e\x0e\x5d\x00\x11\x00\x42\x2d\x15\x64\x43\x02\x2c\x4a\x3e\x07\x4a\x39\x2b\x03\x3e\x53\x1d\x1b\x47\x40\x1b\x44\x42\x3c\x41\x1e\x08
```
Gọi đoạn bytes trên là key để tiện dịch ra flag
Ta cũng chia flag và key thành các khối 3 bytes như blocks ( được tổng 16 khối)
Ta biết mỗi khối đều có giá trị 3 bytes và biết được 3 kí tự đầu của flag là " W1{ " vậy có khối đầu tiên của flag, sau đó xor với khối đầu của key "\x2f\x01\x09" được "x0r" là blocks[0]:
![image](https://hackmd.io/_uploads/SJAvk276xg.png)
Mình suy đoán"x0r" là khối tiếp theo của flag ( nếu không suy đoán thì làm lâu hơn ) và gán vào khối thứ 2 vào flag, xor cùng khối với key được "r_v", là blocks[1]
![image](https://hackmd.io/_uploads/H1cLg3maee.png)
Vì blocks và flag là một, nhưng blocks tráo đổi các khối 3bytes với nhau nên nếu flag có "W1{" thì blocks cũng sẽ có, blocks có "r_v" thì flag cũng có.
Do đó ta thử coi "r_v" lần lượt là các khối của flag( trừ khối đầu tiên và thứ 2), xor lần lượt tương ứng với các khối của key ( đoạn này mình nhờ Gpt làm )ta được danh sách:
![image](https://hackmd.io/_uploads/rkXqWhmpxl.png)
Có thể thấy ngay ở blocks[8] thì kết quả xor đẹp và có thể đọc được "3ry", ghi lại vào bảng
![image](https://hackmd.io/_uploads/H17R-27axg.png)
Tiếp tục quá trình dò từ blocks lên flag/ flag về blocks và chọn các giá trị phù hợp, sau đó thử các giá trị phù hợp vào các khối trống 
Qua rất nhiều lần thử và chọn thì tìm được flag:
![image](https://hackmd.io/_uploads/Bk9IGhXagx.png)
>Flag: W1{x0r_p3rmut4t1on_a3r_v3ry_3asy_t0_brut3f0rc3s}
---
[6]
# [SYSTEM OF EQUATIONS] 

**Category:** Crypto   
**Points:** 472  
**Author:** r1muru  
**Solve by:** VuiVe  



## Đề bài
![Screenshot 2025-10-05 155021](https://hackmd.io/_uploads/H1tJrnQael.png)


```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)
```


## Phân tích
Theo mô tả đề của anh r1muru và đọc đoạn code thì chỉ cần giải hệ 3 phương trình thì sẽ ra flag 


## Ý tưởng 
Bài này chỉ cần giải hệ phương trình 3 ẩn ra x,y,z và nhập vào file chall.py là ra đáp án
Cảm ơn Gpt về phần script giải hệ phương trình 3 ẩn ( vì mình không biết giải )
Sau khi giải xong ta được 3 nghiệm x,y,z="33131538, 22029258543363862, 604095676625"
Nhập x,y,z và chọn phương thức là decrypt
## Script giải
```python=
from sympy import symbols, Eq, solve


x, y, z = symbols('x y z')


eq1 = Eq(x**2 + 2*x*y - 4*z**2 - 4*y + 8*z, 8)
eq2 = Eq(x**5 + y**3 + z**4 , 10823714993004958804353333960725385073542379465721)
eq3 = Eq(8864612849141*x**2 + 8864612849141*y + 17729225698282*z  , 205022233466935232483321764396)


sol = solve((eq1, eq2, eq3), (x, y, z))
print(sol)

```
>W1{y0u_must_b3_th3_m4st3r_0f_3quat1ons_817e31a7ccdbe8fd}
>Cam on Gipiti
---

[7]
# [LEARING WITH BRUTEFORCE] 

**Category:** Crypto   
**Points:** 388  
**Author:** Nhan_laptop  
**Solve by:** GPT
**Idea by:** VuiVe



## Đề bài
![Screenshot 2025-10-05 154911](https://hackmd.io/_uploads/SJ0EygNTxg.png)


```python=
from Crypto.Util.number import *
from sage.all import * 
import numpy as np
flag = b"W1{????????????????????????????????}"

e = [2506,2006]

def rebase(n,b):
    if n <= b:
        return [n]
    
    return [n%b] + rebase(n//b,b)


s = rebase(bytes_to_long(flag),3671)

n = len(s)
A = np.random.randint(1,3671-1,(n,n)).tolist()
s = vector(GF(3671),s)
e = np.random.choice(e,size=n)
A = matrix (GF(3671),A)
e = vector(GF(3671),e.tolist())

print(f'b = {A * s + e}')
print(f'A = {list(A)}')

#b = (3142, 2772, 805, 2779, 2853, 1921, 535, 210, 1161, 989, 2484, 2104, 1594, 1048, 452, 3586, 56, 1370, 436, 1601, 512, 274)
#A = [(2413, 2531, 3411, 2884, 2264, 377, 3514, 78, 1702, 3182, 3167, 20, 1054, 3422, 3177, 1535, 680, 3425, 3297, 535, 3390, 3619), (3236, 181, 2133, 1731, 844, 3201, 2176, 1268, 1285, 1692, 2874, 705, 1025, 2161, 1800, 992, 774, 625, 1897, 1823, 112, 2314), (1036, 1649, 317, 2345, 1900, 2149, 2964, 1518, 2909, 176, 3454, 2808, 465, 2940, 155, 2209, 3019, 1986, 1407, 2536, 3003, 155), (725, 237, 85, 2270, 1539, 1946, 1357, 1526, 759, 2183, 725, 1639, 2478, 2453, 2591, 520, 3060, 2483, 104, 1788, 1358, 1690), (2084, 1986, 1503, 560, 3033, 1451, 2721, 2749, 3537, 2408, 843, 1955, 498, 1849, 878, 2538, 2717, 3655, 3304, 2856, 926, 2658), (2431, 950, 953, 3046, 2543, 2422, 3552, 3656, 2063, 3585, 825, 2811, 497, 3635, 3445, 2579, 1882, 2003, 778, 2285, 866, 1288), (2859, 2257, 1451, 2988, 2568, 150, 2901, 3657, 1736, 2551, 3084, 3146, 2300, 3205, 3246, 909, 1574, 1345, 2087, 147, 584, 321), (3651, 1560, 3243, 1860, 1523, 1374, 1273, 1296, 1043, 1392, 3063, 2144, 21, 323, 3458, 2766, 2390, 2582, 2815, 211, 9, 1781), (2269, 2189, 1832, 1302, 2167, 2126, 863, 1101, 1177, 1689, 3631, 1722, 1933, 2429, 798, 912, 1360, 1811, 1740, 1759, 1981, 1266), (1788, 2524, 910, 448, 3558, 2913, 2309, 328, 404, 1995, 1633, 2605, 2421, 3488, 2860, 1259, 364, 1196, 1504, 1732, 2630, 587), (1975, 82, 3369, 129, 2504, 854, 1538, 3598, 953, 1324, 1469, 2984, 164, 2565, 744, 2792, 1196, 1383, 2922, 2544, 3609, 2630), (3120, 453, 248, 2510, 2464, 3098, 2459, 1219, 1179, 840, 1374, 2641, 1582, 304, 263, 186, 3191, 478, 988, 568, 3300, 929), (3401, 2877, 2106, 1352, 3664, 3069, 845, 1219, 1780, 3135, 2801, 251, 3617, 1195, 764, 2232, 2919, 693, 46, 3113, 2144, 874), (854, 2101, 3361, 2135, 1797, 3133, 2872, 3494, 2534, 1978, 1066, 1138, 439, 1503, 962, 1509, 2360, 1924, 1574, 483, 2641, 545), (2163, 3377, 253, 2530, 1968, 2470, 2662, 2807, 1264, 2924, 2528, 468, 729, 1707, 2692, 1960, 387, 3591, 800, 1428, 655, 2190), (1569, 3225, 3456, 1244, 157, 2438, 3248, 3443, 547, 967, 1107, 2571, 3068, 3578, 1799, 98, 452, 2108, 3462, 40, 2302, 41), (672, 2649, 1436, 2391, 2011, 2920, 2460, 1672, 3594, 2587, 1647, 1366, 3006, 1449, 2945, 2767, 3023, 991, 82, 1432, 1493, 1498), (1763, 3130, 948, 2461, 2695, 1362, 1558, 3344, 2710, 3397, 1845, 1735, 3493, 450, 407, 2907, 1564, 1203, 1497, 1656, 3651, 2348), (506, 1747, 50, 967, 1100, 2688, 283, 160, 3599, 2210, 3548, 3191, 252, 3519, 591, 3393, 3482, 1364, 1420, 425, 318, 2133), (2136, 625, 2454, 2764, 3635, 3514, 559, 1526, 1301, 2311, 837, 111, 3431, 1363, 3365, 2946, 1116, 1215, 1555, 3594, 973, 3622), (2464, 914, 3225, 706, 1804, 137, 2957, 1278, 766, 3570, 2155, 3634, 1960, 3482, 394, 2665, 896, 529, 1510, 1142, 656, 2868), (1080, 2030, 878, 945, 658, 1134, 2591, 1512, 313, 3348, 1329, 1571, 1108, 3279, 3185, 1188, 1330, 2315, 2885, 3190, 2141, 1307)]
```


## Phân tích
- Hàm `rebase()` dùng để chuyển dãy số n từ hệ 10 sang hệ cơ số b
- s là dãy số hệ cơ số 3671 sau khi chuyển flag sang số nguyên, sau đó mod 3671 và chuyển vào vector s
- A là một list được tạo có kích thước nxn, các giá trị được tạo ngẫu nhiên từ 1 đến 3669 và mod 3671, sau đó đưa vào tạo thành ma trận A
- e chọn ngẫu nhiên 2506/2006 với độ dài là n, sau đó cũng mod 3671 và tạo thành vector e 
- Ma trận b được tạo bởi công thức `b = A*s +e ` tức:
 b$_i$ = (A{$_i$ ; $_0$} * s$_0$ +A{$_i$ ; $_1$} * s$_1$+...+A{$_i$ ; $_{n-1}$  * s$_{n-1}$  +e$_i$) (mod 3671)
- n = độ dài dãy số nguyên s = 22 = kích thước ma trận vuông A (22x22)
## Ý tưởng 
Có công thức tạo ma trận b:
$$ b = A*s +e \pmod{3671} $$
Ta có thể biến đổi ngược lại để tìm vector s:
$$
\begin{aligned}
&b = A*s +e \pmod{3671}\\
&\Rightarrow b-e=A*s \pmod{3671}\\
&\Rightarrow  s = A^{-1}*(b-e) \pmod{3671}\\
\end{aligned}
$$
Vì trong công thức có e là được chọn ngẫu nhiên 2506/2006 nên không thể giải ra ngay mà phải chạy thay các e$_i$ là 2506/2006. Do đó ta có  $2^{22}$ cách tạo vector e nên cũng có  $2^{22}$ vector s. Duyệt và dịch từng vector s từ hệ 3671 sang thập phân và chuyển sang bytes, nếu dãy bắt đầu bằng "W1{" và kết thúc bằng "}" thì in ra và kết thúc lặp.
Đến đây là ý tưởng của mình nhưng mình không biết cách triển khai code nên mình có nhờ bạn GPT hỗ trợ làm nốt phần còn lại 
## Script giải
```python=
# solve_lwb.py
from Crypto.Util.number import long_to_bytes
import numpy as np
import sys

q = 3671


A_list = [
(2413,2531,3411,2884,2264,377,3514,78,1702,3182,3167,20,1054,3422,3177,1535,680,3425,3297,535,3390,3619),
(3236,181,2133,1731,844,3201,2176,1268,1285,1692,2874,705,1025,2161,1800,992,774,625,1897,1823,112,2314),
(1036,1649,317,2345,1900,2149,2964,1518,2909,176,3454,2808,465,2940,155,2209,3019,1986,1407,2536,3003,155),
(725,237,85,2270,1539,1946,1357,1526,759,2183,725,1639,2478,2453,2591,520,3060,2483,104,1788,1358,1690),
(2084,1986,1503,560,3033,1451,2721,2749,3537,2408,843,1955,498,1849,878,2538,2717,3655,3304,2856,926,2658),
(2431,950,953,3046,2543,2422,3552,3656,2063,3585,825,2811,497,3635,3445,2579,1882,2003,778,2285,866,1288),
(2859,2257,1451,2988,2568,150,2901,3657,1736,2551,3084,3146,2300,3205,3246,909,1574,1345,2087,147,584,321),
(3651,1560,3243,1860,1523,1374,1273,1296,1043,1392,3063,2144,21,323,3458,2766,2390,2582,2815,211,9,1781),
(2269,2189,1832,1302,2167,2126,863,1101,1177,1689,3631,1722,1933,2429,798,912,1360,1811,1740,1759,1981,1266),
(1788,2524,910,448,3558,2913,2309,328,404,1995,1633,2605,2421,3488,2860,1259,364,1196,1504,1732,2630,587),
(1975,82,3369,129,2504,854,1538,3598,953,1324,1469,2984,164,2565,744,2792,1196,1383,2922,2544,3609,2630),
(3120,453,248,2510,2464,3098,2459,1219,1179,840,1374,2641,1582,304,263,186,3191,478,988,568,3300,929),
(3401,2877,2106,1352,3664,3069,845,1219,1780,3135,2801,251,3617,1195,764,2232,2919,693,46,3113,2144,874),
(854,2101,3361,2135,1797,3133,2872,3494,2534,1978,1066,1138,439,1503,962,1509,2360,1924,1574,483,2641,545),
(2163,3377,253,2530,1968,2470,2662,2807,1264,2924,2528,468,729,1707,2692,1960,387,3591,800,1428,655,2190),
(1569,3225,3456,1244,157,2438,3248,3443,547,967,1107,2571,3068,3578,1799,98,452,2108,3462,40,2302,41),
(672,2649,1436,2391,2011,2920,2460,1672,3594,2587,1647,1366,3006,1449,2945,2767,3023,991,82,1432,1493,1498),
(1763,3130,948,2461,2695,1362,1558,3344,2710,3397,1845,1735,3493,450,407,2907,1564,1203,1497,1656,3651,2348),
(506,1747,50,967,1100,2688,283,160,3599,2210,3548,3191,252,3519,591,3393,3482,1364,1420,425,318,2133),
(2136,625,2454,2764,3635,3514,559,1526,1301,2311,837,111,3431,1363,3365,2946,1116,1215,1555,3594,973,3622),
(2464,914,3225,706,1804,137,2957,1278,766,3570,2155,3634,1960,3482,394,2665,896,529,1510,1142,656,2868),
(1080,2030,878,945,658,1134,2591,1512,313,3348,1329,1571,1108,3279,3185,1188,1330,2315,2885,3190,2141,1307)
]

b_list = [3142,2772,805,2779,2853,1921,535,210,1161,989,2484,2104,1594,1048,452,3586,56,1370,436,1601,512,274]

# -- end paste ----------------------------------------------------------------

n = len(b_list)
assert n == len(A_list) == len(A_list[0])  # sanity

# --- modular helpers ---

def mat_mul_vec(A, v):
    return [sum((A[i][j]*v[j] for j in range(n))) % q for i in range(n)]

# --- matrix inversion mod q using Gauss-Jordan ---
def invert_matrix_mod(A):
    # A is list of tuples/lists size n x n
    # returns inverse as list of lists
    M = [list(map(lambda x: x % q, row))[:] for row in A]
    Inv = [[0]*n for _ in range(n)]
    for i in range(n):
        Inv[i][i] = 1
    for col in range(n):
        # find pivot
        pivot = None
        for row in range(col, n):
            if M[row][col] % q != 0:
                pivot = row
                break
        if pivot is None:
            raise Exception("Matrix not invertible")
        # swap rows
        if pivot != col:
            M[col], M[pivot] = M[pivot], M[col]
            Inv[col], Inv[pivot] = Inv[pivot], Inv[col]
        # normalize pivot row
        inv_p = pow(M[col][col], -1, q)
        M[col] = [(val * inv_p) % q for val in M[col]]
        Inv[col] = [(val * inv_p) % q for val in Inv[col]]
        # eliminate other rows
        for r in range(n):
            if r == col:
                continue
            factor = M[r][col]
            if factor != 0:
                M[r] = [ (M[r][c] - factor * M[col][c]) % q for c in range(n) ]
                Inv[r] = [ (Inv[r][c] - factor * Inv[col][c]) % q for c in range(n) ]
    return Inv

print("Invert matrix A mod", q, "...")
A_inv = invert_matrix_mod(A_list)
print("Done invert.")

# convert b to mod ints
b = [x % q for x in b_list]

# e choices: map bit 0 -> 2506, bit 1 -> 2006
vals = (2506, 2006)

# iterate masks 0 .. 2^n - 1
limit = 1 << n
print("Bruteforcing", limit, "possibilities...")
for mask in range(limit):
    # build e vector 
    e = [ vals[(mask >> i) & 1] % q for i in range(n) ]
    # compute rhs = b - e mod q
    rhs = [ (b[i] - e[i]) % q for i in range(n) ]
    # s = A_inv * rhs
    s = mat_mul_vec(A_inv, rhs)
    # reconstruct integer from base 3671 digits
    X = 0
    pow_base = 1
    for i in range(n):
        X += s[i] * pow_base
        pow_base *= q
    # convert to bytes
    try:
        flag_bytes = long_to_bytes(X)
    except Exception:
        continue
    # cheap sanity check: starts with W1{ and printable
    if flag_bytes.startswith(b"W1{") and b"}" in flag_bytes:
        print("POSSIBLE FLAG FOUND:")
        print(flag_bytes)
        sys.exit(0)
    # optional progress
    if mask & 0x3FFFF == 0:  # every 262144 iterations
        print("mask:", mask, " /", limit)
print("Done. Không tìm thấy flag (hoặc kiểm tra điều kiện lọc quá chặt).")

#W1{M3ss1_1s_t43_90AT!!!!!!!!!!!}

```
>Flag: W1{M3ss1_1s_t43_90AT!!!!!!!!!!!}
-Nghịch đảo ma trận ( chưa hiểu   ): https://chatgpt.com/s/t_68e68f4ffdb081918aef88abbd5dcba8
-Khử Gauss-Jordan (chưa hiểu nốt :( ):
https://hackmd.io/@Pikachuuuu/rkYAYdEYj#Gi%E1%BA%A3i-c%C3%A1c-h%E1%BB%87-c%C3%B3-modulo
-Cách sinh vector e:
https://chatgpt.com/s/t_68e68fe0829481918a1e9b27c07a458b

---

[8]
# [BO 4 SIEU DANG] 

**Category:** Crypto   
**Points:** 500  
**Author:** L1ttl3
**Support by:** Nhan_laptop, L1ttl3, Mai Đăng Khoa
**Solve by:** VuiVe  



## Đề bài
![Screenshot 2025-10-05 155326](https://hackmd.io/_uploads/BJ4qlt8pxx.png)


```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
```


## Phân tích
Phần mã hóa chỉ có đúng 1 dòng là 
$$ c =((((m^e \pmod{m1}) \pmod{m2}) \pmod{m3})\pmod{m4})$$
Gọi 
$$
\begin{aligned}
&a=m^e \pmod{m1}\\
&b= a\pmod{m2}\\
&d=b\pmod{m3}\\
&\Rightarrow c = d\pmod{m4}
\end{aligned}
$$
Nhìn form của a rất giống RSA, còn thêm e=65537 nên mình chắc là RSA
## Ý tưởng 
Muốn giải RSA thì phải gỡ được hết các cái mod bên ngoài:
$$
\begin{aligned}
&d=c+t_1*m4\\
&b= d+t_2*m3\\
&a=b+t_3*m2\\
&\Rightarrow a=c+t_1*m4+t_2*m3+t_3*m2=m^e \pmod{m1}
\end{aligned}
$$
m1 không phải số nguyên tố và cũng không phải là tích của 2 số nguyên tố. Nhờ gợi ý của anh L1ttl3, mình có search cách giải RSA khác:
![image](https://hackmd.io/_uploads/HJ28dKITlg.png)
Tức là ta có thể phân tích m1 thành các thừa số nguyên tố và giải, m1 phân tích thừa số nguyên tố được 7 số ( theo factordb)
![image](https://hackmd.io/_uploads/ByVp_tLall.png)
Nhưng mà số cuối không phải là số nguyên tố nên ta chỉ dùng được 6 số trước.
Vậy ta có:
$$
\begin{aligned}
&m=a^{D_1} \pmod{p_1}\\
&m=a^{D_2} \pmod{p_2}\\
&m=a^{D_3} \pmod{p_3}\\
&m=a^{D_4} \pmod{p_4}\\
&m=a^{D_5} \pmod{p_5}\\
&m=a^{D_6} \pmod{p_6}\\
\end{aligned}
$$
với p$_i$ là các số nguyên tố được phân tích từ m1, D$_i$=e$^{-1}$ $\pmod{p_i-1}$
Với 6 phương trình trên, ta dùng CRT để giải và tìm m
## Script giải
```python=
from Crypto.Util.number import long_to_bytes

def crt(M, p):
    N = 1
    for m in p:
        N *= m
    x = 0
    for r, m in zip(M, p):
        Ni = N // m
        Mi = pow(Ni, -1, m)
        x += r * Ni * Mi
    return x % N

e = 65537
m1 = 2**1024 - 3
m2 = 2**1022 - 2
m3 = 2**1020 - 1
m4 = 2**1018
c = 2027792127378145444099302510462900300257442068928010403052259994880511317607407514908720534902489134379904618947792557805368190009359079320337075768626232418980864987406619809977532904702783433112202254001367719098893178820312980355187703995660867067442830169498602243151057835147454968516377852012013934653

a = []
#tim cac gia tri m^e mod(m1)
for k in range(0, 8):
    s2 = c + k * m4
    if s2 < m3:
        for j in range(0, 8):
            s1 = s2 + j * m3
            if s1 < m2:
                for i in range(0, 8):
                    t = s1 + i * m2
                    if t<m1 and (((t % m2) % m3) % m4) == c:
                        a.append(t)
p = [
    13,
    107,
    87671,
    3870037838243,
    279462107025143615623321823017,
    1325706410421371952032007611396267
] #su dung factordb phan tich thua so nguyen to cua m1
D=[]
m=[]
for i in range(len(a)):
    D.clear()
    m.clear()
    #giai rsa tim cac m[j] 
    for j in range(len(p)):
        D.append(pow(e,-1,p[j]-1))
        m.append(pow(a[i],D[j],p[j]))
    res=crt(m,p) 
    flag=long_to_bytes(res)
    if flag.startswith(b'W1{') and flag.endswith(b'}'):
        print(flag)
        break


```
>Flag: W1{RSA_w1th_0v3rl4pp1ng_m0dulo}
#note:
![image](https://hackmd.io/_uploads/ByF9CKITgg.png)


---

    









    



