# 卷王杯
# 密码签到
密文: Y3NldHRfZl9jc2FyaF95b3Nwd2l0JTdCbW9qcCF1bCU3RA==
base64 解码 csett_f_csarh_yospwit%7Bmojp!ul%7D
url 解码 csett_f_csarh_yospwit{mojp!ul}
栅栏爆破 ctfshow{just_a_simple_crypto!}
# 真・简单・不卷・现代密码签到
from Crypto.Util.number import bytes_to_long | |
from secrets import p,q,r,s,t,flag | |
n = p * q * r * s * t | |
e = 2 | |
m = bytes_to_long(os.urandom(500) + flag) | |
c = pow(m,e,n) | |
print(p,q,r,s,t,sep='\n') | |
print(c) | |
''' | |
145332367700944303747548912160113939198078051436029477960348968315913956664143693347226702600438608693933768134575289286283267810723137895903153829001826223446477799895493265422562348917012216790077395795861238257357035152687833639085415763850743538206986781418939737511715957738982536382066693822159860701263 | |
116660458253067608044065523310547233337730583902133756095473339390057738510707447906971188577217274861047379404014140178165569604404468897712846876108444468370709141219302291601408652742006268186059762087155933131837323952675627966299810891805398890428420575425160696531236660480933905879208166090591482794763 | |
157931722402853245421436270609912823260313730941283152856444641969403238646482562190531038393124087232554754746464603598717356255570166081501573727336977292059427220330169044611674973569766966838498453232642731737958791706086957762244686953294662693939604300864961637325536379321027705854708492453330690705531 | |
100973451687449518854742673778783266158999451072058606348222018797891147675959983616210003484476577612134482311993701677242007759556951494382833070563369964294544839433671087037596159753825249018950693369209927951667775267086896180395776150188902057785214767230658487267587289809918132337927575673868568976679 | |
93960345071948255233882121683650797512129333868351496468898834736770441398743300745703393838320587998953678254272245400344928586394089488734271897540051673996675973642347859306921527430850673334243441180183460927865980713929789963587608547554858491264614271309608925634272282292964002897650355047792764365447 | |
9144597920381774885442906257311149465702295057238600973973598305004391534618770363098565074541384771979931799878381439264848137810353858418200992191234142740194489573540381681161219332611454834544291634628456257670178843484698324641739324687497388018406214041657278323855749902661752448796122517061920880552011343608609622885787617238758769398972009949575526258430282648817039091284796330585349957724522615105102735930258969562103112238020133587096826386028128471852377225525357348919204333121695432662339443004327748973224423132988376298843862056631045488285859621661802413201793962883794915513510467912312842687601478117040419013468059983777273699192408773551806581458197324620065210523913467414181480875280203580147077789063808832356486197271376615883221558265591069223727607585313240243619515521180600435114131162272519949101464089935441251751426683447701142156416866113627126765919641034042927519834229168536331952275698122511502745177547569813354280565828372968703810158857859460406828090199683324760956105682902577189283246483314689365570862217407333103243336691401424548702387876409228977278498691200028282744239512091373110111792177228979867318546462714521296256938374618636206565791541769138267080789842400796973226733816939794717596194090232425688504890234304977612220790858557639246367437740975495450011676714198668471438814299689325208882261918460708833888406187912527346628912894921059735420931656953236560178909180587372589456926690219114173193202048332172538564489660440225377822914097420807957784201785024166011709377791129 | |
''' |
e=2 可以想到 rabin 但是 gcd (e,p-1)=e,gcd (e,q-1)=e……
看到 la 佬博客里有
AMM 算法看不懂加 CRT 算法
p=145332367700944303747548912160113939198078051436029477960348968315913956664143693347226702600438608693933768134575289286283267810723137895903153829001826223446477799895493265422562348917012216790077395795861238257357035152687833639085415763850743538206986781418939737511715957738982536382066693822159860701263 | |
q=116660458253067608044065523310547233337730583902133756095473339390057738510707447906971188577217274861047379404014140178165569604404468897712846876108444468370709141219302291601408652742006268186059762087155933131837323952675627966299810891805398890428420575425160696531236660480933905879208166090591482794763 | |
r=157931722402853245421436270609912823260313730941283152856444641969403238646482562190531038393124087232554754746464603598717356255570166081501573727336977292059427220330169044611674973569766966838498453232642731737958791706086957762244686953294662693939604300864961637325536379321027705854708492453330690705531 | |
s=100973451687449518854742673778783266158999451072058606348222018797891147675959983616210003484476577612134482311993701677242007759556951494382833070563369964294544839433671087037596159753825249018950693369209927951667775267086896180395776150188902057785214767230658487267587289809918132337927575673868568976679 | |
t=93960345071948255233882121683650797512129333868351496468898834736770441398743300745703393838320587998953678254272245400344928586394089488734271897540051673996675973642347859306921527430850673334243441180183460927865980713929789963587608547554858491264614271309608925634272282292964002897650355047792764365447 | |
c=9144597920381774885442906257311149465702295057238600973973598305004391534618770363098565074541384771979931799878381439264848137810353858418200992191234142740194489573540381681161219332611454834544291634628456257670178843484698324641739324687497388018406214041657278323855749902661752448796122517061920880552011343608609622885787617238758769398972009949575526258430282648817039091284796330585349957724522615105102735930258969562103112238020133587096826386028128471852377225525357348919204333121695432662339443004327748973224423132988376298843862056631045488285859621661802413201793962883794915513510467912312842687601478117040419013468059983777273699192408773551806581458197324620065210523913467414181480875280203580147077789063808832356486197271376615883221558265591069223727607585313240243619515521180600435114131162272519949101464089935441251751426683447701142156416866113627126765919641034042927519834229168536331952275698122511502745177547569813354280565828372968703810158857859460406828090199683324760956105682902577189283246483314689365570862217407333103243336691401424548702387876409228977278498691200028282744239512091373110111792177228979867318546462714521296256938374618636206565791541769138267080789842400796973226733816939794717596194090232425688504890234304977612220790858557639246367437740975495450011676714198668471438814299689325208882261918460708833888406187912527346628912894921059735420931656953236560178909180587372589456926690219114173193202048332172538564489660440225377822914097420807957784201785024166011709377791129 | |
e=2 | |
P.<a>=PolynomialRing(Zmod(p),implementation='NTL') | |
f=a^e-c | |
mpx=f.monic().roots() | |
P.<a>=PolynomialRing(Zmod(q),implementation='NTL') | |
g=a^e-c | |
mqx=g.monic().roots() | |
P.<a>=PolynomialRing(Zmod(r),implementation='NTL') | |
h=a^e-c | |
mrx=h.monic().roots() | |
P.<a>=PolynomialRing(Zmod(s),implementation='NTL') | |
i=a^e-c | |
msx=i.monic().roots() | |
P.<a>=PolynomialRing(Zmod(t),implementation='NTL') | |
j=a^e-c | |
mtx=j.monic().roots() | |
for mpp in mpx: | |
x=mpp[0] | |
for mqq in mqx: | |
y=mqq[0] | |
for mrr in mrx: | |
z=mrr[0] | |
for mss in msx: | |
a=mss[0] | |
for mtt in mtx: | |
b=mtt[0] | |
solution=hex(CRT_list([int(x),int(y),int(z),int(a),int(b)], [p,q,r,s,t]))[2:] | |
if (b'ctfshow'.hex() in solution): | |
print(bytes.fromhex(solution)) |
# 芜
from Crypto.Cipher import AES | |
from Crypto.Util.number import * | |
from Crypto.Util.Padding import pad | |
import random | |
def woohoo(): | |
a = random.getrandbits(32) | |
b = random.getrandbits(32) | |
c = random.getrandbits(32) | |
d = random.getrandbits(32) | |
return (a<<96)+(b<<64)+(c<<32)+(d) | |
BANNER = """ | |
+-------------+ | |
| * * | | |
| * * | | |
| *********** | | |
| * * | | |
| | | |
| ********* | | |
| * | | |
| * | | |
| *********** | | |
| * * | | |
| * * | | |
| * * * | | |
| ** ***** | | |
+-------------+ | |
赛事预告: | |
比赛名称:ctfshow 卷王杯 | |
题目难度:无 | |
出题奖励:usb小台灯+周边钥匙扣 | |
比赛奖励:单项第1送定制妹子贴纸,单项AK取前3 | |
比赛时间:2022年2月25日(周五) 18时整 | |
比赛时长:48小时 | |
比赛地址:https://ctf.show/challenges | |
投稿邮箱:ctfshow@163.com | |
""" | |
MENU = """ | |
+-----------------+ | |
|[E]ncrypt | | |
|[T]est encryption| | |
|[8]86 | | |
+-----------------+ | |
""" | |
if __name__ == '__main__': | |
print(BANNER) | |
# 我只泄露一点线索 | |
# 是谁为爱走钢索 | |
for i in range(130): | |
print(MENU) | |
option = input("> ").lower() | |
if option == "e": | |
print("Enter your message.") | |
msg = input("> ").encode() | |
msg = pad(msg, AES.block_size) | |
key = woohoo() | |
iv = woohoo() | |
key = long_to_bytes(key).rjust(AES.block_size, b"\x00") | |
iv = long_to_bytes(iv).rjust(AES.block_size, b"\x00") | |
c = AES.new(key, AES.MODE_CBC, iv=iv) | |
ct = c.encrypt(msg) | |
iv = b"never gonna give you up" | |
print(f"Ciphertext (hex): {ct.hex()}") | |
print(f"Key (hex): {key.hex()}") | |
print(f"IV (hex): {iv.hex()}") | |
elif option == "t": | |
flag = open("flag.txt", "rb").read() | |
msg = pad(flag, AES.block_size) | |
key = woohoo() | |
iv = woohoo() | |
key = long_to_bytes(key) | |
iv = long_to_bytes(iv) | |
c = AES.new(key, AES.MODE_CBC, iv=iv) | |
ct = c.encrypt(msg) | |
key = b"never gonna let you down" | |
print(f"Ciphertext (hex): {ct.hex()}") | |
print(f"Key (hex): {key.hex()}") | |
print(f"IV (hex): {iv.hex()}") | |
elif option == "8": | |
print("Sa yo na la!") | |
break | |
else: | |
print("What r u DOIN?") | |
else: | |
print("Never gonna run around and desert you") |
我们可以看到
def woohoo(): | |
a = random.getrandbits(32) | |
b = random.getrandbits(32) | |
c = random.getrandbits(32) | |
d = random.getrandbits(32) | |
return (a<<96)+(b<<64)+(c<<32)+(d) |
看到 getrandbits 就要想到 mt19937 随机数预测
在选项 e 里 可以得到 key 值
那么通过这个值可以得到密文解密后的明文 1 在与自己设置的 iv 异或得到正真的 iv
具体可以看图
这样我们知道了 key 和 iv 就相当于知道了 8 个随机数
而成功预测要 624 个 所以要 624/8 次循环
from pwn import * | |
from Crypto.Util.number import * | |
from Crypto.Cipher import AES | |
from Crypto.Util.Padding import pad | |
from mt19937predictor import MT19937Predictor | |
re=remote("pwn.challenge.ctf.show",28046) | |
mt=[] | |
for i in range(100): | |
m=b'' | |
re.recvuntil(b'> ') | |
re.sendline(b'E') | |
re.recvuntil(b'> ') | |
re.sendline(m) | |
re.recvuntil(b'Ciphertext (hex): ') | |
c = int(re.recv(32).decode(), 16) | |
re.recvuntil(b'Key (hex): ') | |
key1 = int(re.recv(32).decode(), 16) | |
mt.append(key1) | |
c=long_to_bytes(c).rjust(AES.block_size, b"\x00") | |
key1=long_to_bytes(key1).rjust(AES.block_size, b"\x00") | |
iv0=b'\x00'*16 | |
d=AES.new(key1,AES.MODE_CBC,iv0) | |
iv=d.decrypt(c).rjust(AES.block_size, b"\x00") | |
iv1=bytes_to_long(xor(iv,pad(m,AES.block_size))) | |
mt.append(iv1) | |
predictor = MT19937Predictor () | |
for i in mt: | |
d=i & (2**32-1) | |
i=i>>32 | |
c=i &(2**32-1) | |
i=i>>32 | |
b = i & (2 ** 32 - 1) | |
i = i >> 32 | |
a = i & (2 ** 32 - 1) | |
predictor.setrandbits(a, 32) | |
predictor.setrandbits(b, 32) | |
predictor.setrandbits(c, 32) | |
predictor.setrandbits(d, 32) | |
a=predictor.getrandbits(32) | |
b=predictor.getrandbits(32) | |
c=predictor.getrandbits(32) | |
d=predictor.getrandbits(32) | |
key=(a<<96)+(b<<64)+(c<<32)+(d) | |
a=predictor.getrandbits(32) | |
b=predictor.getrandbits(32) | |
c=predictor.getrandbits(32) | |
d=predictor.getrandbits(32) | |
iv=(a<<96)+(b<<64)+(c<<32)+(d) | |
print(hex(iv)) | |
key = long_to_bytes(key) | |
iv = long_to_bytes(iv) | |
re.recvuntil(b'> ') | |
re.sendline(b'T') | |
c=int(re.recvline().decode().strip()[18:],16) | |
c=long_to_bytes(c) | |
h = AES.new(key, AES.MODE_CBC, iv) | |
print(h.decrypt(c)) | |
re.interactive() |
# 概率 RSA
完全没思路,看了 wp and 借鉴 307 的博客
la 佬
这道题是 rsa 的 lsb
假设存在一个 oracle,能对给定密文进行解密并给出对应明文的奇偶信息,则我们只需要 log (N) 次就能解密任意密文。
在一次 RSA 加密中,明文为 m,模数为 n,加密指数为 e,密文为 c。我们可以构造出
c′=((2e)⋅c)%n=((2e)⋅(me))%n=((2⋅m)e)%n ,
因为 m 的两倍可能大于 n,所以经过解密得到的明文是 m′=(2⋅m)% n 。
我们还能够知道 m′ 的最低位 lsb 是 1 还是 0。 因为 n 是奇数,而 2⋅m 是偶数,所以如果 lsb 是 0,说明 (2⋅m)% n 是偶数,没有超过 n,即 m<n/2,反之则 m>n/2 。举个例子就能明白 2%3=2 是偶数,而 4%3=1 是奇数。以此类推,构造密文 c′′=((4^e)⋅c)% n 使其解密后为 m′′=(4⋅m)% n ,判断 的奇偶性可以知道 m′′ 和 n/4 的大小关系。所以我们就有了一个二分算法,可以在对数时间内将 m 的范围逼近到一个足够狭窄的空间。
# https://introspelliam.github.io/2018/03/27/crypto/RSA-Least-Significant-Bit-Oracle-Attack/ | |
from pwn import * | |
from Crypto.Util.number import * | |
import re | |
p=remote("pwn.challenge.ctf.show",28158) | |
# context.log_level = 'debug' | |
def oracle(c): | |
l = [] | |
for i in range(20): | |
p.sendline(str(c)) | |
s = p.recvuntil(b"temp_c = ") | |
l.append(int(re.findall(b"\)\s*=\s*([0-9]*)", s)[0])) | |
flag0 = 0 | |
flag2 = 0 | |
for i in range(20): | |
if l[i] % 2 != 0: | |
flag0 = 1 | |
if l[i] > 10000: | |
flag2 = 1 | |
return [flag2, flag0] | |
def main(): | |
ss = p.recvuntil(b"temp_c = ") | |
N = int(re.findall(b"N\s*=\s*(\d+)", ss)[0]) | |
e = int(re.findall(b"e\s*=\s*(\d+)", ss)[0]) | |
C = int(re.findall(b"c\s*=\s*(\d+)", ss)[0]) | |
print("N=", N) | |
print("e=", e) | |
print("c=", C) | |
c = (pow(2, e, N) * C) % N | |
LB = 0 | |
UB = N | |
i = 1 | |
while LB != UB: | |
flag = oracle(c) | |
print(i, flag) | |
if flag[1] % 2 == 0: | |
UB = (LB + UB) // 2 | |
else: | |
LB = (LB + UB) // 2 | |
c = (pow(2, e, N) * c) % N | |
i += 1 | |
print(LB) | |
print(UB) | |
for i in range(-128, 128): | |
temp = LB | |
temp += i | |
if pow(temp, e, N) == C: | |
print(long_to_bytes(temp)) | |
exit(0) | |
if __name__ == '__main__': | |
main() | |
p.interactive() |
跑的有点慢 要 i=1024 才出来
# 铱锡锡
本题和上次 ECC 一样,漏洞点还是在输入椭圆曲线上的点坐标时,并未检测点是否在曲线上。
并且注意,倍点运算的过程中并未利用到 的值进行计算。
所以就有我们可以调整 的值,使得点 在以我们调整的 值所对应的椭圆曲线上。由倍点计算过程,点 也在这条椭圆曲线上。
而且题目给了 6 次尝试机会,所以我们可以把点 弄成一个光滑的循环子群的生成元,其阶为(光滑),送到交互里面,会吐出一个,这样就可以由 Pohlig-Hellman 算法算出 的值。
再由中国剩余定理,如果这些 选择得当,那么便可以知道 的值。
参考的 值:1, 4, 12, 38.
#sage | |
from pwn import * | |
from sage.all import * | |
oi=remote('pwn.challenge.ctf.show',28044) | |
B=[1,5,9,12,38,13] | |
G=((111400716329737223151348215591382049163897085784802947255747133622415879105394, 39992761736411400081935771079229874378216016675324636692947348968013201165276), | |
(13719045388076151520803368351989304615465812259733704032402319532249511403233, 70112205679957371132763956439647700048310284796833596573793277095178113815519), | |
(43073418371286323595156732037737293646818329128791009438524376324397773820726, 35593429086189375972008488132929667910986330958314594350096901828426497889077), | |
(66433977671962939100073201807983167264694941590643124947273042440494792218015, 21652151330053975273880197568657021519050157521775125899551963970572483258486), | |
(40092374358375676891557996696416077109395130857602600253780368444671153878383, 1220793250473451325744127538413666357546316742399446078249755026290349789846), | |
(37673718832712137809127078277795630388877581750162566803210280135148912394288, 56746642413640372892023989284505332312846604225559347665409782919856416362427)) | |
QQ=[] | |
for i in range(6): | |
oi.sendline('1') | |
oi.sendline(str(G[i])) | |
oi.recvuntil('The coordinate of Q is ') | |
x=int(oi.recvuntil(', ')[1:-2]) | |
y=int(oi.recvuntil('\n')[:-2]) | |
QQ.append((x,y)) | |
tt=[1,1,2,2,2,1] | |
aa=[] | |
bb=[] | |
for i in range(6): | |
print(i) | |
p = 115792089210356248762697446949407573530086143415290314195533631308867097853951 | |
a = -3 | |
b=B[i] | |
E=EllipticCurve(GF(p),[a,b]) | |
Q=E(QQ[i]) | |
GG=E(G[i]) | |
factors, exponents = zip(*factor(E.order())) | |
primes = [factors[i] ** exponents[i] for i in range(len(factors))][:-tt[i]] | |
K=[] | |
mul=1 | |
for i in primes: | |
mul*=i | |
for i in primes: | |
t=E.order()//i | |
k=discrete_log(t*Q,t*GG,operation='+') | |
K.append(k) | |
aa.append(crt(K,primes)) | |
bb.append(mul) | |
print(aa) | |
print(bb) | |
pay=crt(aa,bb) | |
print(pay) | |
oi.sendline('2') | |
oi.sendline(str(pay)) | |
oi.interactive() |