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}