SHCTF-Crypto

CRYPTO

[WEEK1]立正

wl hgrfhg 4gNUx4NgQgEUb4NC64NHxZLg636V6CDBiDNUHw8HkapH :jdoi vl vlkw ~xrb wd nrrT Y:
提示:注意要

因为是要正,所以猜测可能是反转或是镜像。反转字符串获得:
:Y Trrn dw brx~ wklv lv iodj: HpakH8wHUNDiBDC6V636gLZxHN46CN4bUEgQgN4xUNg4 ghfrgh lw
看起来像是一段话,所以试试凯撒前进3,获得字符串:
:V Qook at you~ this is flag: EmxhE8tERKAfYAZ6S636dIWuEK46ZK4yRBdNdK4uRKd4 decode it

EmxhE8tERKAfYAZ6S636dIWuEK46ZK4yRBdNdK4uRKd4这段字符串怎么看都像base64,但扔cyberchef里又解不出来可见字符,并且学这么久英语也没见过Qook at you这个短语,猜测可能是大小写有不同的凯撒规则。

大写字母单独凯撒前进8后得到:Q Look at you~ this is flag: ZmxhZ8tZMFVfTVU6N636dDRuZF46UF4yMWdIdF4uMFd4 decode it,至少Look at you看得懂了,不过base64解ZmxhZ8tZMFVfTVU6N636dDRuZF46UF4yMWdIdF4uMFd4还是没出来字符串,但前四个字符flag已经出来了,说明方向没问题。image.png

