网鼎杯2020青龙组crypto

  1. Boom
  2. You raise me up
  3. easy_ya

Boom

  • IDA打开,发现有三个验证,第一个验证md5值相等,解密得到en5oy,第二个解密三元一次方程,得到x=74,y=68,z=31,第三个解一元二次方程,正整数根x=89127561,得到flag

You raise me up

  • sage求离散对数
  • 脚本如下:
1
2
3
4
5
6
7
8
9
10
import binascii
m = 391190709124527428959489662565274039318305952172936859403855079581402770986890308469084735451207885386318986881041563704825943945069343345307381099559075
c = 6665851394203214245856789450723658632520816791621796775909766895233000234023642878786025644953797995373211308485605397024123180085924117610802485972584499
n=2**512

a=Mod(m,n)
b=Mod(c,n)

flag_bin=discrete_log(b,a)
print (binascii.unhexlify(hex(flag_bin)[2:].strip("L")))

easy_ya

  • nc每次连接会改变加密方式,直接爆破
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from hashlib import *
from pwn import *
import string
import itertools
#context.log_level = "debug"
io = remote("39.96.90.217", "17497")
io.recvuntil("= ")
suffix = io.recvline().strip().decode("utf-8")
print(suffix)
io.recvuntil("openssl_")
mode = io.recvuntil(">")[:-1].decode("utf-8")
print(mode)
pts = itertools.product(string.printable, repeat=4)
len = 100**4
cnt = 0
for pt in pts:
if cnt % 1000 == 0:
print("{}%".format(100*cnt/len))
p = "".join(list(pt))
if mode == "sha1":
ct = sha1(p.encode()).hexdigest()
elif mode == "sha224":
ct = sha224(p.encode()).hexdigest()
elif mode == "sha256":
ct = sha256(p.encode()).hexdigest()
elif mode == "sha384":
ct = sha384(p.encode()).hexdigest()
elif mode == "sha512":
ct = sha512(p.encode()).hexdigest()
elif mode == "md5":
ct = md5(p.encode()).hexdigest()
else:
exit(0)
if ct[:20] == suffix:
print(p)
break
cnt += 1
io.interactive()
  • 提交token之后得到rsa中的n1 c1 n2 c2
  • 找到n1和n2的公约数,侧面分解n1,.n2
  • 解得ek是中文:愿我所爱无忧恙岁长安,根据ek生成规则得到key,算出题目的a,b,c,d
  • 题目在加密时,每8个字符作为一组,利用该组生成y和z然后对y和z进行运算,返回结果。注意到返回的结果为hex((y << 52) ^ (pads << 20) ^ z)
  • 所以可以知道
1
2
1.返回结果(视作84位)的前32位是y;
2.返回结果的第33位至第54位为pads的前20位,第55位至第64位为pads的后12位和z的前12位异或的结果。
  • 注意到y和z一共运算了32轮,所以这时pads应该是limit(32*pad),其后5位是0,所以pads的情况相当于:
1
????? ******** ******** ****???? ???00000
  • 其中 * 代表已知,? 代表未知,0就是0。去掉后边5个0后,另外32位就是pad。
  • 这个pad中,未知的地方只有12位,总计4096种情况,每种情况对应唯一的z。
  • 所以可以通过爆破这4096种情况,逆推32轮得到初始的y和z,再观察其转为字符后是否在string.printable中来确定答案。完整代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import gmpy2
from libnum import n2s,s2n
import string

