1、[AFCTF2018]Tiny LFSR
考点:LFSR加密
题解:
(1)题目
import sys
from binascii import unhexlify
if(len(sys.argv)<4):
print("Usage: python Encrypt.py keyfile plaintext ciphername")
exit(1)
def lfsr(R, mask):
output = (R << 1) & 0xffffffffffffffff
i=(R&mask)&0xffffffffffffffff
lastbit=0
while i!=0:
lastbit^=(i&1)
i=i>>1
output^=lastbit
return (output,lastbit)
R = 0
key = ""
with open(sys.argv[1],"r") as f:
key = f.read()
R = int(key,16)
f.close
mask = 0b1101100000000000000000000000000000000000000000000000000000000000
a = ''.join([chr(int(b, 16)) for b in [key[i:i+2] for i in range(0, len(key), 2)]])
f=open(sys.argv[2],"r")
ff = open(sys.argv[3],"wb")
s = f.read()
f.close()
lent = len(s)
for i in range(0, len(a)):
ff.write((ord(s[i])^ord(a[i])).to_bytes(1, byteorder='big'))
for i in range(len(a), lent):
tmp=0
for j in range(8):
(R,out)=lfsr(R,mask)
tmp=(tmp << 1)^out
ff.write((tmp^ord(s[i])).to_bytes(1, byteorder='big'))
ff.close()
题目大概的思路就是用Key对Plain.txt和flag_encode.txt进行异或加密,得到了cipher.txt和flag_encode.txt;那么让cipher.txt和flag_encode.txt;进行异或就能得到key
import codecs
import binascii
from Crypto.Util.strxor import strxor
cip = open('cipher.txt', 'rb').read()
msg = open('Plain.txt', 'rb').read()
bytes_data= strxor(cip, msg)[:len(cip)]
print(binascii.b2a_hex(bytes_data))
得到key为:0123456789abcdef;在得到了key之后,解题就只需要再一次进行异或运算即可
import sys
from binascii import unhexlify
from Crypto.Util.strxor import strxor
import codecs
key = '0123456789abcdef'
R = int(key, 16)
def lfsr(R, mask):
output = (R << 1) & 0xffffffffffffffff
i=(R&mask)&0xffffffffffffffff
lastbit=0
while i!=0:
lastbit^=(i&1)
i=i>>1
output^=lastbit
return (output,lastbit)
mask = 0b1101100000000000000000000000000000000000000000000000000000000000
cip = open('flag_encode.txt', 'rb').read()
a = ''.join([chr(int(b, 16)) for b in [key[i:i+2] for i in range(0, len(key), 2)]])
#上面这步是将a中的16进制范围内的字符每2个一组,构成0~255范围内的8个字符,然后与密文进行异或运算,密文读入时是'\xaa'的形式
lent = len(cip)
ans = []
for i in range(len(a)):
ans.append(chr((cip[i] ^ ord(a[i]))))
for i in range(len(a), lent):
tmp=0
for j in range(8):
(R,out)=lfsr(R,mask)
tmp=(tmp << 1)^out
#位移8次得到一个8位的序列,这个序列用于后续的异或运算
ans.append(chr(tmp ^ cip[i]))
#原本的加密没有改变信息原文的长度,于是可以对其进行简单异或还原信息
#cip[i]算作是int类型数据,故可以进行异或运算
print(''.join(ans))
2、[BJDCTF 2nd]老文盲了
考点:拼英解密
题解:
(1)题目
缃奸洤绶犵湐鎿寸仢娣涘尪瑗患鐎幎杌勯稕椹曢硴鍝电湐闉归皾
首先尝试拼音解密;发现就是flag
BJD{淛匶襫黼瀬鎶軄鶛驕鳓哵}
3、[AFCTF2018]一道有趣的题目
考点:
题解:
加密原理是明文自身每个字节依次与自身的某一个字节异或,与谁异或由space决定;那么我们首先就需要将space爆破出来
参考链接
4、LeftOrRight
考点:二叉树
题解:
(1)题目附件是一个照片;先用010看一下;发现了两串16进制数;转为字符看一下
f09e54c1bad2x38mvyg7wzlsuhkijnop 和905e4c1fax328mdyvg7wbsuhklijznop;根据题目提示知道了前序序列和中序列;现在需要算出后序
# f09e54c1bad2x38mvyg7wzlsuhkijnop
# 905e4c1fax328mdyvg7wbsuhklijznop
def fromFMtoL( mid ):
global las #全局后序遍历
global fir #先序遍历
root = fir[0] #取出当前树根
fir = fir[1:] #取出树根后 先序遍历把根拿出来 下面一个元素做树根
root_po = mid.find( root ) #在中序遍历当中树根的位置
left = mid[0:root_po] #左子树
right = mid[root_po+1:len(mid)] #右子树
'''
后序遍历: 左 右 根
先左子树 再右子树 最后跟
'''
#有左子树的时候
if len(left) > 0:
fromFMtoL( left )
#有右子树的时候
if len(right) > 0:
fromFMtoL( right )
#树根写进结果
las += root
if __name__ == "__main__" :
# fir = input("请输入先序遍历:") #前序遍历的结果
# mid = input("请输入中序遍历:") #中序遍历的结果
fir = "f09e54c1bad2x38mvyg7wzlsuhkijnop"
mid = "905e4c1fax328mdyvg7wbsuhklijznop"
# fir = "ABC"
# mid = "BAC"
las = ""
fromFMtoL( mid )
print(las)
5、[BJDCTF 2nd]签到-y1ng
考点:真的签到题目
题解:直接base64解密就行
6、[GUET-CTF2019]Uncle Sam
考点:RS-Schmidt-Samoa密码系统
(1)==n=p^2q == dn=1mod(p-1)(p-1)
推导可以算出pq=gcd(a^N*d-an);算出pq;就可以解密出m;直接上exp
from gmpy2 import*
from libnum import*
N =
#N = p^2*q
d =
c =
pq = gcd(pow(2,d*N,N)-2,N)
m = pow(c,d,pq)
print(n2s(m))
7、[NCTF2019]Reverse
考点:三重DES pydes模块解密
题解:参考链接
(1)题目:
汮S賳!Ⅳ?Z_l,?漋& hDa莸&5匼?oZ€|U€骸%#}巴
import os
import pyDes
flag = "NCTF{******************************************}"
key = os.urandom(8)
d = pyDes.des(key)
cipher = d.encrypt(flag.encode())
with open('cipher', 'wb') as f:
f.write(cipher)
# Leak: d.Kn[10] == [0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1]
解密
from base64 import b64decode
from itertools import product
from DES import * # https://github.com/soreatu/Cryptography/blob/master/DES.py
guess_8bit = list(product(range(2), repeat=8))
not_in_PC2 = [9,18,22,25,35,38,43,54]
def re_PC2(sbkey):
# 48-bit -> 56-bit
res = [0]*56
for i in range(len(sbkey)):
res[PC_2_table[i]-1] = sbkey[i]
return res # ok
def guess_CiDi10(sbkey, t):
res = re_PC2(sbkey)
for i in range(8):
res[not_in_PC2[i]-1] = guess_8bit[t][i]
return res # ok
def guess_allsbkey(roundkey, r, t):
sbkey = [[]]*16
sbkey[r] = roundkey
CiDi = guess_CiDi10(roundkey, t)
Ci, Di = CiDi[:28], CiDi[28:]
for i in range(r+1,r+16):
Ci, Di = LR(Ci, Di, i%16)
sbkey[i%16] = PC_2(Ci+Di)
return sbkey # ok
def long_des_enc(c, k):
assert len(c) % 8 == 0
res = b''
for i in range(0,len(c),8):
res += DES_enc(c[i:i+8], k)
return res
def try_des(cipher, roundkey):
for t in range(256):
allkey = guess_allsbkey(roundkey, 10, t)
plain = long_des_enc(cipher, allkey[::-1])
if plain.startswith(b'NCTF'):
print(plain)
if __name__ == "__main__":
cipher = b64decode(b'm0pT2YYUIaL0pjdaX2wsxwedViYAaBkZA0Rh3bUmNYVclBlvWoB8VYC6oSUjfbDN')
sbkey10 = [0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1]
try_des(cipher, sbkey10)
# b'NCTF{1t_7urn3d_0u7_7h47_u_2_g00d_@_r3v3rs3_1snt}'
8、[Zer0pts2020]ROR
考点:对n取余二进制最后一位不变
chall=open('chall.txt').read().split()
mm=[]
for i in chall:
mm.append(int(i))
m=''
for i in mm:
m+=bin(i)[-1]
from Crypto.Util.number import long_to_bytes
m=int(m[::-1],2)
print(long_to_bytes(m))
9、[NewStarCTF 2023 公开赛道]babyrsa
题解:rsa
题解:
(1)分解n分解出11个因子;也就是phi的就算不同
import gmpy2
from Crypto.Util.number import long_to_bytes
# 给定的参数
n = 17290066070594979571009663381214201320459569851358502368651245514213538229969915658064992558167323586895088933922835353804055772638980251328261
e = 65537
c = 14322038433761655404678393568158537849783589481463521075694802654611048898878605144663750410655734675423328256213114422929994037240752995363595
# 分解出的因子
P1 = 3207148519
P2 = 2217990919
P3 = 2370292207
P4 = 3654864131
P5 = 2970591037
P6 = 3939901243
P7 = 2338725373
P8 = 2463878387
P9 = 2923072267
P10 = 2706073949
P11 = 3831680819
P12 = 4278428893
P13 = 2804303069
P14 = 4093178561
P15 = 2794985117
# 计算 phi(n)
phi = 1
for p in [P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15]:
phi *= (p - 1)
# 计算私钥 d
d = gmpy2.invert(e, phi)
# 解密密文
m = pow(c, d, n)
# 将解密结果转换为字节
plaintext = long_to_bytes(m)
print(plaintext)
10、[V&N2020 公开赛]easy_RSA
考点:RSA-光滑数求解
题解:从公式可以得知需求出p,q,r,然后逆元出di,从而解出c,m,直接看代码
from Crypto.Util.number import *
from primefac import *
import gmpy2
from sympy import *
n=7941371739956577280160664419383740967516918938781306610817149744988379280561359039016508679365806108722198157199058807892703837558280678711420411242914059658055366348123106473335186505617418956630780649894945233345985279471106888635177256011468979083320605103256178446993230320443790240285158260236926519042413378204298514714890725325831769281505530787739922007367026883959544239568886349070557272869042275528961483412544495589811933856131557221673534170105409
d = 7515987842794170949444517202158067021118454558360145030399453487603693522695746732547224100845570119375977629070702308991221388721952258969752305904378724402002545947182529859604584400048983091861594720299791743887521228492714135449584003054386457751933095902983841246048952155097668245322664318518861440
cipher = 1618155233923718966393124032999431934705026408748451436388483012584983753140040289666712916510617403356206112730613485227084128314043665913357106301736817062412927135716281544348612150328867226515184078966397180771624148797528036548243343316501503364783092550480439749404301122277056732857399413805293899249313045684662146333448668209567898831091274930053147799756622844119463942087160062353526056879436998061803187343431081504474584816590199768034450005448200
e = 0x10001
# 1. 通过光滑数得到p,光滑数求解因子恰好为505bit位的参数p,继续用光滑数向下求解q,r会发现非常慢,可以通过已知条件求解q和r
p = williams_pp1(n)
# 得知505bit位的p
# 2. 继续通过d对p^2的逆元求解出q^2 mod p^2,但这里不是唯一解,因为p^2非素数,所以就要考虑用nthroot求解出q
# 即公式 q_2 = q ^ 2 mod p ^ 2;这里尝试通过暴力枚举k参也能得出q;
q_2 = gmpy2.invert(d, p ** 2)
# Find the solutions to ``x**n = a mod m`` when m is not prime.
q = nthroot_mod(q_2, 2, p ** 2)
# 3. 求得r
r = n // p // q
# 4. 继续逆元求解出c
fin = (p-1)*(q-1)*(r-1)
di = gmpy2.invert(e, fin)
c = gmpy2.powmod(cipher, di, n)
#5. nthroot求解出m
m = nthroot_mod(c, 2, r)
print(long_to_bytes(m))
#b'flag{fd462593-25e4-4631-a96a-0cd5c72b2d1b}'