image.png
先用base64编码一下flag{看看哪里有问题,发现数字是3,并且大括号后面无论是什么数字都不会变,猜测数字也需要凯撒,所以数字凯撒前进5。

ZmxhZ3tZMFVfTVU1N181dDRuZF91UF9yMWdIdF9uMFd9
得到最后flag
flag{Y0U_MU57_5t4nd_uP_r1gHt_n0W}

[WEEK1]Crypto_Checkin

QZZ|KQbjRRS8QZRQdCYwR4_DoQ7~jyO>0t4R4__aQZQ9|Rz+k_Q!r#mR90+NR4_4NR%>ipO>0s{R90|SQhHKhRz+k^S8Q5JS5|OUQZO}CQfp*dS8P&9R8>k?QZYthRz+k_O>0#>
确实签到
base85_IPv6–>base64–>base32–>hex
flag{Th1s_1s_B4s3_3nc0d3}

[WEEK1]残缺的md5

被污染的字符串:KCLWG?K8M9O3?DE?84S9
被污染的地方为大写字母
md5码值:F0AF????B1F463????F7AE???B2AC4E6
爆破即可
image.png
flag{KCLWGXK8M9O3KDED84S9}

[WEEK1]凯撒大帝

pvkq{mredsrkyxkx}
凯撒前进10位即可
flag{chutihaonan}

[WEEK1]进制

3636366336313637376236313638363636623661366336383662363136383764
套了两层hex
flag{ahfkjlhkah}

[WEEK1]okk

Ook解密即可
flag{123456789}

[WEEK1]熊斐特

熊斐特博士发现了一种新的密码。
uozt{zgyzhs xrksvi}
熊斐特博士发现了埃特巴什码在线解码即可。
flag{atbash cipher}

[WEEK1]黑暗之歌

⠴⡰⡭⡳⠴⡰⡭⡰⡷⡲⡢⡩⡭⡡⠯⡩⡭⡡⡺⡩⡭⡡⠳⡩⡭⡡⡺⡩⡭⡡⡶⡩⡭⡡⡶⡩⡭⡡⡲⡩⡭⡡⡺⡩⡭⡡⠯⡩⡧⡊⡢⡩⡭⡡⠯⡩⡭⡡⡺⡃⡰⠫⡋⡚⡲⡍⡋⡮⠴⡰⡭⡶⡷⡲⡢⡩⡧⡊⡢⡃⡴⡵⡋⡁⡬⡵⡋⡁⡬⡵⡋⡁⡬⡳⡋⠲⠴⡯⡃⡗⠴⡰⡭⡴⠴⡰⡭⡶⡷⡲⡢⡩⡧⡊⡢⡩⡭⡡⡺⡩⡭⡡⡺⡩⡭⡡⠳⡩⡧⡊⡢⡩⡭⡡⠯⡩⡧⡊⡢⡃⡴⡵⡋⡚⡱⠫⡋⡚⡱⠫⡋⡚⡲⠵⠲⡺⠰⠽
只有特定网站才能解,没找到网站还解不了,还困我了好几天。
盲文–>base64–>音符
flag{b2cc-9091-8a29}

[WEEK1]迷雾重重

0010 0100 01 110 1111011 11 111 010 000 0 001101 00 000 001101 0001 0 010 1011 001101 0010 001 10 1111101
摩斯电码,短0长1,解码即可。
flag{morse_is_very_fun}

[WEEK1]难言的遗憾

题目描述:
我们本可以早些进入信息化时代的,但是清政府拒不采纳那份编码规则。 (注:flag为中文,使用flag{}包裹提交)
000111310008133175592422205314327609650071810649
搜一下题目描述就知道

在19世纪,法国驻华人员威基杰(S·A·Viguer)参照《康熙字典》的部首排列方法,挑选了常用汉字6800多个,编成了第一部汉字电码本,名为《电报新书》。这是第一个把汉字化作电子讯号的编码表。华侨商人王承荣从法国回国后,与福州的王斌研制出我国第一台电报机,并呈请政府自办电报。然而,清政府拒不采纳。如果当时清政府接受了这份编码规则,中国可能会早些步入信息化时代。这是一个值得深思的历史教训。

所以是中文电码查询,查出来的汉字套flag就行。image.png
flag{一天不学高数我就魂身难受}

[WEEK1]小兔子可爱捏

**题目描述:**宇宙的终极答案是什么?
U2FsdGVkX1/lKCKZm7Nw9xHLMrKHsbGQuFJU5QeUdASq3Ulcrcv9

生命、宇宙以及万物的终极答案是:42。

看题目就知道是rabbit加密,key就是万物的答案42。
flag{i_love_technology}

[WEEK1]电信诈骗

怎么会有人出rot47后再异或转十六进制的东西啊
050f000a7e407151537802540b747176075178027552756d0256726262627c
一段十六进制的字符串,拿到题的时候各种加密都给它试了一遍,什么凯撒栅栏都安排上,试半天都没出来,过了一周玩xortool的时候想起这题,猜测是xor,试了试毫无疑问的大失败。image.png
只能接着看题了,想起题目里还有个**第四行第七列**看起来像是个条件的东西没用上,排除第一天猜的曲路密码,那只有rot47了。
image.png
先在cyberchef将flag{rot47得到7=28L,再在xortool执行xortool -b -p "7=28L" fff,有一个结果,大成功。
image.png
key:0x32
我们得到了字符串7=28LrCcaJ0f9FCD5cJ0GG_0d@PPPN,扔回cyberchef进行rot47,得到最终flag flag{Cr42y_7hursd4y_v1v0_5o!!!}`

[WEEK1]what is m

1
2
3
4
5
6
7
from Crypto.Util.number import bytes_to_long
from secret import flag

m = bytes_to_long(flag)
print("m =",m)

# m = 7130439814059477382735061905846926104190173258689906867912627305084790676702500703219569625857222878602432233922047703164719872847143382515739521443488714791253213527237485305010874627540093

十分基础RSA,甚至没有RSA,直接long_to_bytes(m)就可以了。
flag{thERE_Are_5EvEraL_AIt3rn47ivES_TO_The_I0nG_to_8yt35_fUNctioN_E8gC0ZTO44bD}

[WEEK1]really_ez_rsa

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from Crypto.Util.number import getPrime, bytes_to_long

e = 65537
m = b''

p = getPrime(128)
q = getPrime(128)
n = p * q
m = bytes_to_long(m)
c = pow(m, e, n)

print("p =", p)
print("q =", q)
print("c =", c)
print("e =", e)

# p = 217873395548207236847876059475581824463
# q = 185617189161086060278518214521453878483
# c = 6170206647205994850964798055359827998224330552323068751708721001188295410644
# e = 65537
1
2
3
4
5
6
7
8
9
10
11
12
13
import gmpy2
from Crypto.Util.number import *

p = 217873395548207236847876059475581824463
q = 185617189161086060278518214521453878483
c = 6170206647205994850964798055359827998224330552323068751708721001188295410644
e = 65537

phi = (p-1)*(q-1)
d = gmpy2.invert(e,phi)
m = gmpy2.powmod(c,d,p*q)
m = long_to_bytes(m)
print(m)

flag{Y0ung_meiyou_xiaojj}

[WEEK2]XOR

1
2
3
4
n = 20810298530643139779725379335557687960281905096107101411585220918672653323875234344540342801651123667553812866458790076971583539529404583369246005781146655852295475940942005806084842620601383912513102861245275690036363402134681262533947475193408594967684453091957401932685922178406769578067946779033282889429596341714417295489842047781388337010440309434639274398589029236213499110100040841426995862849012466514170374143655264739023758914247116354182164550612494432327931655944868705959874670536031052370968354394583880324756639698871918124498442308334232127034553164826483441746719644515097123067550594588348951855987
c = 15294238831055894095745317706739204020319929545635634316996804750424242996533741450795483290384329104330090410419090776738963732127756947425265305276394058773237118310164375814515488333015347737716139073947021972607133348357843542310589577847859875065651579863803460777883480006078771792286205582765870786584904810922437581419555823588531402681156158991972023042592179567351862630979979989132957073962160946903567157184627177910380657091234027709595863061642453096671316307805667922247180282486325569430449985678954185611299166777141304330040782500340791721548519463552822293017606441987565074653579432972931432057376
e = 65537
p⊕q = 66138689143868607947630785415331461127626263390302506173955100963855136134289233949354345883327245336547595357625259526618623795152771487180400409991587378085305813144661971099363267511657121911410275002816755637490837422852032755234403225128695875574749525003296342076268760708900752562579555935703659615570

假设pqp\oplus q的第一个 bit 是 0,那么 p,q 的第一个 bit 只有(0,0)(0,0)(1,1)(1,1)两个可能
假设pqp\oplus q的第一个 bit 是 1,那么 p,q 的第一个 bit 只有(0,1)(0,1)(1,0)(1,0)两个可能
所以我们直接拿现成脚本就能过了

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
from Crypto.Util.number import *
from tqdm import tqdm

class Solver:
def __init__(self, x, n):
self.x = x
self.n = n
self.pq = [(0, 0)]

def add(self, b, p, q):
if p * q <= n and (p | (b - 1)) * (q | (b - 1)) >= n:
self.pq.append((p, q))

def solve(self):
for shift in tqdm(range(4095, -1, -1)):
b = 1 << shift
pq, self.pq = self.pq, []
for p, q in pq:
if self.x & b:
self.add(b, p | b, q)
self.add(b, p, q | b)
else:
self.add(b, p, q)
self.add(b, p | b, q | b)
return self.pq[0]

x = 66138689143868607947630785415331461127626263390302506173955100963855136134289233949354345883327245336547595357625259526618623795152771487180400409991587378085305813144661971099363267511657121911410275002816755637490837422852032755234403225128695875574749525003296342076268760708900752562579555935703659615570
n = 20810298530643139779725379335557687960281905096107101411585220918672653323875234344540342801651123667553812866458790076971583539529404583369246005781146655852295475940942005806084842620601383912513102861245275690036363402134681262533947475193408594967684453091957401932685922178406769578067946779033282889429596341714417295489842047781388337010440309434639274398589029236213499110100040841426995862849012466514170374143655264739023758914247116354182164550612494432327931655944868705959874670536031052370968354394583880324756639698871918124498442308334232127034553164826483441746719644515097123067550594588348951855987
c = 15294238831055894095745317706739204020319929545635634316996804750424242996533741450795483290384329104330090410419090776738963732127756947425265305276394058773237118310164375814515488333015347737716139073947021972607133348357843542310589577847859875065651579863803460777883480006078771792286205582765870786584904810922437581419555823588531402681156158991972023042592179567351862630979979989132957073962160946903567157184627177910380657091234027709595863061642453096671316307805667922247180282486325569430449985678954185611299166777141304330040782500340791721548519463552822293017606441987565074653579432972931432057376
e = 65537
solver = Solver(x, n)
p, q = solver.solve()
r = (p - 1) * (q - 1)
d = inverse(e, r)
m = pow(c, d, n)
print(long_to_bytes(m))

flag{7428fbd7-639b-11ee-b51b-64d69af3cb76}

[WEEK2]easymath

LCG解码

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
import sympy
import libnum
import contextlib


def lcg_get_m(output):
t = [output[i] - output[i - 1] for i in range(1, len(output))]
return [int(sympy.gcd(t[i + 3] * t[i + 1] - t[i + 2] * t[i + 2], t[i + 2] * t[i] - t[i + 1] * t[i + 1])) for i in range(len(t) - 3)]

def lcg_get_a(output, m):
lis = []
with contextlib.suppress(Exception):
lis.extend((output[i + 2] - output[1]) * int(sympy.mod_inverse((output[i + 1] - output[i]), m)) % m for i in range(len(output) - 2))
return lis

def lcg_get_b(output, a, m):
return [(output[i] - a * output[i-1]) % m for i in range(1, len(output))]

def lcg_get_seed(output, a, b, m):
with contextlib.suppress(Exception):
a_inv = int(sympy.mod_inverse(a, m))
return a_inv * (output[0] - b) % m

def lcg_solver(output, isPrint=True, isSet=False):
lis = []
for m in lcg_get_m(output):
for a in lcg_get_a(output, m):
for b in lcg_get_b(output, a, m):
print(f'a={a}')
print(f'b={b}')
print(f'n={m}')
print('')
return lis

if __name__ == '__main__':
# output = [69676071514199964129368494511049773706185789519381885090989836826032423348931601761005255484444660094, 63031206989830671133688676504767396390656004885395484175664501826753686622909142758317354395992301026, 10982611756211554291222567868588733322082261620905115629089850311461024570081479382334755302093076626, 57593354371133571326881703280620102147253648139230630688131873856129105654575862207035367081838844484, 47619980490914264678052844656879066638030284466312631649629134306776942962249639156106765582151143844, 58789571370633161248337888914950971131623915440268354523313877777336488371785773275506162258821825516, 109481456137357201661490538198304522268006931099085677213764961347749368305449034788701532872386412243, 19307804703479426044115964742461201656670909298595515226324824508728816047217841799764422041962083267, 93700801968408201834162526077717334683725582703626747502836611244942102316238114344746715776427713387, 87095688282213954059983741940081650190732077925687511841367934545528486899471711188785929150582606959]
output = [288530505749272642500730917886204398531, 63547143998110685331032679758907988154, 15151206512028268617888756820805603406, 268092204209244869520724955865278855216, 261067075335188593563542448889694952077, 138067838531633886698552659065694918861, 201319433320428898153580935653793106657]
lcg_solver(output, isPrint=True, isSet=False)


image.png
整出来几个只有前半部分对或后半部分对。测试后发现后半部分对的数据的n//2后都能对上

1
2
3
4
5
6
7
s=288530505749272642500730917886204398531
a=353733322192743482141176376172827954412
b=11856650155037935400579201826386146297
n=625538716226113130272019859227420156638//2
for i in range(6):
s = (s * a +b) % n
print(s)

image.png
得到第七个数据302184756857257140159769321021979097116
flag{302184756857257140159769321021979097116}

[WEEK2]ez_rsa

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
# from flag import flag
from Crypto.Util.number import getPrime, bytes_to_long
from math import prod
import libnum

with open("flag.txt","rb") as f:
flag = f.read().strip()

m = int.from_bytes(flag[:19],"big")
m1 = int.from_bytes(flag[19:],"big")

e = 65537

primes = [getPrime(64) for i in range(32)]
n = prod(primes)
c = pow(m,e,n)
print("c =",c)
print("n =",n)

p = libnum.generate_prime(1024)
q = libnum.generate_prime(1024)
e1 = 13
e2 = 15
n1 = p * q
c1 = pow(m1, e1, n1)
c2 = pow(m1, e2, n1)
print("n1 =", n1)
print("e1 =", e1)
print("c1 =", c1)
print("n2 =", n1)
print("e2 =", e2)
print("c2 =", c2)

# c = 28535916699190273475273097091422420145718978597126134891571109006456944397344856577421369324831702083810238921719657496747722337086131545474384253288151783029981352196506749672783866527948391034258269669654392993063423671431837882584570973320095601407578443348352802850496429240170710269529489900871208384711844617081275862971410246759090936379744946527813691945129059991795202769186014306943707223831130752782380563227353615164053563120572722464543812139164048342504963081408349934180883607554389607335607410546630525512019818062185681153477671373000186961748278118124044645584490544698827467815360888525822167
# n = 114107341297408283801468814470303963122122556489590451040619457052827864984505912502462030175984161431709841571908269123131659496812467145870607611968843929870716066046232009282431653653484798819370087696248364531531706249180822839879862098012984590503284615395588919199545142177727328844260380842155437987767067800740569616584597507776426572206990858918111272636507821551592564540694671795374831548677720629329358177802890287837056940407030212276399942462042866947423728888561392653713356355778914658317507319575084393752755452971007289968044006561357799908892371839922838486713582082980752194204224263283004373
# n1 = 21235204662158833223664424963408105101885570855652885953922511758363954474947609854216589644512813634294435585894296340005122907229365513346971631594453999584706013889403572150499529308966742992668850443386284277210686717652643585324255759216699733045642544284406720854291604837774882256435503827543483289606177965628162259184958789025311291796067574924595051311298594432767265114154138693108465671184854794167878031822162731921299518989845784744659944947091213703810190708463199067553747177712259911724424547999547534441790125049383068377243727588278432796727885216967953646999183906479537750330738956233695342750567
# e1 = 13
# c1 = 5640630966585093229374938575158853304507369792931959909038819773057666482368490365383634362421839045569190487785222799103423460816096797210546343809620912249021763787314569982909943181390882015170344954037813745251119237402775124991005154299085147091159741067430623420349690886728161235034687649593258746455165172528681627568611599473627285223154284756417744280966157271904828156564067870877521824545300153084830020169048653830385763172792698591998191641849931039720453035065355411394516308865955772746815765864888631258825704788352584540380169938419618543124830541663995097651872542381
# n2 = 21235204662158833223664424963408105101885570855652885953922511758363954474947609854216589644512813634294435585894296340005122907229365513346971631594453999584706013889403572150499529308966742992668850443386284277210686717652643585324255759216699733045642544284406720854291604837774882256435503827543483289606177965628162259184958789025311291796067574924595051311298594432767265114154138693108465671184854794167878031822162731921299518989845784744659944947091213703810190708463199067553747177712259911724424547999547534441790125049383068377243727588278432796727885216967953646999183906479537750330738956233695342750567
# e2 = 15
# c2 = 5481001445755770090420425478456880914921441486935672376394423326451811448703288166341447356603281843336826624725965666634194700496514262129376916108926167953996689011980280761368893884042609095616407660087448963015169181749124738976578495911295096014725354350167650232970262765851074146687931181216305972147994236689422572940877763047930111954798962097847426932730342258169023809341164876019161104439561164839132092594444017039073155506935768658830659965630065643619399324102814118128802834719820426253836317043818687888302054465994498115387703382090351794495827905499417861507007863378916334790750453883661675063377

因为n是由32个64位质数相乘,所以拿yafu或者Wolfram很容易就能算出32个质数
image.png
然后我们就可以使用前面的已知p,q,e,m的脚本求出flag的前半部分:flag{05929ec9778ed7

n = p1 ^ k1 * p2 ^ k2 pm ^ km
phi(n)= phi(p1 ^ k1)* phi(p2 ^ k2)* … * phi(pm ^ km)
=(p1 ^(k1-1)(p1-1))(p2 ^(k2-1)(p2-1))(pm ^(km-1)(pm-1))

接下来再看第二部分,下半段flag是使用相同N,不同私钥e加密。通过共模攻击就能获取flag的下半段了。

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
import gmpy2 as gp
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)

n =
c1 =
c2 =
e1 =
e2 =
s = egcd(e1, e2)
s1 = s[1]
s2 = s[2]
if s1<0:
s1 = - s1
c1 = gp.invert(c1, n)
elif s2<0:
s2 = - s2
c2 = gp.invert(c2, n)

m = pow(c1,s1,n)*pow(c2,s2,n) % n
print(hex(m)[2:])
print(bytes.fromhex(hex(m)[2:]))

39d94ee1a77b742714}
flag{05929ec9778ed739d94ee1a77b742714}

[WEEK2]e?

1
2
3
4
p= 70724362259337647663584082414795381346569735601816096923682814277857463878289
q= 114427188167532721707398034034072867253267857672869034942206947096293901917007
e= 1314
c= 4308122681135507736058122041934864039713319497673888928736468819190185301630702240416683093700232966794026900978699666246019059398861283337865339404916304

稍微算一下我们可以得到nφ(n)
n=8092789908277978665005515143673850928353061371599519589535927175863918663237830376840016835685252551651488088046127795645394809920457864985276394027161023
r=8092789908277978665005515143673850928353061371599519589535927175863918663237645225289589965315881569535039219797527958052120124788591975223902242661365728
e和欧拉函数r很明显不互质,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import gmpy2
import libnum

p = 70724362259337647663584082414795381346569735601816096923682814277857463878289
q = 114427188167532721707398034034072867253267857672869034942206947096293901917007
e = 1314
c = 4308122681135507736058122041934864039713319497673888928736468819190185301630702240416683093700232966794026900978699666246019059398861283337865339404916304

n = p * q
phi = (p - 1) * (q - 1)

t = gmpy2.gcd(e, phi)
t1 = e // t
dt1 = gmpy2.invert(t1, phi)
mt1 = pow(c, dt1, n)
s, m = gmpy2.iroot(mt1, t)
print(libnum.n2s(int(s)))

flag{This_e_is_real_or_not}

[WEEK2]factorizing_n

1
2
3
n = 226515252384227990547287743140613580056836242860947832749754689048997071950972581790210817523352001702907675581567498443649554801433663166425134375454937126656357069687274036935331269594383360450823787099121079436459236734336130768046337169817940540921822023269188752420603975467384377614321048859304185067329741055517464271746238143742661897809442359331215501438861121047081117632626097939097519866099140569819965948998542652908170134545593659233229897003698175558888336706474178958535138595687148003367152624421106553412886263257022809480187410133186189435436294593588009551451899398811758511878324326255293307347560753524372663257044426744744426759970254203341706284024734042826158828749144322843934985927079504722440497388146240627249465363931951790326885478025237643
c = 52409805591744226507807531465616894934028463651864630447934395956954575834603756391651746535033902964658694070544877880970130028487381287088425209448038533705903737694267359561133766799228825599943891152463160326583722749586721691729062524310148743637505134465210906856660867852927837112666513674858029892207902196213784902541173835447263733760225682942461048573387925463479672527491229113710629340960375692432470493054415657845868577650170648157402682163577152288432313996310562452677399267755695644659367792066311336521698894993982901657735586844358679888210537898629281625526455444811591386493005341435516094660429968084363084301878446471676122069724608083578102382181382107225473535696274374370868301830807644939881080301668756603163431000745972823980427048672732291
e = 65537

image.png
factordb里可以查到n是11776588228599764849559519654482976956833367474471407292255776713760090338489966385328569279135095351660161277221351884258247731394014018172166064062551483的5次方,通过这个公式算出欧拉。
接下来过程就和正常rsa一样了。
flag{1f95f530f85b940db810fc917607ee22}

[WEEK2]哈希猫

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
hashcat -m 10800 -a 3 991803e045cd761c22b0cb80b8d99b596e446c357e296c35e1984a5475724af9772c9d5ed477d77abb9c0bf4a9892f92 ?a?a
hashcat -m 1700 -a 3 d16b9330e774f03d24018750b6c47ed34fa102f480ed068fd21b9551071afd883fdb58e1ec40c881be6f42e3611c04a51a10972129b9340f0f57cd1e47676fc0 ?a?a
hashcat -m 1700 -a 3 0394aec006a50b2f5c13a8802199e9ea00e031f62a0952bcf027651ae196defc4fbf2c448d6078dbebebc2321f971979c868819774c28afcc8e900693b26e399 ?a?a
hashcat -m 10800 -a 3 acaa3b819d42cdf43ab2fbf0bdceff60401e172b605ce880c8c8bc37aa0e9016cfa6159161e970c9c85d4dd27391982a ?a?a
hashcat -m 0 -a 3 ea4be9e613bdefe2ff22d26ef086489f ?a?a?a
hashcat -m 100 -a 3 5d84b11e776faf1d7c4ef7b24085dc40e3392b04 ?a?a
hashcat -m 0 -a 3 e0cbd66d037c8eed49b363c83c8cc150 ?a?a?a
hashcat -m 1700 -a 3 2b5801d08603c0d5f4db58b71dc5ff22e1e3d3b88ac43dcc4468d1cbbaf3c4631c066a848818c4ed52fb329ec8a9ea77aa470d397040f2d938d1a9c8da6fa96c ?a?a
hashcat -m 10800 -a 3 40d935fc9c84e7009036be09be782a2dbeadd6e17af895b63c0274fdd4e4e90353c86b52e6ce6ae501cf3474fdf1c858 ?a?a
hashcat -m 1300 -a 3 e4cebd3cc00ec13ced07b1ca14c197f42ea1e0cae3f7d77b0a96dd38 ?a?a
hashcat -m 1400 -a 3 0968d47e4b1ab9b3f0512824af29eec65892ee02f6f874991a6e2c332a5d1ec7 ?a?a
hashcat -m 1700 -a 3 38f3476fe78a5ac95ed2e2da792de22645c92f1466b30704c6d8d5d725325da9c742c5e8a3704caaea8b19d4b211780d32b7658958b6bb3f58f6f868f86e522c ?a?a
hashcat -m 0 -a 3 be4e8b1b86899974868e3100862270db ?a?a?a
hashcat -m 1300 -a 3 bd65db31e42b702d2da90620d67a3b7e2bbde97a877ac2caff5ee911 ?a?a
hashcat -m 1700 -a 3 da30f5865321cbaa6608917b01ac8967eeee07c33dd99981f5a9e17b9e0a19c92abc2205cd638b85ff01df016e77bf51d377d29685b1872514ab871eb9ae5094 ?a?a
hashcat -m 1700 -a 3 1cfe56a974c2591a7a6a12e5dcc48b27c8f139a5497d81b39f5c067e6a2bdb6c44d0967118251de876585dde0a0a88a9199ec83ae4f420c5a91f09e733ccbc5f ?a?a
hashcat -m 1400 -a 3 d5dcccf1035b6f3c0b640efafc705b709c915f3865b5c2a2dd507eee8311ecc0 ?a?a
hashcat -m 0 -a 3 6a8cbf8d3b7f9c16471960e00688d5d9 ?a?a?a
hashcat -m 0 -a 3 26eda90c06b2500af822dcc8784b7cac ?a?a

一个一个爆破出来就是flag

[WEEK3]e=3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from Crypto.Util.number import *
import random
from secret import flag

M = 2**54
k = 6

def gen_prime(M, k):
while True:
prime = sum([random.getrandbits(16) * M**i for i in range(k)])
if isPrime(prime) and (prime-1) % 3 == 0:
return prime

p, q, r = [gen_prime(M, k) for i in range(3)]
N = p * q * r
e = 3
m = bytes_to_long(flag)
c = pow(m, e, N)
print(f'N = {N}')
print(f'c = {c}')

ap=u0+M1u1+M2u2+M3u3+M4u4+M5u5ap=u_0+M_1u_1+M_2u_2+M_3u_3+M_4u_4+M_5u_5
image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
x=2**54
M=[]
N=3298593732762513945346583663585189774036688951059270517149719979434109398447628726951796006700754759352430339647168415338320547665794785951232342902233013221132246450312038122695046634624323814318286314664160113738299465643128504110932989263063331290006313
for i in range(16):
temp=[0]*16
temp[i]=1
if i<15:
temp[-1]=x**(15-i)
else:
temp[-1]=-N
M.append(temp)
#print(M)
M=matrix(M)
res=M.LLL()
ans=res[0]
R.<x>=PolynomialRing(ZZ)
f=ans[0]*x^15+ans[1]*x^14+ans[2]*x^13+ans[3]*x^12+ans[4]*x^11+ans[5]*x^10+ans[6]*x^9+ans[7]*x^8+ans[8]*x^7+ans[9]*x^6+ans[10]*x^5+ans[11]*x^4+ans[12]*x^3+ans[13]*x^2+ans[14]*x^1-ans[15]
print(f.factor())
x=2**54
print(350*x^5 + 48522*x^4 + 12574*x^3 + 35367*x^2 + 47153*x + 11459)
print(25282*x^5 + 31957*x^4 + 31998*x^3 + 6834*x^2 + 31014*x + 33821)
print(54595*x^5 + 17296*x^4 + 5814*x^3 + 36787*x^2 + 58035*x + 45247)

计算x^e=c mod p可能的根x,即为明文m对素数因子p的余数,依次求出m对所有素数因子的余数,再利用中国剩余定理CRT即可求得明文m。

image.png

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
from Crypto.Util.number import *
import gmpy2

n=3298593732762513945346583663585189774036688951059270517149719979434109398447628726951796006700754759352430339647168415338320547665794785951232342902233013221132246450312038122695046634624323814318286314664160113738299465643128504110932989263063331290006313

def crt(p1,p2,p3,m1, m2, m3):
sum=0
sum=m1*p2*p3*gmpy2.invert(p2*p3,p1)+m2*p1*p3*gmpy2.invert(p1*p3,p2)+m3*p1*p2*gmpy2.invert(p1*p2,p3)
return(sum%n)

a=[58383452479543131076855934509741752025206650798238763131766171204144199973002763115,122617707808044844007053752240239222045619334067957689167250377150074042923493780616,482996996234883125916032111415725428787855877361820995776251923891064516068510426320]
b=[18143122910746632802760790849434875122272158765179877065974674419710509701900863407838,36424485120478422926110331617780661342810880506830917473692264821696035978803055217117,41359257072780580632890398034433643652882822195872701943656937234984865595670618060671]
c=[61695349249250900171149518200953176371787933317832171902443217436369641168587685862604,67454041411939814638843132976517805891984618772510645207094893775472021220827370015239,77999062797918036151032686758427285444812254144672132867018666300545262814799649766059]
p1=663998156522471100999941798165706402858681862228017448075268472245282758965006970051
p2=47963432552002818180880760250824590058982930733941748241661938238195705638187268342813
p3=103574226729554375480512668967949133854292403117507474988278388756193462602107352821951

for x in a:
for y in b:
for z in c:
m = crt(p1,p2,p3,x, y, z)
m=long_to_bytes(m)
if b'flag{' in m:
print(m)
break

[WEEK3]好好好!

1
2
3
4
5
6
***EGK*MAPZ**3TISLXYHW*B4*R*6CQV

e=65537
dp=89183181604123417010894108474901628410408206538085478807758137668201829058797702838603939730356798163745078443656032825128645105954284119126609502005130005399692420386460970318283171848176434285488698019425286328269756591931253074416895028845240978211030365697435579850343911269163064228581083838914477473793
n=17133884272385326910236146208723169235592379139078245324256146697759098524213354087333170410075813764497353656874360657828668202585141557095326829141561993608634568037533128091918704136052835609732443342167341276983343070200953604216445186924411131823487594273213380078485528148801722039459601896275130691200206027353715109606722659553700867073796386669768748305283547862565020499794358571741903375812063001390288166187510171105241363677243530996160649133253643422391688399573703498726489248479978887237752214015456924632092625018668632234215462091314384917176427670194819828555385014264912614752917792278216214856001
c=7297673446200396117470312266735704951424121735299327785232249350567349180167473433806232931862684106388722088953786183522191592452252650217579986150373463901393038386627370305688040315665037164819432754099421229466379901436696822022518438390977543864543590936753547325597766614648063328562516667604171990354928485383191174966274941678597887943784661684719053108281896697098991347034225406718530599672101743303723470910913422462764406680309933367328977341637394665138995676573466380198978810546689819954949832833954061771415463198737542769848298258925680570823701939997224167603657418270886620562332895947413332492672

单走一个dp泄露。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import gmpy2
import libnum

e=65537
dp=89183181604123417010894108474901628410408206538085478807758137668201829058797702838603939730356798163745078443656032825128645105954284119126609502005130005399692420386460970318283171848176434285488698019425286328269756591931253074416895028845240978211030365697435579850343911269163064228581083838914477473793
n=17133884272385326910236146208723169235592379139078245324256146697759098524213354087333170410075813764497353656874360657828668202585141557095326829141561993608634568037533128091918704136052835609732443342167341276983343070200953604216445186924411131823487594273213380078485528148801722039459601896275130691200206027353715109606722659553700867073796386669768748305283547862565020499794358571741903375812063001390288166187510171105241363677243530996160649133253643422391688399573703498726489248479978887237752214015456924632092625018668632234215462091314384917176427670194819828555385014264912614752917792278216214856001
c=7297673446200396117470312266735704951424121735299327785232249350567349180167473433806232931862684106388722088953786183522191592452252650217579986150373463901393038386627370305688040315665037164819432754099421229466379901436696822022518438390977543864543590936753547325597766614648063328562516667604171990354928485383191174966274941678597887943784661684719053108281896697098991347034225406718530599672101743303723470910913422462764406680309933367328977341637394665138995676573466380198978810546689819954949832833954061771415463198737542769848298258925680570823701939997224167603657418270886620562332895947413332492672

p=gmpy2.gcd(pow(2,e*dp,n)-2,n)
print(p)
q = n // p
phi_n = (p - 1) * (q - 1)
d = gmpy2.invert(e, phi_n)
m = pow(c, d, n)
print(m)
flag = libnum.n2s(int(m))
print(flag)

得到b'7U25DUJJ7USYATEN5SREOFFG5NY57FPS77U5DFPY54JEG3NYKWSYA3YD5CXYTTNW53QS====',看起来是base32,原题也给了个32位长度的字符集,应该是要爆破

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
import base64
import string
import itertools

def custom_b32decode(encoded_string, custom_alphabet):
standard_alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'
translation_table = str.maketrans(custom_alphabet, standard_alphabet)
translated_string = encoded_string.translate(translation_table)
return base64.b32decode(translated_string)

# 需要解码的字符串
encoded_string = "7U25DUJJ7USYATEN5SREOFFG5NY57FPS77U5DFPY54JEG3NYKWSYA3YD5CXYTTNW53QS===="

s = '***EGK*MAPZ**3TISLXYHW*B4*R*6CQV'
num_stars = s.count('*')
chars = 'DFJNOU257'
perms = itertools.permutations(chars, num_stars)

for perm in perms:
temp_s = s
for char in perm:
temp_s = temp_s.replace('*', char, 1)
combination=temp_s
decoded_string = custom_b32decode(encoded_string, combination)
if decoded_string[:4] == b"flag":
print('Decoded:', decoded_string)

flag{fa48a440-d0ff-0c2a-366243-a46b7e7853}

[WEEK3]ECC

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
from Crypto.Util.number import bytes_to_long ,getPrime
from random import randint
from secret import flag , p, A, B
class LCG:
def __init__(self, seed, multiplier, increment, modulus):
self.state = seed
self.multiplier = multiplier
self.increment = increment
self.modulus = modulus

def round(self):
self.state = (self.state * self.multiplier + self.increment) % self.modulus
return self.state

LcG = LCG(p, A, B, getPrime(300))
hint = []
rounds = randint(9,999)
for i in range(rounds):
hint.append(LcG.round())

print('N =', LcG.modulus)
print('hint =', hint[rounds-3:])
print('rounds =',rounds)

m = bytes_to_long(flag)
E = EllipticCurve(GF(p),[A,B])
P = E.random_point()
Q = m*P

print ('P:',P)
print ('Q:',Q)


# N = 1705645606203127815241171918687627021577200232693360803176339060735701046699878139210471893
# hint = [636069412722067246232363738058153543623441999807233766815792565367482634061996324381623962, 304296855761621673778181899704444469040702750638226241550940594764639309459830936587974100, 1369774672269556932935800229277891277508181443695280312507479120092877427518702489338377191]
# rounds = 611

# P:(49406083727713549693479975868239264009389610559536161157693590969827248174170 : 28287361640541793840463104064921879492703398965958850715625826686274126953254 : 1)
# Q:(85104390757778310667159437345416298355181306838067680133293027670951051429172 : 69777058446770421918855917195821666750565679103928898866010952464550068778869 : 1)

前半部分就是之前看到的LCG,用脚本算出abseed也就是pAB

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
import sympy
import libnum
import contextlib

def lcg_get_a(output, m):
lis = []
with contextlib.suppress(Exception):
lis.extend((output[i + 2] - output[1]) * int(sympy.mod_inverse((output[i + 1] - output[i]), m)) % m for i in range(len(output) - 2))
return lis

def lcg_get_b(output, a, m):
return [(output[i] - a * output[i-1]) % m for i in range(1, len(output))]

def lcg_get_seed(output, a, b, m):
with contextlib.suppress(Exception):
a_inv = int(sympy.mod_inverse(a, m))
ipt=[(a_inv * (output[-1] - b) % m)]
for i in range(610):
ipt.append(a_inv * (ipt[-1] - b) % m)
return ipt

def lcg_solver(output, isPrint=True, isSet=False):
lis = []
m=1705645606203127815241171918687627021577200232693360803176339060735701046699878139210471893
for a in lcg_get_a(output, m):
for b in lcg_get_b(output, a, m):
print(f'a={a}')
print(f'b={b}')
ipt = (lcg_get_seed(output, a, b, m))
print(len(ipt))
print(ipt[-1])
print('--------')

if __name__ == '__main__':
output = [636069412722067246232363738058153543623441999807233766815792565367482634061996324381623962, 304296855761621673778181899704444469040702750638226241550940594764639309459830936587974100, 1369774672269556932935800229277891277508181443695280312507479120092877427518702489338377191]
lcg_solver(output, isPrint=True, isSet=False)
1
2
3
4
A = 57186237363769678415558546920636910250184560730836527033755705455333464722170
B = 47572366756434660406002599832623767973471965640106574131304711893212728437629
p = 91720173941422125335466921700213991383508377854521057423162397714341988797837
N = 1705645606203127815241171918687627021577200232693360803176339060735701046699878139210471893

下半部分就是椭圆曲线密码学(英语:Elliptic Curve Cryptography,缩写:ECC)是一种基于椭圆曲线数学的公开密钥加密算法。与传统的基于大质数因子分解困难性的加密方法不同,ECC 依赖于解决椭圆曲线离散对数问题的困难性。
P是椭圆曲线的一个点,Q是椭圆曲线上的另一个点,求k其实就是已知椭圆曲线和两点求私钥,使用sagemath
image.png
flag{7H47s_eAsyES7_ecc_97Dd39}


SHCTF-Crypto
http://example.com/2023/10/30/SHCTF-WP-Crypto/
作者
pjx1314
发布于
2023年10月30日
许可协议