n1 = 523302236767994199900474363344509016779069116440336509402579663927023212822016176967224920257215697515649639915194389392664393435704126520500342935380422629852958893595198501678886910437288107490865842806189885864227955305292596726620737250011643028592306930279653650874633693082819617471411085797465171317473575199984137570425840763157847215554005503026976635376775672263338018024842152016782550728415532850496820668169596712488535626476321971915772540785626943870257914929277013026283202706480202573253694027965561121582254805059775814137542861056288774182091519461752761702279929984980399296157122817271523455097901334302748985253698791419583126820263035649222528798493821648538568572195005358978375666451378629463679501572550304224399031869931606326980885244883575380615433423693907673692911481956161922234589747374211957098461625670478121184734721478951324090304946630772999533103517416951906651316589244984076827527352185687877958699658011472950078992791104307370649334689901210147765149584862868749574640976109508247204313701721196275177445231013673265642224568068643851710967790673640935447579098048865343477978938147696617434878198467680874826616766904653374028721826187308127128623535689512750830887981058826202565202400511
c1 = 498116479126828060721351777093052860074248131123861633687756928866328288114135612849582257727497809922257024131348207980532057240060103798568227977564521497134127080257805342446192248133124844549442334197110567598270256443362563074473166503647429611051333058467042150637666479765740465760837773368463067714839472516227071241189038004851446423799255357523722335018334006275302424683874359612832738469924300750750078529793617519763670882091967677827342326944222743651042579235831828367996040140715066967834876505105847352068608085060284716208922782057542541292881761158407247706056426656079240060590899310402168208571288608455268870805780135942398347873755131825844602660879197979908250552518202142180574849619997871142575611493295891685289794234943270549985371377356916876993228441993132176346052582480841840804748103391892367360829385946406970449784716173650039815882209635063166095389007982620077884907738945623441531598991729082106049943909989119158441101967074276580858829052824691525753913860208906309655761578594225039981683717544420716889594252263165426914121554799496094906541367521362681696570717997925590955291849918357945303214885384216817697786187947817980231717851370305526120464677525392225631245022522492166336294567990
n2 = 536990588699972595171044696252776619032179414787125154102250364726703105272855466989014009336094247702108918440942171080587326115929077717421949560294869471182366684971337895133599697112193778007924450399107079732471847945598232349103839178632745959014098099259478108015237884846605377823461726458684486899249980041743056079896277510838968230729745020510029386228057731944169220820085059789541971092769832034181463596023438597531006332700648910769750936607476390311140301912742677001065893470340950419360642998700303488716826766066363262819042158064398656956185348135880225267894029419814797931720405594656777311094389676998338309809990367862926139317751409984908306801799152005179724137997626023826392780245630698648023945119617679627945415398046106871715475183890738417311925747430222040725394347022734489930069712092197629163647317772330355887387543008085150959104427391942023985298997288368357638062454066636100000548473809891299732343069825793293706407805782587150123342081839983609199059401502925783039760450730519603070519136086703825438807058787688044991172737575437559249668471352046085614345186161595152256193672994722540039920217058451215889862638946510188311582046866299423997659515395934871167522463706085186962242421859
c2 = 164402111514416870480151927449107349163820084533580709383993929301187569338852498622073106678649496858117593538947720740640339668153033620409471744700183709591276280704323985437330452541949262852531710176243561888397374683972759177181684560891529123569371241980602358823138808014488471284855401456011020109937046905434967828616466812821052222924691090808870700970795942705766163862790406417148540210339722273902825469460099520769061522024042123766536620554426683612099219790921573403278241760344418925630823806366949039901279532624187976211611528860461687073096888450694175459321193571925480949635977079339284905452476161156840739751431793628217796061271713787710176980187083301171958573364765677389306720995362317264018186392366551999368657422142163919262968449796794407119199996178284891867472060688293602896147398028717874542567143635071645595076767066361989345197270110842062044509038468406120271061465308775126927579741460684420290619983532930017201223504143911140388202527374930493248620993306321032961537876323380443523093814730204234290659449391857198796743587265894069493376291713198073023178977070834614584650913597763729414655680380751407408769289343905637501434637829997447542901620528323133332447667258731683700542347651
p = gmpy2.gcd(n1, n2)
q1 = n1 // p
q2 = n2 // p
e = 0x10001
phi1 = (p-1)*(q1-1)
d1 = gmpy2.invert(e, phi1)
m = pow(c1, d1, n1)
ek = n2s(m)

key = '8891898088b197a0bfa78199b28195bfae89'.decode('hex')
limit = lambda n: n & 0xffffffff

Key = [ord(i) for i in key]
a = limit((Key[0] << 24) | (Key[1] << 16) | (Key[2] << 8) | Key[3])
b = limit((Key[4] << 24) | (Key[5] << 16) | (Key[6] << 8) | Key[7])
c = limit((Key[8] << 24) | (Key[9] << 16) | (Key[10] << 8) | Key[11])
d = limit((Key[12] << 24) | (Key[13] << 16) | (Key[14] << 8) | Key[15])

outputs = [0x65d4ce3b0b1b3f48bb9fdL, 0xf0230f43414a9c9ac0488L, 0xbd592ebe04025b783fb5bL, 0x28d194dcd1c79b4bb8074L, 0x7c493be8f0fdbb740ec29L]

def reversecalc(a, b, c, d, y, z, pad):
for i in range(32, 0, -1):
# print 'Round %d: %d, %d' % (i, y, z)
pads = limit(pad * i)
paramz = (y*16+c)^(y+pads)^((y>>5)+d)
if(z < paramz):
z = limit(z - paramz + 0x100000000)
else:
z = limit(z - paramz)
paramy = (z*16+a)^(z+pads)^((z>>5)+b)
if(y < paramy):
y = limit(y - paramy + 0x100000000)
else:
y = limit(y - paramy)
# print (y, z)
return y, z

for output in outputs:
print hex(output)
binout = bin(output)[2:]
binout = '0'*(84-len(binout))+binout
y = int(binout[:32], 2)
for i in range(4096):
bini = bin(i)[2:]
bini = '0'*(12-len(bini))+bini
tmpbinpads = bini[0:5] + binout[32:52] + bini[5:12] + '00000'
pad = int(tmpbinpads, 2) / 32
pads = limit(int(tmpbinpads, 2))
z = output ^ (y<<52) ^ (pads<<20)
y0, z0 = reversecalc(a, b, c, d, y, z, pad)
tmpstr = n2s(y0)+n2s(z0)
valid = True
for j in tmpstr:
if (not j in string.printable)and(j != '\x00'):
valid = False
break
if(valid):
print tmpstr
  • 输出结果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
0x65d4ce3b0b1b3f48bb9fdL
S60 '\M(
flag{5fe
0xf0230f43414a9c9ac0488L
86c73a3e
0xbd592ebe04025b783fb5bL
Us
NU\KNP-F
381ee168
0x28d194dcd1c79b4bb8074L
)^C04<b5
Z"N*'U_x000C_=
83c04451
GNM1!Uyl
0x7c493be8f0fdbb740ec29L
9o`YE
1356f}
QG_x000C_rVHZo
7ju-px/_x000C
  • 寻找其中看起来像的拼接得到flag

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1259742453@qq.com

💰

×

Help us with donation