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