以下内容是2024第八届"御网杯"信息安全大赛线上赛——Crypto题目的答案与解题思路
1、Crypto一
解答:
一眼base100,直接喵喵小公举(ToolsFx)梭了
1 base100-->2 base64-->3 base85(ASCII85)-->4 base91chgdchg5clctclcxclc5cdc9chcdcdc9chctchglcdc9chclclcdclcpchchchgdchg5clg5chg9clcpchclcdcdchg9chg5chctclc9chghclchchclclcpclchchghchg5clcpcdclchcpchclcdc9clcdcdc9chglchg5chg5chctcdc9clchclcdchclchgdchcpcdclchclcdc9chghclcdchg5chctclcpchctclclchgpclclchgdclcBchgdchcpchgdclclcdc9chglchcdclg5chglchg5clctchctclctclchchgdchglchg9clcpcdchchcpclclclcpcdc9chg9chcxchclcdghcdghcdghcdghcdghcdgh
结合附件名字是base这肯定又是某种不熟悉的base编码。。看编码格式数字部分最大是9还有字母组成,想到base62。只能说难度都在找工具的时间上了(https://www.wqtool.com/basecode)
4C4A575851324332474E32455356444C4A5A4B5645334B4A47524D544556544D4A563546453253324E4A4A47325453454C463545324D534A475647554F554C594C464C55324E435A4E4A574757544C4E4B5634465556324B48453D3D3D3D3D3D
然后赛博厨子就出来了
flag{HNCTFb8cee34cf4f4633b90d1ac8b9d2e1eb}
2、Crypto二
源码如下:
#!/usr/bin/env python3.9# -*- coding: utf-8 -*-import gmpy2from Crypto.Util.number import getPrime, isPrime, bytes_to_longfrom secret import FLAG, E1, E2, P, Q1, Q2
def next_prime(num: int) -> int: num = num + 2 if num % 2 else num + 1 while not isPrime(num): num += 2 return num
p = getPrime(1024)q = next_prime(getPrime(16) * p + 38219)n = p * qc = pow(E1, 65537, n)print(f'n = {n}')print(f'c = {c}')# n = 1605247600724752598798254639224215706171506359654961357324428027985787942008103766562745464838961569081446916113769517713344420113584254259000172572811154232107339480903672251992191997458469905064423618888336088652352540882576826988355783159237971043770132628344798937353150930071309347972804118952814447576207066147031238749098842662046825743988208813903138796789940911515825517078554074496474819128789835309636804325132602557092847746454786387067599510769382078521691609970320528531270474091713477040343897269903489441410062592732302402854035415438078656688806905350495825334584533345448091335565792091890185673190424063# c = 751639057610677013264061431434189083017589908118307247217007533938435229431015858783222167911772848893015518607229280589985711010766459396989232072512314594917029375221335361209036112742388866873824163350886610514973038316512032459352053158417705406031466332440378871927174731975794579894912999936641163063898365134788537389162378185448090279397717831977803284480743612393591614284972981435749362255654561121758163485884075260156288337176713756471879489767416836868661153693157792733142765671887792303181376620864506386820826866340907593080654521498766421056474652652337037121881207188033108746890998208582406826010121861
assert E2.bit_length() == 69ns = [getPrime(1024) * getPrime(1024) for _ in range(3)]cs = [pow(E2, 89, n) for n in ns]print(f'ns = {ns}')print(f'cs = {cs}')# ns = [15863230586500684911356384742123404120213699052018048588650392009927565369685497256344682150189923131009586323640507773706997704860898682946308031020361302334248895233255911348365179153799197341744863134926804603973507415697810440916305092395180382239729550833607847524005391137474497849077097574452115379368463540087172800902210822143687014813631366360652583216269138116785489485772437870528892032119729929607857459621078790511144060710035933887337208301078892163837203412081114510143406013892393607932596921308889058909544584619676380766485493114814753878272881866907210235681877689493671668534251778397658670518117, 14144098469438619358682652828507744381697293556670717685553585719665002440476256008471235313826051740009083510860714991201047915737216102220242621674841600987122005914542061963618272275986835928673920375768272390912778741502655909281390948606467847118377641357547931472588836726339758576038273820470879637555458446243401248151675266602656677360819563744765522495640821496694918515669243614141704744848980746101569785439728585144841655665959389460512628800782742764147773150430552859331269667626942993392101897661719871375721143240270211821269260950380944670195863016621594387236339317938305273510719419578308449465183, 27563822879593503938377821960427219022565215631856333510782568496016547757945464794632272818101891677705256471714805217606503652132995136255720639088424576003650628211271025648183600635145895528466199068640094470078526413324708028578289949241288828542143203769199399500669311878391255837977932634772778594526940501234736059441483897017015324765266787399950699732518347518591167932031031320265136158304460199654008895095274754918153773566824931440342525688741289235153882699461549523425169846266597156773535163599640189457171272058311480951820887261040891344076039474315985825984444520336790670313179493074014037981261]# cs = [3833095607830862948079097323254872789586576953317671099752083261949616608759231291050566542764984974722790226120399722937104503590740358249900089784508490830379531632752169777949200718567033018577184658177019404903817920024468923715441355404672443007723525750768430895425376124679225715687382380114628103058312176343693900115638265002657622618744666247132114654135429040069316368839938881716554901593031901272992940200484460436193699175500376368456706998564064693820008778900344357745691652875500810447147088715289581351501876012044611990972521570253106671158207677490849249612002954497927762168699886110455354481924, 1502420121177211156091634258259634977709023894278792755694473756163084431123774101512866316989917922052023168401167212284219907272528117024670443698990238243030221117004372456475521502350404137469088570170885409265567084376069256924135270283335242133163303599239181417949980292944203204296598188175632723968779672994090788585343302473442389865459398142634104331743517384589200789331489394375604801951994831647339839112698394141328178967516636452592385248135340133712522135715943787590172334743893259621909532456281362868290556461907936774231166936915669816509378419892149164552548131776979706381641477878931403040942, 8992204063713908492214256291861339175525948946919629972908439132005643626148678347198381531633907182877152728077958345519083406637446972079387161726967295886447791613166577391233866583354793842121902234644830640050181130381996083089350911224037154798259291124104894554037604500881250119806371348673833105103600782286898276354573884788251542211434143476774391457587885772379990104835187104619922442613860682792470389490804228050671124495925536024571104944112397143299499508504917890140939438891891453283594000764399193028606955089853654071198909973555844004685149713774167524224100487937899126480545681565581673958854]
qq = getPrime(1024)nn = P * qqqqq = qq >> 460 << 460print(f'nn = {nn}')print(f'qqq = {qqq}')# nn = 16851735797771199659625936797279158526379741298692339786049494329385618191510929735113284926125682522862667382938603116481087115598324232020838136618518964343752653000145611092980612556947954728339508416646035295651852840099205127587606898235203114875942637900167644300657599966420459187131027117268004042708998239798434578246497419547543598779697909298102358128788120332794123690714647499091326245022977970510468925837363300545900657420134894815246189043375619879915523611890538142257042753868665844692029124229028056547096764320547579965641276151760507921199827910445919017775913411823263307923216323527883262438117# qqq = 121042531930820997492656296084544616958724191434895945419858099204426898711413526806300854553993738803031497438495403291406481997877273916883918253302909196533823945327277312672931819555344139777992801106437643790498379469530787985051569590331291422592393540391481519004782904598710037907420679190942964514816
assert len(FLAG) == 42n1 = P * Q1n2 = P * Q2c1 = pow(bytes_to_long(FLAG), E1, n1)c2 = pow(bytes_to_long(FLAG), E2, n2)print(f'n1 = {n1}')print(f'n2 = {n2}')print(f'c1 = {c1}')print(f'c2 = {c2}')# n1 = 21655617838358037895534605162358784326495251462447218485102155997156394132443891540203860915433559917314267455046844360743623050975083617915806922096697304603878134295964650430393375225792781804726292460923708890722827436552209016368047420993613497196059326374616217655625810171080545267058266278112647715784756433895809757917070401895613168910166812566545593405362953487807840539425383123369842741821260523005208479361484891762714749721683834754601596796707669718084343845276793153649005628590896279281956588607062999398889314240295073524688108299345609307659091936270255367762936542565961639163236594456862919813549# n2 = 24623016338698579967431781680200075706241014384066250660360949684385831604822817314457973559632215801205780786144608311361063622813017396858888436529116737754653067203843306015767091585697803364656624926853551997229897087731298797904208292585562517602132663331748784390752958757661484560335406769204491939879324079089140420467301773366050084810282369044622442784113688062220370531522036512803461607049619641336524486507388232280683726065679295742456158606213294533956580462863488082028563360006966912264908424680686577344549034033470952036766850596897062924137344079889301948258438680545785139118107899367307031396309# c1 = 2615722342860373905833491925692465899705229373785773622118746270300793647098821993550686581418882518204094299812033719020077509270290007615866572202192731169538843513634106977827187688709725198643481375562114294032637211892276591506759075653224150064709644522873824736707734614347484224826380423111005274801291329132431269949575630918992520949095837680436317128676927389692790957195674310219740918585437793016218702207192925330821165126647260859644876583452851011163136097317885847756944279214149072452930036614703451352331567857453770020626414948005358547089607480508274005888648569717750523094342973767148059329557# c2 = 6769301750070285366235237940904276375318319174100507184855293529277737253672792851212185236735819718282816927603167670154115730023644681563602020732801002035524276894497009910595468459369997765552682404281557968383413458466181053253824257764740656801662020120125474240770889092605770532420770257017137747744565202144183642972714927894809373657977142884508230107940618969817885214454558667008383628769508472963039551067432579488899853537410634175220583489733111861415444811663313479382343954977022383996370428051605169520337142916079300674356082855978456798812661535740008277913769809112114364617214398154457094899399
解答
1、求解E1:
由q = next_prime(getPrime(16) p + 38219)可知,q为pgetPrime(16)+38219的下一个素数,由getPrime(16)比较小,我们可以在其取值范围遍历出符合题目的值,从而解出q。
from Crypto.Util.number import *import gmpy2from gmpy2 import next_prime,iroot
n = 1605247600724752598798254639224215706171506359654961357324428027985787942008103766562745464838961569081446916113769517713344420113584254259000172572811154232107339480903672251992191997458469905064423618888336088652352540882576826988355783159237971043770132628344798937353150930071309347972804118952814447576207066147031238749098842662046825743988208813903138796789940911515825517078554074496474819128789835309636804325132602557092847746454786387067599510769382078521691609970320528531270474091713477040343897269903489441410062592732302402854035415438078656688806905350495825334584533345448091335565792091890185673190424063c = 751639057610677013264061431434189083017589908118307247217007533938435229431015858783222167911772848893015518607229280589985711010766459396989232072512314594917029375221335361209036112742388866873824163350886610514973038316512032459352053158417705406031466332440378871927174731975794579894912999936641163063898365134788537389162378185448090279397717831977803284480743612393591614284972981435749362255654561121758163485884075260156288337176713756471879489767416836868661153693157792733142765671887792303181376620864506386820826866340907593080654521498766421056474652652337037121881207188033108746890998208582406826010121861
for i in range(2 ** 15, 2 ** 16): if isPrime(i): q = next_prime(i * gmpy2.iroot(n // i, 2)[0] + 38219) if n % q == 0: print(q) break
p = n // qphi = (p - 1) * (q - 1)d = gmpy2.invert(65537, phi)E1 = pow(c, d, n)print(E1)# 377312346502536339265
2、求解E2:中国剩余定理
from functools import reduce
3、求解E3:
第三部分代码我们可以看出来是利用p高位去求P的,但有趣的是发现最后代码出现n1 = P Q1和n2 = P Q2,因此n1和n2有共同的因子P,所以可以直接求他们的最大公约数得到P,即P=gmpy2.gcd(n1,n2),然后分别可以求出Q1=n1//P和Q2=n2//P。
值得注意的是:
print(gmpy2.gcd(E1, phi_1))
E和phi不互素,而且最后解出来m^35开方也不行。这里我们需要利用同余性质了:把m幂次的复杂度降低。
我们知道:a ≡ b mod mn可变换成:a ≡ b mod m 和 a ≡ b mod n因此有:c1 ≡ m^e1 mod Pc1 ≡ m^e1 mod Q1 c2 ≡ m^e2 mod P c2 ≡ m^e2 mod Q2 再根据相乘性质可得:c3 = c1∗c2 ≡ m^e1 ∗ m^e2 mod P接下来就可以利用中国剩余定理将这一组同余式求得一个特解,即c1 ≡ m^e1 mod Q1c2 ≡ m^e2 mod Q2c3 ≡ m^e1 ∗ m^e2 mod P然后构造新的RSA即可:from Crypto.Util.number import *import gmpy2from libnum import *
n1 = 21655617838358037895534605162358784326495251462447218485102155997156394132443891540203860915433559917314267455046844360743623050975083617915806922096697304603878134295964650430393375225792781804726292460923708890722827436552209016368047420993613497196059326374616217655625810171080545267058266278112647715784756433895809757917070401895613168910166812566545593405362953487807840539425383123369842741821260523005208479361484891762714749721683834754601596796707669718084343845276793153649005628590896279281956588607062999398889314240295073524688108299345609307659091936270255367762936542565961639163236594456862919813549n2 = 24623016338698579967431781680200075706241014384066250660360949684385831604822817314457973559632215801205780786144608311361063622813017396858888436529116737754653067203843306015767091585697803364656624926853551997229897087731298797904208292585562517602132663331748784390752958757661484560335406769204491939879324079089140420467301773366050084810282369044622442784113688062220370531522036512803461607049619641336524486507388232280683726065679295742456158606213294533956580462863488082028563360006966912264908424680686577344549034033470952036766850596897062924137344079889301948258438680545785139118107899367307031396309c1 = 2615722342860373905833491925692465899705229373785773622118746270300793647098821993550686581418882518204094299812033719020077509270290007615866572202192731169538843513634106977827187688709725198643481375562114294032637211892276591506759075653224150064709644522873824736707734614347484224826380423111005274801291329132431269949575630918992520949095837680436317128676927389692790957195674310219740918585437793016218702207192925330821165126647260859644876583452851011163136097317885847756944279214149072452930036614703451352331567857453770020626414948005358547089607480508274005888648569717750523094342973767148059329557c2 = 6769301750070285366235237940904276375318319174100507184855293529277737253672792851212185236735819718282816927603167670154115730023644681563602020732801002035524276894497009910595468459369997765552682404281557968383413458466181053253824257764740656801662020120125474240770889092605770532420770257017137747744565202144183642972714927894809373657977142884508230107940618969817885214454558667008383628769508472963039551067432579488899853537410634175220583489733111861415444811663313479382343954977022383996370428051605169520337142916079300674356082855978456798812661535740008277913769809112114364617214398154457094899399E1 = 377312346502536339265E2 = 561236991551738188085
P = gmpy2.gcd(n1, n2)Q1 = n1 // PQ2 = n2 // P
c = [pow(c1, gmpy2.invert(E1 // 35, (P - 1) * (Q1 - 1)), n1), pow(c2, gmpy2.invert(E2 // 35, (P - 1) * (Q2 - 1)), n2)]c3 = c[0] * c[1] % Pc2 = c[1] % Q2c1 = c[0] % Q1
result = solve_crt([c1,c2,c3],[Q1,Q2,P])phi = (Q1-1)*(Q2-1)n = Q1*Q2c_m = result % ne = 35# print(gmpy2.gcd(e, phi))# 5d = gmpy2.invert(7,phi)m = pow(c_m,d,n)print(long_to_bytes(gmpy2.iroot(m, 5)[0]))# flag{27dab675-9e9b-4c1f-99ab-dd9fe49c190a}
3、不小心
题目源码如下:
# coding:utf-8
# python 3.6
from flag import flag
import re
s = "fst3Sem8Wgnobcd9+++++uv2JKpUViFGHz0QRMyjkA7NaBC14wXYxh5OP/DEqrZIl6LT"
assert re.match(r'^DASCTF\{[a-f0-9]+\}$',flag) != None
def encode(inputs):
bin_str = []
for i in inputs:
x = str(bin(ord(i))).replace('0b', '')
bin_str.append('{:0>8}'.format(x))
outputs = ""
nums = 0
while bin_str:
temp_list = bin_str[:3]
if (len(temp_list) != 3):
nums = 3 - len(temp_list)
while len(temp_list) < 3:
temp_list += ['0' * 8]
temp_str = "".join(temp_list)
temp_str_list = []
for i in range(0, 4):
temp_str_list.append(int(temp_str[i * 6:(i + 1) * 6], 2))
if nums:
temp_str_list = temp_str_list[0:4 - nums]
for i in temp_str_list:
outputs += s[i]
bin_str = bin_str[3:]
outputs += nums * '='
return outputs
c = encode(flag)
print(c)
# +Se++h+mF5u0d++Oc++RbQJYbyuMb++0cYuQc+SwdmK0d+fwcYRYG+==
原题目脚本注释
这里我们来分析一下 题目脚本(我直接在脚本中给出注释)
# 编码设置和导入必要的库
# coding:utf-8 # 指定文件编码为utf-8
# python 3.6 # 注释说明该脚本应在Python 3.6环境下运行,但实际上这行对Python解释器没有实际作用
from flag import flag # 从flag模块中导入flag变量,假设flag模块中定义了flag变量,存储了CTF比赛的flag
import re # 导入正则表达式库
# 给定的字符串,用于编码过程中的映射
s = "fst3Sem8Wgnobcd9+++++uv2JKpUViFGHz0QRMyjkA7NaBC14wXYxh5OP/DEqrZIl6LT"
# 使用正则表达式断言flag的格式,确保flag以DASCTF{开头,后跟一串十六进制数字,以}结尾
assert re.match(r'^DASCTF\{[a-f0-9]+\}$', flag) != None
def encode(inputs):
"""
将输入的字符串(假设为flag)进行编码。
编码过程:
1. 将每个字符转换为二进制字符串,并填充至8位。
2. 每3个二进制字符串(共24位)合并,然后每6位一组转换为十进制数。
3. 使用s字符串中对应位置的字符替换这些十进制数。
4. 如果最后不足3个二进制字符串,则补零至3个,并相应地减少输出的字符数(用'='表示)。
"""
bin_str = [] # 存储每个字符的二进制表示(填充至8位)
for i in inputs:
x = str(bin(ord(i))).replace('0b', '') # 将字符转换为二进制字符串,并去除前缀'0b'
bin_str.append('{:0>8}'.format(x)) # 填充至8位
outputs = "" # 存储编码后的字符串
nums = 0 # 记录需要补零的二进制字符串数量
while bin_str:
temp_list = bin_str[:3] # 每次取3个二进制字符串
if len(temp_list) != 3: # 如果不足3个,则记录需要补零的数量
nums = 3 - len(temp_list)
# 注意:这里的补零逻辑实际上在后续处理中被忽略了,因为temp_list直接用于处理
# 理论上应该在这里补零,但代码中没有实现,可能是个遗漏
temp_str = "".join(temp_list) # 合并3个二进制字符串
temp_str_list = [] # 存储每6位二进制转换成的十进制数
for i in range(0, 4): # 每6位一组进行转换(因为24位/6位=4组)
temp_str_list.append(int(temp_str[i * 6:(i + 1) * 6], 2)) # 转换为十进制
if nums: # 如果需要补零,则减少输出的字符数
temp_str_list = temp_str_list[0:4 - nums]
for i in temp_str_list: # 使用s字符串中的字符替换这些十进制数
outputs += s[i]
bin_str = bin_str[3:] # 处理下一个3个二进制字符串
outputs += nums * '=' # 使用'='表示补零的数量(但这里的实现可能不完全准确,因为补零逻辑未完全实现)
return outputs
# 对flag进行编码并打印结果
c = encode(flag)
print(c) # 输出编码后的字符串
# +Se++h+mF5u0d++Oc++RbQJYbyuMb++0cYuQc+SwdmK0d+fwcYRYG+==
“+”有多个,就需要爆破一下
其实这里一个小漏洞
我们看他自己给的脚本中有DASCTF的字样 这足以证明这道题是之前的原题(这里说明主办方有点懒呀 无意冒犯 哈哈哈) (是2022河北银行CTF的原题 )
完整脚本如下:
# coding:utf-8
# Python 3.6
# 自定义编码函数,将输入字符串转换为基于特定字符串 s 的编码
def encode(inputs):
bin_str = []
for i in inputs:
# 将字符转换为二进制字符串,并去掉前缀 '0b',然后填充至8位
x = '{:08b}'.format(ord(i))
bin_str.append(x)
outputs = ""
nums = 0
while bin_str:
# 每组处理3个二进制字符串(不足时用'0'填充至8位后的全0字符串代替)
temp_list = bin_str[:3]
if len(temp_list) != 3:
nums = 3 - len(temp_list)
while len(temp_list) < 3:
temp_list.append('0' * 8) # 直接添加8个0的字符串,而不是列表
temp_str = "".join(temp_list)
# 从每24位二进制中提取4个6位的部分,转换为十进制索引
temp_str_list = [int(temp_str[i * 6:(i + 1) * 6], 2) for i in range(4)]
if nums:
temp_str_list = temp_str_list[:4 - nums] # 如果不足3个二进制字符串,则截取前面的部分
# 使用索引从字符串 s 中选择字符,并构建输出
for i in temp_str_list:
outputs += "fst3Sem8Wgnobcd9+++++uv2JKpUViFGHz0QRMyjkA7NaBC14wXYxh5OP/DEqrZIl6LT"[i]
bin_str = bin_str[3:]
# 如果不是3的倍数,则添加 '=' 填充
outputs += '=' * nums
return outputs
# 模拟解码 Base64 的过程(实际上并未直接使用 Base64 解码,而是利用了自定义的 s 字符串)
s = "fst3Sem8Wgnobcd9+++++uv2JKpUViFGHz0QRMyjkA7NaBC14wXYxh5OP/DEqrZIl6LT"
h = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
c = '+Se++h+mF5u0d++Oc++RbQJYbyuMb++0cYuQc+SwdmK0d+fwcYRYG+'
m = ''
for i in c:
# 通过查找 c 中每个字符在 s 中的索引,用该索引从 Base64 字符集 h 中选择字符
m += h[s.index(i)]
print("模拟解码结果:", m)
# 递归函数,用于解密特定的 Base64 字符串
from base64 import b64decode
import string
ss = b'0123456789abcdef-_{}'
def aaa(idx, mm):
if idx >= 4:
try:
# 尝试 Base64 解码
t = b64decode(mm)
except:
return
# 检查解码后的每个字节是否在允许的字符集 ss 中
if all(v in ss for v in t):
print("解码成功:", t.decode()) # 解码后可能需要转为字符串输出
return
if mm[idx] == 'Q':
# 替换 'Q' 为 'QRSTU' 中的一个字符,并递归处理
for v in "QRSTU":
aaa(idx + 1, mm[:idx] + v + mm[idx + 1:])
else:
# 继续递归处理下一个字符
aaa(idx + 1, mm)
# 解密过程
m = 'QEFQQ1QGezc4YWQhMQEzZQcwOWZkZjEyYQVhYQQhYQVkZDYyZQMzfQ=='
m = m[8:] # 去掉前缀 'QEFQQ1Q',可能是为了减少搜索空间或符合特定条件
# 分块处理 Base64 字符串
for v in range(0, len(m), 4):
print('---------', v, m[v:v + 4])
aaa(0, m[v:v + 4])
# 预期输出: DASCTF{78ada113e709fdf12a5aa4aa5dd62e33}
# 注意:这个输出是预期值,实际输出取决于 m 的内容和递归函数的实现
得到FLAG:
DASCTF{78ada113e709fdf12a5aa4aa5dd62e33}
4、Justmath
题目一个函数图像 一个脚本
图片如下:
题目的脚本如下:
# 导入必要的库
from gmpy2 import * # 导入GMPY2库,用于高精度算术
from Crypto.Util.number import * # 导入Crypto库的实用程序,用于数字加密和数学函数
from secret import FLAG,x,y # 假设这是一个包含FLAG(待解密的消息)、x和y(可能是某个函数的变量和表达式)的模块
import sympy # 导入SymPy库,用于符号数学
import pylab # 导入pylab,通常用于绘图,但在这个上下文中可能不太必要
# 定义calc函数,可能用于演示或测试符号求导和绘图
def calc():
y1 = sympy.diff(y,x) # 对y关于x求一阶导数
y2 = sympy.diff(y1,x) # 对y1(即y的一阶导数)关于x求二阶导数
v1,v2,v3 = [],[],[] # 初始化三个列表,用于存储计算结果
for i in FLAG: # 遍历FLAG中的每个字符(这里假设FLAG被转换为数字列表)
v1.append(y.subs('x',i)) # 将y中的x替换为FLAG中的当前数字,并将结果添加到v1
print('v1 =',v1[:34]) # 打印v1的前34个元素
for i in v1:
v2.append(y1.subs('x',i)) # 将y1中的x替换为v1中的当前值,并将结果添加到v2
print('v2 =',v2[:2]) # 打印v2的前两个元素
for i in v2:
v3.append(y2.subs('x',i)) # 将y2中的x替换为v2中的当前值,并将结果添加到v3
print('v3 =',v3[:2]) # 打印v3的前两个元素
pylab.plot(v2,v3) # 使用pylab绘制v2和v3的图形
pylab.show() # 显示图形
# 定义rsam函数,生成RSA密钥对并加密FLAG
def rsam():
m = bytes_to_long(FLAG) # 将FLAG(假设为字节串)转换为长整型数字
while True:
try:
p = getPrime(768) # 生成一个768位的质数p
q = getPrime(768) # 生成另一个768位的质数q
n = p*q # 计算n = p*q,用于RSA模
e = 3 # 使用小整数e=3作为公钥的一部分(在实际应用中,e应选择与phi(n)互质的大整数)
phi = (p-1)*(q-1) # 计算欧拉函数phi(n)
d = invert(e,phi) # 计算e关于phi的模逆d,用于私钥
c = pow(m,e,n) # 使用公钥(e,n)加密m
print('n =',n) # 打印公钥和密文的一部分
print('e =',e)
print('c =',c)
break # 跳出循环
except:
pass # 如果生成质数或计算过程中发生错误,则忽略并继续尝试
# 定义main函数,按顺序调用rsam和calc
def main():
rsam() # 调用rsam函数以生成RSA密钥对并加密FLAG
calc() # 调用calc函数以进行符号求导和绘图(与RSA加密无关)
if __name__ == '__main__':
main() # 如果此脚本作为主程序运行,则调用main函数
# 给出的RSA参数和计算结果
# ...(这里列出了n, e, c, v1, v2, v3的值,这些值用于验证或进一步分析)
n = 2260375559104345425590426977960386256287009777233277062625487017885931446911942921201492850167115455071935831283269948569220356763988762825230315520633702443866690239945242948370781975714325308306543337600783340792458991506685843729962897796956171467876531084194426101796617903015810156717396227079274786269217370618477266867389155551378798713259843750289765858717627925689021561352438080039804957145513478767641674644346609224034274906228784593435462413278410143
e = 3
c = 1683427726786225271109289808778075351906457081282891335272956455076290407290946927840180672315908981114229434899424882579823897506730018911375238394076293908946844135295984336122170362703361647325169444373502665686779049846717305377396296752361918921007897449738856962248716579014267597667341690453460130215215256776249910808564677407383996700090361822122676428069577517468851642648993930679875398568383201032360229083338487146673018350740571719960730053254352184
v1 = [3149069, 2271689, 2337632, 3068562, 67697, 2337632, 3068562, 67697, 2143547, 2543093, 1844472, 2206998, 67697, 1844472, 2686547, 2020317, 67697, 3149069, 2271689, 2081324, 67697, 2143547, 2543093, 1844472, 2206998, 67697, 2337632, 3068562, 67697, 2143547, 2543093, 1844472, 2206998, 3752378]
v2 = [59499825996845, 30963434563085]
v3 = [713997911962144, 371561214757024]
编写脚本
第一部分:使用SageMath解方程恢复部分flag
# 引入SageMath的solve函数用于解方程
from sage.symbolic.relation import solve
# 定义变量x
x = var('x')
# y_value列表包含了通过某种方式(可能是符号函数在特定x值下的结果)得到的值
y_value = [3149069, 2271689, 2337632, 3068562, 67697, 2337632, 3068562, 67697, 2143547, 2543093, 1844472, 2206998, 67697, 1844472, 2686547, 2020317, 67697, 3149069, 2271689, 2081324, 67697, 2143547, 2543093, 1844472, 2206998, 67697, 2337632, 3068562, 67697, 2143547, 2543093, 1844472, 2206998, 3752378] # 省略了中间的值以节省空间
# 初始化flag字符串
flag = ""
# 遍历y_value列表中的每个值
for i in y_value:
# 构造一个三次方程,使其等于y_value中的当前值
equation = 2 * x ^ 3 + 2 * x ^ 2 + 3 * x + 17 == i
# 解这个方程
solutions = solve(equation, x)
# 假设方程有三个解,取第三个解(注意:这里假设了解的顺序和存在性)
# 并将该解转换为字符后添加到flag字符串中
flag += chr(solutions[2].rhs())
# 打印恢复的flag部分
print(flag)
第二部分:使用RSA和Coppersmith的小根数攻击恢复剩余的flag
# 引入Crypto.Util.number中的函数
from Crypto.Util.number import *
# 已知flag的一部分(前缀)
flag = b"this is flag and the flag is flag{"
# RSA的公钥参数:模n和指数e
n = 2260375559104345425590426977960386256287009777233277062625487017885931446911942921201492850167115455071935831283269948569220356763988762825230315520633702443866690239945242948370781975714325308306543337600783340792458991506685843729962897796956171467876531084194426101796617903015810156717396227079274786269217370618477266867389155551378798713259843750289765858717627925689021561352438080039804957145513478767641674644346609224034274906228784593435462413278410143 # 省略了具体的大数值以节省空间
e = 3
c = 1683427726786225271109289808778075351906457081282891335272956455076290407290946927840180672315908981114229434899424882579823897506730018911375238394076293908946844135295984336122170362703361647325169444373502665686779049846717305377396296752361918921007897449738856962248716579014267597667341690453460130215215256776249910808564677407383996700090361822122676428069577517468851642648993930679875398568383201032360229083338487146673018350740571719960730053254352184 # 省略了具体的密文大数值以节省空间
# 定义模n的多项式环
R. < x > = PolynomialRing(Zmod(n))
# 尝试使用Coppersmith的小根数攻击来找到m(原始消息)
# 由于我们知道flag的一部分,我们可以尝试通过不断添加'\x00'(即0字节)来扩展这个前缀
# 然后我们尝试找到满足(m + x)^e - c = 0的小x值
for i in range(40): # 尝试不同的扩展长度
mhigh = bytes_to_long(flag + b"\x00" * 32 + b"}") # 构造一个可能的高位m值
f = (mhigh + x) ^ e - c # 构造多项式
# 使用small_roots方法尝试找到多项式的小根
# 参数X指定了搜索的界限,beta和epsilon影响搜索的精度和性能
res = f.small_roots(X=256 ^ i, beta=0.4, epsilon=0.05)
if res != []: # 如果找到了根
# 将找到的小根值加到mhigh上,得到可能的m值
m = mhigh + int(res[0])
# 将m值转换回字节串并打印
print(long_to_bytes(m))
得到flag:
flag{0f5a1806d07f030767e113352727ea2d}