先放一下官方的wp(我这里只放我出的题):
https://j0zr0js7k7j.feishu.cn/wiki/JQbiwKdvtiR49VkMj5RcmPvPn7c
random_primes
from Crypto.Util.number import *
import random
def gen_n():
primes=[getPrime(128) for _ in range(256)]
n = 1
for i in range(100):
n *= primes[random.randint(0,127)]
return primes,n
flag=b'BaseCTF{}'
m=bytes_to_long(flag)
assert len(flag)==45
primes,n = gen_n()
e = 0x010001
c=pow(m,e,n)
print("n =",n)
print("e =",e)
print("c =",c)
print("primes =",primes)
n很大很大,给了flag范围,可以得出flag为359位
素数都是128,利用3个素数(大约384位)即可比flag大
可以直接爆破
(数据太多就不贴了)
(好多师傅来问我最后为什么求出来是0,一看他们都是找出了所有素数,而且过程中都除以了n,导致最后n=1,这点需要注意)
from Crypto.Util.number import *
from gmpy2 import *
# n =
# e =
# c =
# primes =
for i in primes:
for j in primes:
for k in primes:
tn=i*j*k
phi=(i-1)*(j-1)*(k-1)
m=long_to_bytes(pow(c,invert(e,phi),tn))
if b'BaseCTF' in m:
print(m)
exit()
basic
from Crypto.Util.number import *
import socketserver
import os
import random
import base64
import string
flag = os.getenv('GZCTF_FLAG').encode()
class Task(socketserver.BaseRequestHandler):
def _recvall(self):
BUFF_SIZE = 2048
data = b''
while True:
part = self.request.recv(BUFF_SIZE)
data += part
if len(part) < BUFF_SIZE:
break
return data.strip()
def send(self, msg, newline=True):
try:
if newline:
msg += b'\n'
self.request.sendall(msg)
except:
pass
def recv(self):
return self._recvall()
def handle(self):
printable_chars = string.ascii_letters + string.digits + string.punctuation
optional=[b'A',b'B',b'C',b'D']
for _ in range(100):
secret= ''.join(random.choices(printable_chars, k=16)).encode()
select=random.choice(optional)
self.send(select)
enc=b''
if select==b'A':
enc=base64.b64encode(secret)
elif select==b'B':
enc=secret.hex().encode()
elif select==b'C':
enc=bytes_to_long(secret)
enc=str(enc).encode()
elif select==b'D':
enc=[i for i in secret]
enc=str(enc).encode()
self.send(enc)
client_send=self.recv()
if client_send!=secret:
self.send("\nYou wrong!!!!!")
exit()
self.send(flag)
self.send(b"\nConnection has been closed =.= ")
self.request.close()
class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
class ForkedServer(socketserver.ForkingMixIn, socketserver.TCPServer):
pass
if __name__ == "__main__":
HOST, PORT = '0.0.0.0', 9999
server = ForkedServer((HOST, PORT), Task)
server.allow_reuse_address = True
server.serve_forever()
一道给密码手练习pwntools使用的题
主要实现四种加密方式
A:base64
B:直接转成十六进制
C:转成整型
D:每个字符转成ascii码
(本人抽象代码,请谅解)
from pwn import *
import ast
import base64
from Crypto.Util.number import *
rem=remote("",)
for _ in range(100):
a=rem.recvline().decode().strip()
print(a,end=" ")
b=rem.recvline()
if a=='A':
b=base64.b64decode(b)
elif a=='B':
b=bytes.fromhex(b.decode().strip())
elif a=='C':
b=int(b.decode().strip())
b=long_to_bytes(b)
elif a=='D':
b=ast.literal_eval(b.decode().strip())
c=b''
for i in b:
c+=long_to_bytes(i)
b=c
print(b)
rem.send(b)
print(rem.recvall())
rem.interactive()
try_to_factor
from Crypto.Util.number import *
import random
flag=b'BaseCTF{}'+random.randbytes(64)
m=bytes_to_long(flag)
p,q,r,s,t=[getStrongPrime(512) for _ in range(5)]
N=p*q*r*s*t
n=p*q
e=65537
c=pow(m,e,n)
gift=random.randint(2,n)*(p-1)*(q-1)*(r-1)*(s-1)*(t-1)
while gift%2==0:
gift//=2
print("N =",N)
print("c =",c)
print("gift =",gift)
"""
N = 162692163428762295773992659007654377270271126313772302197255271375236131917158614424426498628778734679898165422129699410934825650141972454562350664161510689489443251515884304101827584411577749250383438126881931889798597627663578045519256806107514170414321556291545302688028088470848270636776466672843710163017531472049823632822203461654253767303314505996071453898533003519236112138591066133289040889933161978131399309340741554076140734156174295730180874473301361701867633594222054688204666518058106672165786417002466165926062199279674267145233283545524775943767021416906072142236079753359492846480515376121887507681663761713445807717270089017438999615422884163666812016989696908657065537508715229685120221307021151610089917537155165897740417480127289719971512938348936259
c = 113962118676826667648935023618252851875440854724310328843964819392166304653581141146631375503931008732348730639629174670963727399860571217264854300057305570824097216782800531930906801885967717639795643406206813677461127762087560021634738167845077869308515223303820469892552545806179267969169748886980836435095
gift = 863514692222931709925579242743251211976114217396765747601042357918763818732391790491059528595917786523674732369068315533549380754409535403506339052401422249684188032949680148055803474336983973622610403448963752802490806614810077181934627694570685722842963961551889267501616799757825675192653489096007790143775773378495299981666657347802233798206597104474595281241837323214457344961462510183726339545608046357281265026013496037522835659867389206279894057481600882665189079672009577651494435000349624334685832217586703242422260870866432379257259316411280539845741932725104662417642890238587876489774492067722351467773093391502588019563488688309892102039611978767690653206664257400163618467825666105966072942726011447079204869750153256054140924951306811971422635104088608275908232688385437145325481792836532453258784103533536292492138405929815964841772656055397705840797739586953744563989819811944946916720655079908564653686456283647030055622241840292127096994325415897266379446446435164189216562921252341705747891518007710533906231225283309180960546212899099652226954393826875
"""
(此题算是临时加的,因为我做不出moectf第二周的题,想着增加点难度?所以我一开始就是准备给论文的,如果你能够认真静下心来看完论文,应该就可以解决这个问题了。论文中给出了算法流程,并不需要搞懂原理就可以出,很多师傅找的模板也是可以用的,将gift每次乘2爆破就行,我这里只是稍微改了一下希望不是拿到模板能直接出的那种。最后如果让你感到了不好的体验,我在这道个歉。
关于N和\(phi(n)\)进行分解的脚本,当然可以直接用,可以直接进行爆破x倍的2,然后套脚本也是可以的。我这里只是稍稍微魔改了一点。这里面也有很多脚本,感兴趣可以多看看
https://github.com/jvdsn/crypto-attacks/blob/master/attacks/factorization/known_phi.py)
先贴一下论文3-540-36492-7_25.pdf (springer.com),主要是其中的第三部分
当然看不懂论文也没事,不过可以适当看一下2-Prime和3-Prime的部分,能够按算法流程实现就可以得到flag,主要是思想。
先从后往前看,最后对flag进行了2个素数的rsa加密,给了一个gift为k倍的\(phi(n)\)除去x倍的2。
从这里我们就可以看出来,要根据给的这个gift和之前的N来分解出p和q。
(分解出来是5个数,爆破一下就可以了)
算法流程:
\[我们可以知道:k\phi(n)=2^x*gift\\ 每一次分解时: 随机取一个数w\in[2,N-2]\\ 计算数a_1=w^{2^s*gift}\mod N\quad for\quad s=0,1... until\quad a_1\equiv1\mod N\\ 当结束后如果s=0则说明算法失效,一般为重新选取w。\\ 计算a_2\equiv w^{2^{s-1}*gift}\mod N\\ 保证a_2\not\equiv\pm1,则gcd(N,a_2+1)就是N的一个分解。\\ 由于一开始N不止有两个素数,所以这里需要判断一下分解出来的是不是素数。 \]本人的理解:
\[当a_1\equiv1\mod 时,a_1就是模N下的平凡平方根\\ 通过计算我们知道a_1\equiv a_2^2\equiv1\mod N\\ 因为N是合数,只要a_2\not\equiv\pm1\mod N,则a_2称为模N下的非平凡平方根\\ (这里只需要判断a_2\not\equiv1\mod N,因为出计算a_1时已经计算过一遍a_2不等于1了)\\ 得a_2^2-1\equiv(a_2+1)*(a_2-1)\equiv0\mod N\\ 得(a_2+1)*(a_2-1)=kN,因为N为合数\\ 得a_2+1=x或者a_2-1=x,这里x指kN中的一个因数\\ 那么我们通过求解gcd(N,a_2+1)或者gcd(N,a_2-1)就可以得到N的分解了\\ (所以算法中gcd中的a_2+1改成a_2-1也是可行的) \]from random import randrange
from gmpy2 import *
from Crypto.Util.number import *
import itertools
def my_factors(N, gift):
ans=[]
factors=[N]
while len(factors)>0:
N=factors[0]
w = randrange(2, N - 1)
s = 0
a_1 = pow(w, gift * pow(2,s), N)
while a_1!=1:
s=s+1
a_1 = pow(w, gift * pow(2,s), N)
if s!=0:
a_2 = pow(w, gift * pow(2,s-1), N)
if a_2!=N-1:
p = gcd(N, a_2 + 1)
if p!=1:
q=N//p
factors=factors[1:]
if isPrime(p):
ans.append(p)
else:
factors.append(p)
if isPrime(q):
ans.append(q)
else:
factors.append(q)
return ans
N = 162692163428762295773992659007654377270271126313772302197255271375236131917158614424426498628778734679898165422129699410934825650141972454562350664161510689489443251515884304101827584411577749250383438126881931889798597627663578045519256806107514170414321556291545302688028088470848270636776466672843710163017531472049823632822203461654253767303314505996071453898533003519236112138591066133289040889933161978131399309340741554076140734156174295730180874473301361701867633594222054688204666518058106672165786417002466165926062199279674267145233283545524775943767021416906072142236079753359492846480515376121887507681663761713445807717270089017438999615422884163666812016989696908657065537508715229685120221307021151610089917537155165897740417480127289719971512938348936259
c = 113962118676826667648935023618252851875440854724310328843964819392166304653581141146631375503931008732348730639629174670963727399860571217264854300057305570824097216782800531930906801885967717639795643406206813677461127762087560021634738167845077869308515223303820469892552545806179267969169748886980836435095
gift = 863514692222931709925579242743251211976114217396765747601042357918763818732391790491059528595917786523674732369068315533549380754409535403506339052401422249684188032949680148055803474336983973622610403448963752802490806614810077181934627694570685722842963961551889267501616799757825675192653489096007790143775773378495299981666657347802233798206597104474595281241837323214457344961462510183726339545608046357281265026013496037522835659867389206279894057481600882665189079672009577651494435000349624334685832217586703242422260870866432379257259316411280539845741932725104662417642890238587876489774492067722351467773093391502588019563488688309892102039611978767690653206664257400163618467825666105966072942726011447079204869750153256054140924951306811971422635104088608275908232688385437145325481792836532453258784103533536292492138405929815964841772656055397705840797739586953744563989819811944946916720655079908564653686456283647030055622241840292127096994325415897266379446446435164189216562921252341705747891518007710533906231225283309180960546212899099652226954393826875
primes=my_factors(N,gift)
print(primes)
permutation=itertools.combinations(primes,2)
for i in permutation:
p,q=i
p,q=int(p),int(q)
flag=long_to_bytes(pow(c,inverse(65537,(p-1)*(q-1)),p*q))
if b'BaseCTF' in flag:
print(flag)
break
#b'BaseCTF{ed4bff90-d1f4-4f0f-a3bd-999c54d9eeb7};\xef\xd7"X\xceglz\xc2l\xc3\xf0\x04\n$I\x00\xda\rT\xc5\xef\xc9t]\x0c\xae@\xdcO5\x02\xa8\xd6/{5\xacD5\xda\x11{\x80\x80\xa3\t#\x97\x871L\x10\r\x122z\xe1\x89%\x85\xdb\x94'
标签:gift,self,BaseCTF2024,Crypto,flag,wp,print,import,primes
From: https://www.cnblogs.com/naby/p/18385497