ctfshow月饼

crypto1_中秋月

此夜中秋月,清光十万家*** 自动钥匙⊕ 明文全大写,得到后转小写,并以_连接单词。 格式:flag{xxx}。 @⎝Lazzaro⎠师傅供题
fsskryenvkm~jl{ejs}jwflzsnpgmifq{{j{|suhzrjppnx|qvixt~whu

看起来毫无头绪,观察提示,自动钥匙,也就是autokey密码。

网上有它的python2脚本,但是解密后发现不正确,自动钥匙后面有异或的操作,可能题目给出的密文是通过异或得出来的,我们需要再进行异或一下,于是有

message="fsskryenvkm~jl{ejs}jwflzsnpgmifq{{j{|suhzrjppnx|qvixt~whu"
for i in range(255):#ASCLL---```0-255
    res=''
    for j in range (0,len(message)):
        temp =ord(message[j])^i#python中的^表示异或,在进行异或步骤时,需要把^前后两个数转换为二进制
        if 65<=temp<=90 or 97<=temp<=122:#65-90表示A-Z,97-122表示a-z
            res+=(chr(temp))
    if len(res)==len(message):
        print(res)

运行脚本后得到两组数字,再根据题目的提示发现有密文均为大写,即选择密文

YLLTMFZQITRAUSDZULBUHYSELQOXRVYNDDUDCLJWEMUOOQGCNIVGKAHWJ

再根据python脚本,即有

from ngram_score import ngram_score
from pycipher import Autokey
import re
from itertools import permutations

qgram = ngram_score('quadgrams.txt')
trigram = ngram_score('trigrams.txt')
ctext = 'YLLTMFZQITRAUSDZULBUHYSELQOXRVYNDDUDCLJWEMUOOQGCNIVGKAHWJ'
ctext = re.sub(r'[^A-Z]','',ctext.upper())

# keep a list of the N best things we have seen, discard anything else
class nbest(object):
    def __init__(self,N=1000):
        self.store = []
        self.N = N
        
    def add(self,item):
        self.store.append(item)
        self.store.sort(reverse=True)
        self.store = self.store[:self.N]
    
    def __getitem__(self,k):
        return self.store[k]

    def __len__(self):
        return len(self.store)

#init
N=100
for KLEN in range(8,20):
    rec = nbest(N)

    for i in permutations('ABCDEFGHIJKLMNOPQRSTUVWXYZ',3):
        key = ''.join(i) + 'A'*(KLEN-len(i))
        pt = Autokey(key).decipher(ctext)
        score = 0
        for j in range(0,len(ctext),KLEN):
            score += trigram.score(pt[j:j+3])
        rec.add((score,''.join(i),pt[:30]))

    next_rec = nbest(N)
    for i in range(0,KLEN-3):
        for k in range(N):
            for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
                key = rec[k][1] + c
                fullkey = key + 'A'*(KLEN-len(key))
                pt = Autokey(fullkey).decipher(ctext)
                score = 0
                for j in range(0,len(ctext),KLEN):
                    score += qgram.score(pt[j:j+len(key)])
                next_rec.add((score,key,pt[:30]))
        rec = next_rec
        next_rec = nbest(N)
    bestkey = rec[0][1]
    pt = Autokey(bestkey).decipher(ctext)
    bestscore = qgram.score(pt)
    for i in range(N):
        pt = Autokey(rec[i][1]).decipher(ctext)
        score = qgram.score(pt)
        if score > bestscore:
            bestkey = rec[i][1]
            bestscore = score       
    print(bestscore,'autokey, klen',KLEN,':"'+bestkey+'",',Autokey(bestkey).decipher(ctext).lower())

得到一句明文为,ohnoyoufindtheflagtheflagforyouisdoyoulikeclassicalcipher

得到flag

flag{do_you_like_classical_cipher}
autokey密码

中文为自动密钥密码,是属于多表替换密码的一种,该密钥的构成形式为关键字+明文。

举个例子

明文:THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG 
关键词:CULTURE
密钥: CULTURE THE QUICK BROWN FOX JUMPS OVER THE 

然后再采取与维吉尼亚密码相同的加密方式,在字母表中进行替换

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jIAVNT7s-1665645554165)(C:\Users\25964\AppData\Roaming\Typora\typora-user-images\image-20221013143850119.png)]

即可得到对应的密文

VBP JOZGD IVEQV HYY AIICX CSNL FWW ZVDP WVK

在线解密网站:

http://www.atoolbox.net/Tool.php?Id=920

crypto2_月自圆

题目源码

# -*- coding:utf-8 -*-
#Author: Lazzaro

from itertools import *
from random import *
from string import *

def encrypt(m, a, si):
	c=""
	for i in range(len(m)):
		c+=hex(((ord(m[i])) * a + ord(next(si))) % 128)[2:].zfill(2)
	return c
	
if __name__ == "__main__":
	m = '****************************************************flag{*************}'
	assert(len(m)==71)
	a = randint(50,100)
	salt = ''.join(sample(ascii_uppercase, 4))#生成四位大写字母
	si = cycle(salt.lower())#开始循环迭代
	c=encrypt(m, a, si)
	print(c)
	
#3472184e657e50561c481f5c1c4e1938163e154431015e13062c1b073d4e3a444f4a5c5c7a071919167b034e1c29566647600c4e1c2956661b6c1f50622f0016317e563546202a

先来分析一下题目的源码

他首先定义了一个加密函数,接下来进行了两个操作,生成字母以及一个迭代,接下来输出密文。

可以发现,原本定义的m明文长度为71位,解密后的c变成了142位,也就是翻了两倍,这是我们的一个信息点

因为我们现在未知的,一个是a,一个是salt,在已知信息m中给了我们一段flag,它处于第53位,对应到密文里,翻倍也就是106位,就可以根据这个信息来进行爆破

因此我们得到对应关系

f ⇒ 1c l ⇒ 29  a ⇒ 56   g ⇒ 66

from itertools import *
from random import *
from string import *

def encrypt(m, a, si):
	c=""
	for i in range(len(m)):
		c+=hex(((ord(m[i])) * a + ord(next(si))) % 128)[2:].zfill(2)
	return c

if __name__ == "__main__":
	for i in range(50,100):
		for j in ascii_uppercase:
			si = cycle(j.lower())

			if encrypt('l', i, si)=='29':
				print('i =',i,'\tj =',j)
            
			if encrypt('f', i, si)=='1c':
			 	print('i =',i,'\tj =',j)

我们二者取共同点,得到a=67

再使用他得加密函数,通过a来求得salt

if encrypt('a', 67, si)=='56':
	print('j =',j)

if encrypt('g', 67, si)=='66':
	print('j =',j)

即我们现在得到了,a=67,salt=JESQ,即有

from itertools import *
from random import *
from string import *

def encrypt(m, a, si):
	c=""
	for i in range(len(m)):
		c+=hex(((ord(m[i])) * a + ord(si)) % 128)[2:].zfill(2)
	return c
	
if __name__ == "__main__":
	
	salt = 'JESQ'
	si = cycle(salt.lower())
	c = '3472184e657e50561c481f5c1c4e1938163e154431015e13062c1b073d4e3a444f4a5c5c7a071919167b034e1c29566647600c4e1c2956661b6c1f50622f0016317e563546202a'
	res = ''
	for i in range(0,len(c),2):
		ssi = next(si)
		for j in range(32,127):
			if encrypt(chr(j),67,ssi)==c[i]+c[i+1]:
				res += chr(j)
	print(res)

得到res

now_is_7fad9fcb-d361-4964-821c-177c906b8d20_flag_is_flag{md5(now-salt)}

由flag后文得知,还需要再进行一次md5加密,加密后为需要得flag

flag{1efce62ee0a96e39149e2179db1dd04c}

crypto3_多少离怀

Weird Γ(x)? @⎝Lazzaro⎠师傅供题

# -*- coding:utf-8 -*-
#Author: Lazzaro

from Crypto.Util.number import getPrime,isPrime
from math import gamma
import random

def nextPrime(n):
    n += 2 if n & 1 else 1
    while not isPrime(n):
        n += 2
    return n

def getNewPrime():
    A = getPrime(512)
    B = nextPrime(A - random.randint(1e4,1e5))
    return nextPrime(gamma(B+2)%A)
	
p = getNewPrime()
q = getNewPrime()
r = getNewPrime()
n = p * q ** 2 * r ** 3
e = 0x10001
c = pow(flag,e,n)


#pA=6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723982789
#pB=6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723922147
#qA=7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477881291
#qB=7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477807457
#n=4451906216583258787166698210560165433649728830889954633721198623488802305844782492171757604711145165920462286487680020347239300947225371917344589502941576734875830871998499135120227347066586066943289430156378296665669974728569678779668142712266780949126509440672273927433367293606776081254094682033167575930701870261219046464773708974194213798032346187463443317770758989273370488582862531630356263732232300508706676725203199729764016766683870925164232508407363688370458877688991733322055785233669885166225464068579486683574954699370175267031949720967812902215635630884502987094547523361027411501285252862476410213277925430392164226297316310465146003494714018456407793759170649913180823814850170639706664167149612984905056804131124522209409607977589884632999710708045656852149371030046919242039957767777840304466948549383597755811307383659188216421501912831203089570725388153416013596114462069777713822433178099904907224119
#c=1996198968748552041728429851810599627895157160099076033250854211280074825148767841655949210593646824507865483166496070951130337321360509148527292165245205219296211294789087358959553387392928560150390604911087085313000622842025416521494799132969818997182731021267942464323979261593380113740152841984062184326431879167516288834455296913822921806893572566867611541664848820247889274979245086440402996661226884320574824077910315143756471444347386795428338020162169391827182914043434253974549636668126789355991920452920806351939782281969098470635517019120996509180703896707990501216102290302162705699788457579330150149320348175742131887213742989509004374645723471497302400169849858253644606818874098604333865973357374444445825761600866472906771935670261641342221394488068630591190697667016958881530367047928341661857241378511420562236766886349565409774340321441504290366223243635878057759623855735794209219474650425139791831374


观察它给出得数字,p,q,n,c已经全部给出,现在只剩一个(gamma(B+2)%A)是未知数,而这涉及到伽马函数,即

gamma(n)=(n-1)!

那我们就可以转换成

(B+1)!%A

再根据威尔逊定理第一条

当且仅当p为素数时:(p-1)! ≡ -1 (mod p)
推论:(p-2)! ≡ 1 (mod p)

设出(A-2)!%A=1

再令x=(A-2)/(B+1)!,y=(B+1)!,即可得到x * y ≡ 1 (mod A),因为现在y是x关于A得一个逆元,所以我们要先求X%A,进而求出y%A。

from Crypto.Util.number import getPrime,isPrime
import gmpy2

def nextPrime(n):
    n += 2 if n & 1 else 1
    while not isPrime(n):
        n += 2
    return n
	
def factorial_mod(A,B):
    ans = 1
    tmp = pow(-1,1,A)
    for i in range(B+1,A):
        ans = (ans*gmpy2.invert(i,A))%A
    return (ans*tmp)%A
	
pA = 6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723982789
pB = 6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723922147
qA = 7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477881291
qB = 7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477807457
n = 4451906216583258787166698210560165433649728830889954633721198623488802305844782492171757604711145165920462286487680020347239300947225371917344589502941576734875830871998499135120227347066586066943289430156378296665669974728569678779668142712266780949126509440672273927433367293606776081254094682033167575930701870261219046464773708974194213798032346187463443317770758989273370488582862531630356263732232300508706676725203199729764016766683870925164232508407363688370458877688991733322055785233669885166225464068579486683574954699370175267031949720967812902215635630884502987094547523361027411501285252862476410213277925430392164226297316310465146003494714018456407793759170649913180823814850170639706664167149612984905056804131124522209409607977589884632999710708045656852149371030046919242039957767777840304466948549383597755811307383659188216421501912831203089570725388153416013596114462069777713822433178099904907224119
c = 1996198968748552041728429851810599627895157160099076033250854211280074825148767841655949210593646824507865483166496070951130337321360509148527292165245205219296211294789087358959553387392928560150390604911087085313000622842025416521494799132969818997182731021267942464323979261593380113740152841984062184326431879167516288834455296913822921806893572566867611541664848820247889274979245086440402996661226884320574824077910315143756471444347386795428338020162169391827182914043434253974549636668126789355991920452920806351939782281969098470635517019120996509180703896707990501216102290302162705699788457579330150149320348175742131887213742989509004374645723471497302400169849858253644606818874098604333865973357374444445825761600866472906771935670261641342221394488068630591190697667016958881530367047928341661857241378511420562236766886349565409774340321441504290366223243635878057759623855735794209219474650425139791831374
e = 0x10001
p = nextPrime(factorial_mod(pA,pB+1))
q = nextPrime(factorial_mod(qA,qB+1))
r=gmpy2.iroot(n//(p*q*q),3)[0]
phi=(p-1)*q*(q-1)*r*r*(r-1)
d=gmpy2.invert(e,phi)
flag=gmpy2.powmod(c,d,n)
import binascii
print(binascii.unhexlify(hex(flag)[2:]))

flag{N0w_U_knOw_how_70_u5E_W1lS0n'5_Th30r3m~}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值