WaniCTF 2023
MIsc
Prompt
题目给了个chatgpt的api,要求从AI这里获得flag。这是最近常见的misc签到题目类型,本题的具体信息如下:
可以得知AI的flag是admin告诉它的,因此直接问它刚刚的对话内容即可获得flag:
shuffle_base64
一道置换映射的题,爆破即可:
import base64
import itertools
from hashlib import sha256
check = '19b0e576b3457edfd86be9087b5880b6d6fac8c40ebd3d1f57ca86130b230222'
def make_shuffle_list(m):
num = []
for i in range(len(m) // 3):
num.append(i)
return list(itertools.permutations(num, len(m) // 3))
def make_str_blocks(m):
tmp = ""
ret = []
for i in range(len(m)):
tmp += m[i]
if i % 3 == 2:
ret.append(tmp)
tmp = ""
return ret
c = 'fWQobGVxRkxUZmZ8NjQsaHUhe3NAQUch'
s = base64.b64decode(c).decode()
print(s)
s_list = make_str_blocks(s)
shuffle_list = make_shuffle_list(s)
for a in shuffle_list:
tmp = s_list.copy()
t = ['*'] * 8
for i in range(len(tmp)):
t[a[i]] = tmp[i]
unpad_t = []
for _ in t:
unpad_t.append(_[:2])
m = ''.join(unpad_t)
if m.startswith('FLAG{'):
if sha256(m[:-1].encode()).hexdigest() == check:
print(m[:-1])
Crypto
密码学就三个题目稍微难点。
pqqp
给定\(\small s=(p^q+q^p)\;mod\;n\),分别模p和模q可得\(\small s=q\;mod\;p,s=p\;mod\;q\),即\(\small s=k_1\cdot p+q,s=k_2\cdot q+p\),由于s的比特位数仅仅比p多一位,不难确定\(s=p+q\),因此利用这个关系分解n即可。
n = 31091873146151684702346697466440613735531637654275447575291598179592628060572504006592135492973043411815280891993199034777719870850799089897168085047048378272819058803065113379019008507510986769455940142811531136852870338791250795366205893855348781371512284111378891370478371411301254489215000780458922500687478483283322613251724695102723186321742517119591901360757969517310504966575430365399690954997486594218980759733095291730584373437650522970915694757258900454543353223174171853107240771137143529755378972874283257666907453865488035224546093536708315002894545985583989999371144395769770808331516837626499129978673
e = 65537
c = 8684906481438508573968896111659984335865272165432265041057101157430256966786557751789191602935468100847192376663008622284826181320172683198164506759845864516469802014329598451852239038384416618987741292207766327548154266633297700915040296215377667970132408099403332011754465837054374292852328207923589678536677872566937644721634580238023851454550310188983635594839900790613037364784226067124711011860626624755116537552485825032787844602819348195953433376940798931002512240466327027245293290482539610349984475078766298749218537656506613924572126356742596543967759702604297374075452829941316449560673537151923549844071
s = 352657755607663100038622776859029499529417617019439696287530095700910959137402713559381875825340037254723667371717152486958935653311880986170756144651263966436545612682410692937049160751729509952242950101025748701560375826993882594934424780117827552101647884709187711590428804826054603956840883672204048820926
from Crypto.Util.number import *
from gmpy2 import *
p_q = iroot(s**2 - 4 * n,2)[0]
p = (s+p_q)//2
q = s-p
assert n == p*q
phi = (p-1)*(q-1)
d= inverse(e,phi)
print(long_to_bytes(pow(c,d,n)))
fusion
通过每4位为一组进行剪枝,详情见exp:
from Crypto.Util.number import *
n = 27827431791848080510562137781647062324705519074578573542080709104213290885384138112622589204213039784586739531100900121818773231746353628701496871262808779177634066307811340728596967443136248066021733132197733950698309054408992256119278475934840426097782450035074949407003770020982281271016621089217842433829236239812065860591373247969334485969558679735740571326071758317172261557282013095697983483074361658192130930535327572516432407351968014347094777815311598324897654188279810868213771660240365442631965923595072542164009330360016248531635617943805455233362064406931834698027641363345541747316319322362708173430359
e = 65537
c = 887926220667968890879323993322751057453505329282464121192166661668652988472392200833617263356802400786530829198630338132461040854817240045862231163192066406864853778440878582265466417227185832620254137042793856626244988925048088111119004607890025763414508753895225492623193311559922084796417413460281461365304057774060057555727153509262542834065135887011058656162069317322056106544821682305831737729496650051318517028889255487115139500943568231274002663378391765162497239270806776752479703679390618212766047550742574483461059727193901578391568568448774297557525118817107928003001667639915132073895805521242644001132
r = 163104269992791295067767008325597264071947458742400688173529362951284000168497975807685789656545622164680196654779928766806798485048740155505566331845589263626813345997348999250857394231703013905659296268991584448212774337704919390397516784976219511463415022562211148136000912563325229529692182027300627232945
mask = int("55" * 128, 16)
print(bin(mask)[2:])
print(bin(mask << 1)[2:])
nbits = format(n, "02048b")
rbits = format(r, "01024b")
PBITS = ["x"]*1024
QBITS = ["x"]*1024
for i in range(0, 1024):
if i%2 == 0: PBITS[1023-i] = rbits[1023-i]
else:QBITS[1023-i] = rbits[1023-i]
_pbits = ""
_qbits = ""
def run(offset):
global _pbits, _qbits
for bits in [list(format(x, "04b")) for x in list(range(2**4))]:
p1,p3,q0,q2 = bits
pb = p3+PBITS[1023-offset-2]+p1+PBITS[1023-offset-0] + _pbits
qb = QBITS[1023-offset-3]+q2+QBITS[1023-offset-1]+q0 + _qbits
_n = int(pb, 2)*int(qb, 2)
if format(_n, "02048b")[-(offset+4):] == nbits[-(offset+4):]:
_pbits = pb
_qbits = qb
return
raise Exception("Not found")
offset = 0
while offset < 1024:
run(offset)
offset += 4
p = int(_pbits, 2)
q = n//p
assert p*q == n
d = inverse(e, (p-1)*(q-1))
print(long_to_bytes(pow(c,d,n)).decode())
DSA?
本题的签名算法为DSA,主要漏洞在于\(\small k^{-1}\)的比特太小,已知\(\small s=k^{-1}(h+xr)\;mod\;q=m(h+xr)\;mod\;q=mh+mxr+aq\),这里m是flag,为29字节,利用该关系造格子即可,注意:1.需要调大最后一列的系数,使其优先规约 2.需要调整对角线上的元素系数使得LLL得到的最短向量每一维元素的大小大致为\(\small 2^{384}\cdot m\)。详情见exp:
q = 139595134938137125662213161156181357366667733392586047467709957620975239424132898952897224429799258317678109670496340581564934129688935033567814222358970953132902736791312678038626149091324686081666262178316573026988062772862825383991902447196467669508878604109723523126621328465807542441829202048500549865003
h = 0x7aad5b407493e83e9c8a11170733019dfb55dcdb0b7ec677ded13ad9ab16cc82
r = 61401707010758101526146375076142785590307812475121812316952376486069149360425245868500855973757366554075933599220935059105890347272857469593141580674416812501978293803766670329096383435341545996560650936693344739955943829806575705777357363320849419106573553984283202966428145927420324135463723534658578592614
s = 111517010926059770368621794619904523635402276018797799050063356381741027477406088876713980060476757084941067618714931799291527322872915994467900428221446499284372216091094469753894965723718559615488738094837413786466795341422409453410629346868694542622233657373439752122126458542360612892187894362397949528433
M = Matrix([
[2^384, 0, 0, h*2^1000], # m
[0, 1, 0, r*2^1000], # x*m
[0, 0, 2^(29*8+384), s*2^1000], # 1
[0, 0, 0, q*2^1000], # a
])
k = M.LLL()[0][0]
k = abs(k)
from Crypto.Util.number import *
print(long_to_bytes(k >> 384).decode())