一共8道密码题,前4个比较简单,后边3个基本是模板恰巧有这个板子。
rot727
没啥就是个凯撒,直接在厨子里爆破就行。
aeg{at_imuf_nussqd_zgynqd_paqezf_yqmz_yadq_eqogdq}
osu{oh_wait_bigger_number_doesnt_mean_more_secure}
beyond-wood
from PIL import Image
import random
FLAG = Image.open("flag.png")
width, height = FLAG.size
key = [random.randrange(0, 256) for _ in range(width+height+3)]
out = FLAG.copy()
for i in range(width):
for j in range(height):
pixel = FLAG.getpixel((i, j))
pixel = tuple(x ^ k for x, k in zip(pixel, key)) #变色这块对区分图上的字没有影响
newi, newj = (2134266 + i * 727) % width, (4501511 + j * 727) % height
out.putpixel((newi, newj), pixel)
out.save("output.png")
一是位置作了替换,这个因为是固定替换,所以很容易替换回去,二是把颜色作了变更,由于每次都是固定的异或key的前3个,所以不用关心他,只是颜色不同,看图形没问题。然后就是猜那些巨难认的手写字符。
old = Image.open("output.png")
width, height = old.size
out = old.copy()
for i in range(width):
for j in range(height):
newi, newj = (2134266 + i * 727) % width, (4501511 + j * 727) % height
pixel = old.getpixel((newi, newj))
out.putpixel((i, j), pixel)
out.save("new.png")
#osu{h1_05u_d351gn_t34m}
xnor
意思就是同或,相同为1不同为0,跟异或差不多只是取反。
import os
flag = open("flag.txt", "rb").read()
def xnor_gate(a, b): #同或
if a == 0 and b == 0:
return 1
elif a == 0 and b == 1:
return 0
elif a == 1 and b == 0:
return 0
else:
return 1
def str_to_bits(s):
bits = []
for x in s:
bits += [(x >> i) & 1 for i in range(8)][::-1]
return bits
def bits_to_str(bits):
return bytes([sum(x * 2 ** j for j, x in enumerate(bits[i:i+8][::-1])) for i in range(0, len(bits), 8)])
def xnor(pt_bits, key_bits):
return [xnor_gate(pt_bit, key_bit) for pt_bit, key_bit in zip(pt_bits, key_bits)]
key = os.urandom(4) * (1 + len(flag) // 4)
key_bits = str_to_bits(key)
flag_bits = str_to_bits(flag)
enc_flag = xnor(xnor(xnor(flag_bits, key_bits), key_bits), key_bits)
print(bits_to_str(enc_flag).hex())
# 7e5fa0f2731fb9b9671fb1d62254b6e5645fe4ff2273b8f04e4ee6e5215ae6ed6c
key未知,作了3次同或,其实相同于1次。
先弄到key,跟异或一样,拿头异或回来。
c = bytes.fromhex('7e5fa0f2731fb9b9671fb1d62254b6e5645fe4ff2273b8f04e4ee6e5215ae6ed6c')
c_bits = str_to_bits(c)
head = b'osu{'
head_bits = str_to_bits(head)
key = bits_to_str(xnor(c_bits[:32], head_bits))
#b'\xee\xd3*v'
再拿key同或回来。
key_bits = str_to_bits(key*9)
bits_to_str(xnor(c_bits, key_bits))
b'osu{b3l0v3d_3xclus1v3_my_b3l0v3d}'
pls-nominate
from Crypto.Util.number import *
FLAG = open("flag.txt", "rb").read()
message = bytes_to_long(
b"hello there can you pls nominate my map https://osu.ppy.sh/beatmapsets/2436259 :steamhappy: i can bribe you with a flag if you do: " + FLAG
)
ns = [getPrime(727) * getPrime(727) for _ in range(5)]
e = 5
print(len(FLAG))
print(ns)
print([pow(message, e, n) for n in ns])
e=5给了5对n,c直接用crt,再求x小值
N = prod(ns)
C = crt(cs,ns)
m = b"hello there can you pls nominate my map https://osu.ppy.sh/beatmapsets/2436259 :steamhappy: i can bribe you with a flag if you do: osu{"+b'\0'*46+b'}'
m = bytes_to_long(m)
P.<x> = PolynomialRing(Zmod(N))
f = (m+x*256)^5 - C
m = f.small_roots(X=2^(8*47))[0]
long_to_bytes(int(m))
#osu{pr3tty_pl3453_w1th_4_ch3rry_0n_t0p!?:pleading:}
please-nominate
上一题的升级版,把每个c对应的m的填充不同。大概看也是crt,只是m不同,所以需要对多项式作.
from Crypto.Util.number import *
FLAG = open("flag.txt").read()
BNS = ["Plus4j", "Mattay", "Dailycore"]
print(len(FLAG))
for BN in BNS:
print("message for", BN)
message = bytes_to_long(
(f"hi there {BN}, " + FLAG).encode()
)
n = getPrime(727) * getPrime(727)
e = 3
print(n)
print(pow(message, e, n))
'''
147
message for Plus4j
n1 = 398846569478640111212929905737126219425846611917845064245986310899352455531776606361272505433849914145167344554995030812644189047710542954339906669786929747875597103059283954786345252202913509966200329213618547501451752329008531151228646387182403280019664272348231587940227470159846477386295856419407431569159867135365878913551268186765163877676657618137090681937329865631964114691373454627873900294385351135992352798790940857277941472243
c1 = 158222951303542921410153264594688628146576794503998427093311713650774531277430572380170172031191979123500854263417781975728851277579707820383487572964731381023292312261571110891911863884482902461410218286288183400964045679561296043109527250114073394295486982996930960424139332989226106162113091535475425207610140495532136130360540296097313129598880764160739736823532823136291009499982471028009894097569348660440830784543668141509385395632
#message for Mattay
n2 = 263921537800979838796221921202623647462415714721726394821753160972868778052085367522658133754602607941536627474441882978361116817475949497489399939969612509386335591643019109294105788234910211931439396509289221190345347268312099449152342020093136914687793357372601654532872673983206837150636881928382445566331068237688851345596537893940860402116702078271640048006152159670916299390559068168682951764623558492401318864545619303656361575039
c2 = 166535918659821916010028099769670832129351247306732465032191446110439632420210106966178779555368253320514619095691319433325610616798380002564235371548166904170934635615481900225094067835806190805967329346507481446735982286060193425107057243896658750175391024795867108700750688771820192759373880324263838550825384190714299697136118712791588291627904942573970568726142296145821435413605295796704576678263679112272532276173497584694652201371
#message for Dailycore
n3 = 244031565800210621970295548144726813179733488382314342571474949081381534498271587584918252306707810369627816196681952536809552862200098862267362735277533022204353497254323228274491354364582967316701126783750290886096960998524414107270804949357307485711415647006606381700355291677615735646360495158637105102935658791364633128882874894799509049190571860852436246528522948513282608143921733438326627413507376148669722384969604597622237576689
c3 = 132630164676661516893599967289982601955380588903536428955472887691456873565355730161547637935630009622741758822400797894281114572338413548852823840995609427904180355965179631480101131212344121270312182355342132383562008365671754190667582150820337165104642347684925014217687937383396003151315200366708307846959894632317624125785370063052712288658901699972320248281442796056361927746314341729204052997736037101265782906021307934740092047950
'''
flag比较长,small_roots需要一点时间,等就行了。
BNS = ["Plus4j", "Mattay", "Dailycore"]
rs = [bytes_to_long(f"hi there {BN}, ".encode() + (b"\0"*147)) for BN in BNS]
cs = [c1,c2,c3]
ns = [n1,n2,n3]
e=3
equation = []
nl = ns
P.<x>=PolynomialRing(ZZ)
for _ in range(len(rs)):
f = (x + rs[_]) ^ e - cs[_]
equation.append(f)
mod=1
for i in nl:
mod*=i
ff=crt(equation,nl)
Q.<x>=PolynomialRing(Zmod(mod))
ff=Q(ff)
ff=ff.monic()
v = ff.small_roots(X=2 ** (8 * 147 ) , epsilon=0.03)[0]
long_to_bytes(v)
#b'guys please play resplendence https://osu.ppy.sh/beatmapsets/2436259#osu/5311353 6 digit represent osu{0mg_my_m4p_f1n4lly_g0t_r4nk3d_1m_s0_h4ppy!!}'
#osu{0mg_my_m4p_f1n4lly_g0t_r4nk3d_1m_s0_h4ppy!!}
ssss
#!/usr/local/bin/python3
from Crypto.Util.number import *
import random
p = 2**255 - 19
k = 15
SECRET = random.randrange(0, p)
def lcg(x, a, b, p):
return (a * x + b) % p
a = random.randrange(0, p)
b = random.randrange(0, p)
poly = [SECRET]
while len(poly) != k: poly.append(lcg(poly[-1], a, b, p))
def evaluate_poly(f, x):
return sum(c * pow(x, i, p) for i, c in enumerate(f)) % p
print("welcome to ssss", flush=True)
for _ in range(k - 1):
x = int(input())
assert 0 < x < p, "no cheating!"
print(evaluate_poly(poly, x), flush=True)
if int(input("secret? ")) == SECRET:
FLAG = open("flag.txt").read()
print(FLAG, flush=True)
分圆方程,这个p有最多12个根,把这些根发上去,用12次可以求出x0+x12,x1+x13,x2+x14,x3,x4,... 利用x3-x5求lcg,因为a,b,p已知所以求起来比较方便。
from pwn import remote,context as ctx
ctx.log_level = 'debug'
# context.log_level="debug"
p = 2 ** 255 - 19
R.<x0> = GF(p)[]
g,t = 2,12 #先找到一个t,使得 g = pow(2,(p-1)//t,p), pow(g,t,p)==1
g = pow(g, (p-1)//t, p)
def query():
g = 2
while pow(g, (p-1)//t, p) == 1:
g += 1
g = pow(g, (p-1)//t, p)
assert pow(g, t, p) == 1
shares = []
for i in range(t):
x = pow(g, i, p)
conn.sendline(str(x).encode())
y = int(conn.recvline())
shares.append((x, y))
return list(R.lagrange_polynomial(shares))
conn = remote('ssss.challs.sekai.team', 1337)
conn.recvline()
conn.recvline()
A = query()
a = (A[4]-A[5])*inverse_mod(int(A[3]-A[4]),p)%p
b = (A[4]-a*A[3])%p
v = A[3]
for i in range(3):
v = (v-b)*inverse_mod(int(a),p)%p
print('13,14')
conn.sendline(b'1')
conn.sendline(b'1')
conn.sendline(str(v).encode())
print(conn.recvline())
conn.interactive()
#osu{0n3_hundr3d_p3rc3nt_4ccur4cy!}
ssss+
#!/usr/local/bin/python3
from Crypto.Util.number import *
import random
p = 2**255 - 19
k = 15
SECRET = random.randrange(0, p)
def lcg(x, a, b, p):
return (a * x + b) % p
pp = getPrime(256)
a = random.randrange(0, pp)
b = random.randrange(0, pp)
poly = [SECRET]
while len(poly) != k: poly.append(lcg(poly[-1], a, b, pp))
def evaluate_poly(f, x):
return sum(c * pow(x, i, p) for i, c in enumerate(f)) % p
print("welcome to ssss", flush=True)
for _ in range(k - 1):
x = int(input())
assert 0 < x < p, "no cheating!"
print(evaluate_poly(poly, x), flush=True)
if int(input("secret? ")) == SECRET:
FLAG = open("flag.txt").read()
print(FLAG, flush=True)
上一题的升级版,这里lcg的pp不是用的p,由于p非常大的255位,所以很明显这些模p以后一般就是减掉一个p, :xp = x+kp (k∈[0,1]),所以这里对得到的结果需要爆破一系列k,测试6个就能出结果。
from pwn import remote,context as ctx
ctx.log_level = 'debug'
# context.log_level="debug"
p = 2 ** 255 - 19
R.<x0> = GF(p)[]
g,t = 2,12 #先找到一个t,使得 g = pow(2,(p-1)//t,p), pow(g,t,p)==1
g = pow(g, (p-1)//t, p)
def query():
g = 2
while pow(g, (p-1)//t, p) == 1:
g += 1
g = pow(g, (p-1)//t, p)
assert pow(g, t, p) == 1
shares = []
for i in range(t):
x = pow(g, i, p)
conn.sendline(str(x).encode())
y = int(conn.recvline())
shares.append((x, y))
return list(R.lagrange_polynomial(shares))
def getagv(A):
for kk in range(64):
ks = list(map(int,bin(kk)[2:].zfill(6)))
aa = [int(A[3+i])+ks[i]*p for i in range(6)]
#print('ks',ks,aa)
P.<a,b> = PolynomialRing(ZZ)
F = [a*aa[i]+b-aa[i+1] for i in range(5)]
ideal = Ideal(F)
I = ideal.groebner_basis()
#print('I', I)
if '*' in str(I):
continue
# 求解参数a b n
res=[x.constant_coefficient() for x in I]
print('res',res)
if len(res) == 3:
n = res[2]
a = -res[0]%n
b = -res[1]%n
print('ks,a,b,n',ks,a,b,n,isPrime(n))
if isPrime(n) and n.bit_length()==256: #过滤掉2这样的小素数
return n,a,b,aa[0]
conn = remote('ssssp.challs.sekai.team', 1337)
conn.recvline()
conn.recvline()
A = query()
A = [int(i) for i in A]
n,a,b,s3 = getagv(A)
v = s3
for i in range(3):
v = (v-b)*inverse_mod(int(a),n)%n
print('got :', v)
print('13,14')
conn.sendline(b'1')
conn.sendline(b'1')
conn.sendline(str(v).encode())
print(conn.recvline())
conn.interactive()
liner-feedback
from secrets import randbits
from math import floor
from hashlib import sha256
class LFSR:
def __init__(self, key, taps, format):
self.key = key
self.taps = taps
self.state = list(map(int, list(format.format(key))))
def _clock(self):
ob = self.state[0] #输出的前n个就是key
self.state = self.state[1:] + [sum([self.state[t] for t in self.taps]) % 2]
return ob
def xnor_gate(a, b):
if a == 0 and b == 0:
return 1
elif a == 0 and b == 1:
return 0
elif a == 1 and b == 0:
return 0
else:
return 1
key1 = randbits(21)
key2 = randbits(29)
L1 = LFSR(key1, [2, 4, 5, 1, 7, 9, 8], "{:021b}")
L2 = LFSR(key2, [5, 3, 5, 5, 9, 9, 7], "{:029b}")
bits = [xnor_gate(L1._clock(), L2._clock()) for _ in range(floor(72.7))]
print(bits)
FLAG = open("flag.txt", "rb").read()
keystream = sha256((str(key1) + str(key2)).encode()).digest()
print(bytes([b1 ^ b2 for b1, b2 in zip(FLAG, keystream)]).hex())
一个lfsr的题,用key1,key2生成两个lfsr然后将结果同或得到密文,由于这里直接输出0位,所以前n位就是key,所以可以先爆破key1(只有21位)生成29位,然后同或密文得到29位的key2就OK了。
from tqdm import trange
from hashlib import sha256
c = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0]
cipher = bytes.fromhex('9f7f799ec2fb64e743d8ed06ca6be98e24724c9ca48e21013c8baefe83b5a304af3f7ad6c4cc64fa4380e854e8')
c1 = c[:29]
def b2n(v):
return int(''.join(map(str,v)),2)
for key1 in trange(1<<21):
L1 = LFSR(key1, [2, 4, 5, 1, 7, 9, 8], "{:021b}")
v1 = [L1._clock() for i in range(29)]
v2 = [xnor_gate(cb,vb) for cb,vb in zip(c1,v1)]
key2 = b2n(v2)
keystream = sha256((str(key1) + str(key2)).encode()).digest()*2
tmp = bytes([b1 ^ b2 for b1, b2 in zip(cipher, keystream)])
if b'osu{' in tmp:
print(tmp, key1,key2)
#osu{th1s_hr1_i5_th3_m0st_fun_m4p_3v3r_1n_0wc}

被折叠的 条评论
为什么被折叠?



