前言
总而言之,言而总之,就是被爆鲨X﹏X
长路漫漫
1.md5-1
题目:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50from hashlib import md5
flag='UNCTF{%s}'%md5('x'.encode()).hexdigest()
# x不是一个字符是n个字符
for i in flag:
with open('out.txt','a')as file:
file.write(md5(i.encode()).hexdigest()+'\n')
'''
4c614360da93c0a041b22e537de151eb
8d9c307cb7f3c4a32822a51922d1ceaa
0d61f8370cad1d412f80b84d143e1257
b9ece18c950afbfa6b0fdbfa4ff731d3
800618943025315f869e4e1f09471012
f95b70fdc3088560732a5ac135644506
e1671797c52e15f763380b45e841ec32
c9f0f895fb98ab9159f51fd0297e236d
a87ff679a2f3e71d9181a67b7542122c
8fa14cdd754f91cc6554c9e71929cce7
e1671797c52e15f763380b45e841ec32
8277e0910d750195b448797616e091ad
cfcd208495d565ef66e7dff9f98764da
c81e728d9d4c2f636f067f89cc14862c
c9f0f895fb98ab9159f51fd0297e236d
92eb5ffee6ae2fec3ad71c777531578f
45c48cce2e2d7fbdea1afc51c7c6ad26
cfcd208495d565ef66e7dff9f98764da
a87ff679a2f3e71d9181a67b7542122c
1679091c5a880faf6fb5e6087eb1b2dc
8fa14cdd754f91cc6554c9e71929cce7
4a8a08f09d37b73795649038408b5f33
cfcd208495d565ef66e7dff9f98764da
e1671797c52e15f763380b45e841ec32
c9f0f895fb98ab9159f51fd0297e236d
8fa14cdd754f91cc6554c9e71929cce7
cfcd208495d565ef66e7dff9f98764da
c9f0f895fb98ab9159f51fd0297e236d
cfcd208495d565ef66e7dff9f98764da
e1671797c52e15f763380b45e841ec32
45c48cce2e2d7fbdea1afc51c7c6ad26
1679091c5a880faf6fb5e6087eb1b2dc
e1671797c52e15f763380b45e841ec32
8f14e45fceea167a5a36dedd4bea2543
c81e728d9d4c2f636f067f89cc14862c
c4ca4238a0b923820dcc509a6f75849b
c9f0f895fb98ab9159f51fd0297e236d
a87ff679a2f3e71d9181a67b7542122c
cbb184dd8e05c9709e5dcaedaa0495cf
'''
根据代码可以知道是将某一字符串MD5后再对 “UNCTF{字符串MD5结果}” 这一字符串中的每一个字符进行MD5并且输出。因为MD5结果中的字符种类有限,因此将每一个字符MD5后的结果存储,最终查表即可。
1 | import hashlib |
2.md5-2
题目:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59from hashlib import md5
flag='UNCTF{%s}'%md5('x'.encode()).hexdigest()
# x不是一个字符是n个字符
md5_=[]
for i in flag:
md5_.append(int(md5(i.encode()).hexdigest(),16))
print(md5_)
for i in range(0,len(md5_)):
if i==0:
with open('out.txt','a')as file:
file.write(hex(md5_[i])[2:]+'\n')
else:
with open('out.txt','a')as file:
file.write(hex(md5_[i]^md5_[i-1])[2:]+'\n')
'''
4c614360da93c0a041b22e537de151eb
c1fd731c6d60040369908b4a5f309f41
80fdc84bbb5ed9e207a21d5436efdcfd
b48d19bb99a7e6bb448f63b75bc92384
39eaf918a52fcaa5ed9195e546b021c1
795d6869f32db43ff5b414de3c235514
f59a054403f933c842e9c3235c136367
c80b37816048952a3c0fc9780602a2fa
810ecef68e945c3fe7d6accba8b329bd
cad06891e0c769c7b02c228c8c2c8865
470a96d253a639193530a15487fea36f
470a96d253a639193530a15487fea36f
4bdea6676e5335f857fa8e47249fa1d8
810ecef68e945c3fe7d6accba8b329bd
edbb7ab78cde98a07b9b5a2ab284bf0a
44b43e07e9af05e3b9b129a287e5a8df
a641c08ed66b55c9bd541fe1b22ce5c0
abed1f675819a2c0f65c9b7da8cab301
738c486923803a1b59ef17329d70bbbd
7e209780adf2cd1212e793ae8796ed7c
a641c08ed66b55c9bd541fe1b22ce5c0
a641c08ed66b55c9bd541fe1b22ce5c0
636a84a33e1373324d64463eeb8e7614
6ec65b4ab061843b066cc2a2f16820d5
a4a39b59eb036a4a8922f7142f874114
8c34745bd5b5d42cb3efe381eeb88e4b
5b1ba76b1d36847d632203a75c4f74e2
d861570e7b9998dbafb38c4f35ba08bc
464b7d495dc6019fa4a709da29fc7952
8eb69528cd84b73d858be0947f97b7cc
dd6ac4c783a9059d11cb0910fc95d4a
4b6b0ee5d5f6b24e6898997d765c487c
b0762bc356c466d6b2b8f6396f2e041
8547287408e2d2d8f3834fc1b90c3be9
82947a7d007b9854fa62efb18c9fd91f
8ddafe43b36150de851c83d80bd22b0a
c7b36c5f23587e285e528527d1263c8b
2a0816e8af86e68825c9df0d63a28381
63ce72a42cf62e6d0fdc6c96df4687e3
'''
和md5-1差不多,只是从第二个字符开始,每一个字符对应的输出结果变成了当前字符的MD5值和前一个的异或,根据异或的性质: a^a=0, a^0=a,将从第二个开始的每一个值与前一个异或后再查表即可。
1 | import hashlib |
3.dddd
题目:
1 | 110/01/0101/0/1101/0000100/0100/11110/111/110010/0/1111/ |
根据题目名字以及所给txt可知为摩斯码,再根据 “110” 表示的是 “U” 可知
0代表的是 -,1代表的是 .,直接解码即可。
4.caesar
题目:
1 | 我把表换成了base64的表 |
凯撒密码, 题目已经说明将表替换成了base64的表,base64的表是 26个大写字母 + 26个小写字母 + 10个数字 + “+/” 找到偏移量,还原即可。
1 | import string |
5.Single table
题目:
1 | ABCDEFGHIKLMNOPQRSTUVWXYZ |
Playfair密码
根据给的文档提示可知规则如下:
- table为5*5矩阵,其中I和J合并,密钥放置到最后,其它非密钥字符按行排列。
- 明文到密文的转换规则为:
- 先将明文两个两个分组,其中特殊符号不参与分组,最后一组不够两个字符时使用 X 字符填充。
- 如果一个分组中的两个字符在同一行,则将两个字符分别右移一位作为密文。(一行中最后一个字符的右移看作是该行最左边的字符。)
- 如果一个分组中的两个字符在同一列,则将两个字符分别下移一位作为密文。(一列中最后一个字符的下移看作是该列最上边的字符。)
- 如果一个分组中的两个字符不在同一行也不在同一列,则取以这两个字符作为对角线的矩形的另外一条对角线上的字符,密文中两个字符的顺序根据明文中两个字符的顺序确定,密文第一个字符为明文第一个字符的同列字符,第二个字符为明文第二个字符的同列字符。
因此根据此规则逆向解密即可。
- table为5*5矩阵,其中I和J合并,密钥放置到最后,其它非密钥字符按行排列。
密文到明文的转换规则为:
- 先将密文两个两个分组,其中特殊符号不参与分组。
- 如果一个分组中的两个字符在同一行,则将两个字符分别左移一位作为密文。(一行中第一个字符的左移看作是该行最右边的字符。)
- 如果一个分组中的两个字符在同一列,则将两个字符分别上移一位作为密文。(一列中第一个字符的上移看作是该列最下边的字符。)
- 如果一个分组中的两个字符不在同一行也不在同一列,则取以这两个字符作为对角线的矩形的另外一条对角线上的字符,明文中两个字符的顺序根据密文中两个字符的顺序确定,明文第一个字符为密文第一个字符的同列字符,第二个字符为密文第二个字符的同列字符。
- 最后一个字母如果解出来是 X 则可能需要将其去除。
最后再加上下划线即可。
1
2
3
4
5
6
7
8
9
10
11
12
13key="PLAY"
table=
[
B C D E F
G H I K M
N O Q R S
T U V W X
Z P L A Y
]
ciphertext = OTUBM{BCQ_SPH_WOQA_UAYFMKLWS}
OT UB MB CQ SP HW OQ AU AY FM KL WS
UN CT FG OD YO UK ON WP LA YF AI RX
plaintext = UNCTF{GOD_YOU_KNOW_PLAYFAIR}
6.babyRSA
题目:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21from Crypto.Util.number import *
from secret import flag
import libnum
flag="UNCTF{*************************}"
m=libnum.s2n(flag)
p=libnum.generate_prime(1024)
q=libnum.generate_prime(1024)
n=p*q
e=6
c=pow(m,e,n)
M=((m>>60)<<60)
print("n=",n)
print("c=",c)
print("((m>>60)<<60)=",M)
'''
25300208242652033869357280793502260197802939233346996226883788604545558438230715925485481688339916461848731740856670110424196191302689278983802917678262166845981990182434653654812540700781253868833088711482330886156960638711299829638134615325986782943291329606045839979194068955235982564452293191151071585886524229637518411736363501546694935414687215258794960353854781449161486836502248831218800242916663993123670693362478526606712579426928338181399677807135748947635964798646637084128123883297026488246883131504115767135194084734055003319452874635426942328780711915045004051281014237034453559205703278666394594859431
15389131311613415508844800295995106612022857692638905315980807050073537858857382728502142593301948048526944852089897832340601736781274204934578234672687680891154129252310634024554953799372265540740024915758647812906647109145094613323994058214703558717685930611371268247121960817195616837374076510986260112469914106674815925870074479182677673812235207989739299394932338770220225876070379594440075936962171457771508488819923640530653348409795232033076502186643651814610524674332768511598378284643889355772457510928898105838034556943949348749710675195450422905795881113409243269822988828033666560697512875266617885514107
11941439146252171444944646015445273361862078914338385912062672317789429687879409370001983412365416202240
'''
小指数攻击
M只有343位,加密后的n最多2058位,爆破即可。
1 | import gmpy2 |
7.ezRSA
题目:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21import libnum
p=libnum.generate_prime(256)
e=65537
m=flag
m=libnum.s2n(m)
n=p**4
phi_n=p**4-p**3
d=libnum.invmod(e,phi_n)
c=pow(m,e,n)
print ("n=",n)
print ("e=",e)
print ("c=",c)
'''
n = 62927872600012424750752897921698090776534304875632744929068546073325488283530025400224435562694273281157865037525456502678901681910303434689364320018805568710613581859910858077737519009451023667409223317546843268613019139524821964086036781112269486089069810631981766346242114671167202613483097500263981460561
e = 65537
c = 56959646997081238078544634686875547709710666590620774134883288258992627876759606112717080946141796037573409168410595417635905762691247827322319628226051756406843950023290877673732151483843276348210800329658896558968868729658727981445607937645264850938932045242425625625685274204668013600475330284378427177504
'''
n = p^4, 直接将p解出即可。(phi还直接白给了…)1
2
3
4
5
6
7
8
9
10from Crypto.Util.number import *
import gmpy2
n = 62927872600012424750752897921698090776534304875632744929068546073325488283530025400224435562694273281157865037525456502678901681910303434689364320018805568710613581859910858077737519009451023667409223317546843268613019139524821964086036781112269486089069810631981766346242114671167202613483097500263981460561
e = 65537
c = 56959646997081238078544634686875547709710666590620774134883288258992627876759606112717080946141796037573409168410595417635905762691247827322319628226051756406843950023290877673732151483843276348210800329658896558968868729658727981445607937645264850938932045242425625625685274204668013600475330284378427177504
p, op = gmpy2.iroot(n, 4)
phi = p**4 - p**3
d = inverse(e, phi)
m = pow(c, d, n)
print(long_to_bytes(m))
8.今晚吃什么
题目:
1 | 10000 10000 10000 00000 10000 00000 10000 10000 10000 10000 |
打开txt,只有两种字符“10000” 和 “00000”,二元编码。根据标题以及二元以及五个字符为一组推测为培根密码。
将“10000”视作A,“00000”视作B,即可解码。
9.easy_RSA
题目:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22from Crypto.Util.number import *
from gmpy2 import *
from secret import flag
import random
assert flag.startwith(b"flag{")
e=0x10001
c=6423951485971717307108570552094997465421668596714747882611104648100280293836248438862138501051894952826415798421772671979484920170142688929362334687355938148152419374972520025565722001651499172379146648678015238649772132040797315727334900549828142714418998609658177831830859143752082569051539601438562078140
n=102089505560145732952560057865678579074090718982870849595040014068558983876754569662426938164259194050988665149701199828937293560615459891835879217321525050181965009152805251750575379985145711513607266950522285677715896102978770698240713690402491267904700928211276700602995935839857781256403655222855599880553
m=bytes_to_long(flag)
p=getPrime(512)
q=getPrime(512)
n=p*q
c=pow(m,e,n)
print("n={}".format(n))
print("c={}".format(c))
tmp=random.randint(100,300)
print("p>>tmp={}".format(p>>tmp))
#c=6423951485971717307108570552094997465421668596714747882611104648100280293836248438862138501051894952826415798421772671979484920170142688929362334687355938148152419374972520025565722001651499172379146648678015238649772132040797315727334900549828142714418998609658177831830859143752082569051539601438562078140
#n=102089505560145732952560057865678579074090718982870849595040014068558983876754569662426938164259194050988665149701199828937293560615459891835879217321525050181965009152805251750575379985145711513607266950522285677715896102978770698240713690402491267904700928211276700602995935839857781256403655222855599880553
#p>>200=8183408885924573625481737168030555426876736448015512229437332241283388177166503450163622041857
已知p的高位,使用Coppersmith算法进行高位攻击,用Sage求解。
详见 Coppersmith 相关攻击
对RSA-Factoring with High Bits Known理解1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24from sage.all import *
import binascii
n = 102089505560145732952560057865678579074090718982870849595040014068558983876754569662426938164259194050988665149701199828937293560615459891835879217321525050181965009152805251750575379985145711513607266950522285677715896102978770698240713690402491267904700928211276700602995935839857781256403655222855599880553
p4 = 8183408885924573625481737168030555426876736448015512229437332241283388177166503450163622041857
#已知的p的高位
cipher = 6423951485971717307108570552094997465421668596714747882611104648100280293836248438862138501051894952826415798421772671979484920170142688929362334687355938148152419374972520025565722001651499172379146648678015238649772132040797315727334900549828142714418998609658177831830859143752082569051539601438562078140
e = 0x10001
pbits = 512
#p原本的位数
kbits = pbits - p4.nbits()
p4 = p4 << kbits
PR.<x> = PolynomialRing(Zmod(n))
f = x + p4
roots = f.small_roots(X=2^kbits, beta=0.4)
if roots:
p = p4 + int(roots[0])
assert n % p == 0
q = n // p
phi = (p-1) * (q-1)
d = inverse_mod(e, phi)
flag = pow(cipher,d,n)
flag = hex(int(flag))[2:]
print binascii.unhexlify(flag)
10.Multi table
题目:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29from string import ascii_uppercase
from random import randint,shuffle
from binascii import b2a_hex,a2b_hex
flag="UNCTF{}"
base_table=list(ascii_uppercase)
# shuffle(base_table)
print(base_table)
table={}
for i in range(26):
table[i]=ascii_uppercase[i:]+ascii_uppercase[:i]
key=[]
for i in range(4):
key.append(randint(0,25))
print(key)
c=''
x=0
for i in range(len(flag)):
if flag[i] in ascii_uppercase:
c+=table[key[x%4]][base_table.index(flag[i])]
x+=1
else:
c+=flag[i]
print(c)
# ['J', 'X', 'I', 'S', 'E', 'C', 'R', 'Z', 'L', 'U', 'K', 'Q', 'Y', 'F', 'N', 'V', 'T', 'P', 'O', 'G', 'A', 'H', 'D', 'W', 'M', 'B']
# SDCGW{MPN_VHG_AXHU_GERA_SM_EZJNDBWN_UZHETD}
多表代替。
分析题目,key的长度为4,根据flag的前四个字符为“UNCT”可以算出key的四个值,加密的时候是根据key算出替换表,再根据字符在基表中的下标算出来密文字符,解密由于key的值已知,根据密文字符的下标反推出基表中的字符就好了。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25from string import ascii_uppercase
base_table = 'JXISECRZLUKQYFNVTPOGAHDWMB'
table={}
for i in range(26):
table[i]=ascii_uppercase[i:]+ascii_uppercase[:i]
s = 'SDCGW{MPN_VHG_AXHU_GERA_SM_EZJNDBWN_UZHETD}'
# for x in range(26):
# if table[x][base_table.index('U'/'N'/'C'/'T')] == 'S'/'D'/'C'/'G':
# print(x)
# 9 15 23 16
key = [9, 15, 23, 16]
res = ''
x = 0
for i in range(len(s)):
if s[i] in ascii_uppercase:
res += base_table[table[key[x % 4]].index(s[i])]
x += 1
else:
res += s[i]
print(res)
11.ezxor
题目:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31from key import m,flag
def xor(a, b):
return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b)])
def OPT(key,crypto):
ciphertext=xor(key,crypto)
return ciphertext
ls=[]
for i in range(11):
ls.append(m[i*42:(i+1)*42])
for x in ls:
k=OPT(flag,x).encode('hex')
print(k)
'''
1c2063202e1e795619300e164530104516182d28020005165e01494e0d
2160631d325b3b421c310601453c190814162d37404510041b55490d5d
3060631d325b3e59033a1252102c560207103b22020613450549444f5d
3420277421122f55067f1207152f19170659282b090b56121701405318
212626742b1434551b2b4105007f110c041c7f361c451e0a02440d010a
75222a22230877102137045212300409165928264c091f131701484f5d
21272d33661237441a7f005215331706175930254c0817091b4244011c
303c2674311e795e103a05520d300600521831274c031f0b160148555d
3c3d63232909355455300752033a17175e59372c1c0056111d01474813
752b22272f1e2b10063e0816452b1e041c593b2c02005a450649440110
396e2f3d201e795f137f07130c2b1e450510332f4c08170e17014d481b
'''
这题就得边写边猜了。
分析题目可知,flag作为“掩码”每次和消息m的若干个字节进行异或并输出,flag的前几个字符为“UNCTF{”是已知的,就拿这串字符作为“掩码”去和输出异或,看看明文m是什么,发现输出的明文是有意义的,就根据推测出来的明文的下一个字节计算出“掩码”的下一个字符,最终推出掩码的全部内容。下面的两个脚本同步进行。
1 | out = ['1c2063202e1e795619300e164530104516182d28020005165e01494e0d', |
例如,下图为上面的脚本中 s = ‘UNCTF{‘ 时输出的结果,根据输出的结果,推测出倒数第二个对应的明文应该为 ‘easier’,因此掩码的第7个字符与 ‘r’ 异或得到out中倒数第二个密文第七个字节的值,用 ‘r’ 与out中倒数第二个密文第七个字节的值异或即可得到掩码的第7个字符,以此类推…
1 | out = ['1c2063202e1e795619300e164530104516182d28020005165e01494e0d', |
12.Fermat
题目:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19from Crypto.Util.number import *
from gmpy2 import *
flag=b'UNCTF{}'
e=0x10001
p=getPrime(1024)
q=getPrime(1024)
n=p*q
m=bytes_to_long(flag)
c=pow(m,e,n)
x=getPrime(1024)
assert gift+x==x*p
print(n)
print(c)
print(gift)
# 19793392713544070457027688479915778034777978273001720422783377164900114996244094242708846944654400975309197274029725271852278868848866055341793968628630614866044892220651519906766987523723167772766264471738575578352385622923984300236873960423976260016266837752686791744352546924090533029391012155478169775768669029210298020072732213084681874537570149819864200486326715202569620771301183541168920293383480995205295027880564610382830236168192045808503329671954996275913950214212865497595508488636836591923116671959919150665452149128370999053882832187730559499602328396445739728918488554797208524455601679374538090229259
# 388040015421654529602726530745444492795380886347450760542380535829893454552342509717706633524047462519852647123869277281803838546899812555054346458364202308821287717358321436303133564356740604738982100359999571338136343563820284214462840345638397346674622692956703291932399421179143390021606803873010804742453728454041597734468711112843307879361621434484986414368504648335684946420377995426633388307499467425060702337163601268480035415645840678848175121483351171989659915143104037610965403453400778398233728478485618134227607237718738847749796204570919757202087150892548180370435537346442018275672130416574430694059
# 28493930909416220193248976348190268445371212704486248387964331415565449421099615661533797087163499951763570988748101165456730856835623237735728305577465527656655424601018192421625513978923509191087994899267887557104946667250073139087563975700714392158474439232535598303396614625803120915200062198119177012906806978497977522010955029535460948754300579519507100555238234886672451138350711195210839503633694262246536916073018376588368865238702811391960064511721322374269804663854748971378143510485102611920761475212154163275729116496865922237474172415758170527875090555223562882324599031402831107977696519982548567367160
考查费马定理
从上面的推导可以看出,pow(c, gift, n) 的结果为p的整数倍,又因为c的值我们可以选择多个,因此取两个c值求出两个结果tmp1,tmp2,并求出gcd(tmp1, tmp2),gcd一定为p的倍数,再对p的位数进行初步的判断即可得到p。
1 | from Crypto.Util.number import * |
13.Today_is_Thursday_V_me_50
题目:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37import random
import itertools
from Crypto.Util.number import *
from Crypto.Util.strxor import strxor
from flag import flag
name = "unctf"
key1 = TOPIC
key1 = b'Today_is_Thursday_V_me_50'
key1_num = bytes_to_long(key1)
def encrypt_1(message,name):
res = message
guess=[i for i in itertools.permutations(name, 5)]
for i in range(4):
what = guess.pop(50)
name = ''.join(j for j in what)
mask = strxor(5*name.encode(),key1)
res = strxor(mask,message)
return res
def encrypt_2(message,num):
random.seed(num)
res_2 = b''
for i in message:
temp_num = random.randint(1,128)
res_2 += long_to_bytes(temp_num ^ i)
return res_2
if __name__ == '__main__':
x = encrypt_2(encrypt_1(flag,name),key1_num)
print(x)
# b'Q\x19)T\x18\x1b(\x03\t^c\x08QiF>Py\x124DNg3P'
分析代码可知,全是异或操作,name已知,key1_num(随机数种子)已知,再异或一遍结果就出来了。唯一需要注意的就是把key1换成题目的25个字符。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41import random
import itertools
from Crypto.Util.number import *
from Crypto.Util.strxor import strxor
# from flag import flag
name = "unctf"
# key1 = TOPIC
key1 = b'Today_is_Thursday_V_me_50'
key1_num = bytes_to_long(key1)
cipher = b'Q\x19)T\x18\x1b(\x03\t^c\x08QiF>Py\x124DNg3P'
def encrypt_1(message,name):
res = message
guess=[i for i in itertools.permutations(name, 5)]
for i in range(4):
what = guess.pop(50)
name = ''.join(j for j in what)
mask = strxor(5*name.encode(),key1)
res = strxor(mask,message)
return res
def encrypt_2(message,num):
random.seed(num)
res_2 = b''
for i in message:
temp_num = random.randint(1,128)
res_2 += long_to_bytes(temp_num ^ i)
return res_2
if __name__ == '__main__':
# x = encrypt_2(encrypt_1(flag,name),key1_num)
# print(x)
res = encrypt_1(encrypt_2(cipher, key1_num), name)
print(res)
# b'Q\x19)T\x18\x1b(\x03\t^c\x08QiF>Py\x124DNg3P'
# b'unctf{1_l0ve_Thurs4Ay!!!}'
14.EZcry
题目:
1 | enc ->282158061343175228835964192208256575114110067106646494628420 |
给了密文以及密钥,大概率是对称加密。先把enc和key转换为字节,看看长度以及是否有提示内容。
转换后key是“12345678”,长度为8字节64位,明文内容不可读,长度为38字节,这里的38字节不能整除8。
首先使用DES对密文任意填充2字节,解密无果,考虑流密码。
使用RC4解密得到明文。
15.easy_lfsr
题目:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27from Crypto.Util.number import *
import random
import os
def lfsr(R, mask):
output = (R << 1) & lengthmask
i = (R & mask) & lengthmask
lastbit = 0
while i != 0:
lastbit ^= (i & 1)
i >>= 1
output ^= lastbit
return (output, lastbit)
length = 512
lengthmask = 2 ** length - 1
flag = b'flag{**********************}'
pad = os.urandom((length - len(flag) * 8) // 8)
mask = bytes_to_long(flag + pad)
R = random.getrandbits(length)
print(f'r1 = {R}')
for _ in range(length):
R,out = lfsr(R,mask)
print(f'r2 = {R}')
# r1 = 1261758973831852037364036680281442789461569523587512977925542995725854499352478233840720068310447535900840104847512878006505600998481136843381903570688446
# r2 = 1563853949934744587783542352813857485182445023523734908403585490477271641971239139925690033798570364214960692427704824920072270819031456154655408096237757
线性反馈移位寄存器。详情可查看详解线性反馈移位寄存器(LFSR)
给了寄存器的初始状态和经过512轮后的状态,让我们求反馈函数。
设r1从高位到低位的512位分别是(a0, a1, … , a511)
mask从高位到低位的512位分别是(c0, c1, … , c511)
分析 lfsr 函数,则可以得到以下等式
</br>
两个矩阵我们都是知道的,因此在GF(2)上求逆矩阵并与右边矩阵左乘即可得到mask,进而求出flag。本题我是用MATLAB求解的。(矩阵太大了…贴图吧)
矩阵生成:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26from Crypto.Util.number import *
R = 1261758973831852037364036680281442789461569523587512977925542995725854499352478233840720068310447535900840104847512878006505600998481136843381903570688446
R2 = 1563853949934744587783542352813857485182445023523734908403585490477271641971239139925690033798570364214960692427704824920072270819031456154655408096237757
s1 = bin(R)[2:].zfill(512)
s2 = bin(R2)[2:].zfill(512)
matrix = []
for i in range(512):
matrix.append([])
matrix[i] = s1[i:512:1] + s2[0:i:1]
matrix[i] = ','.join(matrix[i])
# for i in range(512):
# print('[', end='')
# print(matrix[i], end='')
# print(']')
# res = ','.join(s2)
# print(res)
ans = '01100110011011000110000101100111011110110011000000111001011001000110010100110100001101000110001001100101001011010011010101100010001100110110010000101101001100010011000101100101011001000010110101100010001101110011011000110100001011010110000101100011001100010011001000110000001100110110000101100010001100010011010001100100001101110111110110110000011101100110011101100110100101101101111101100000011101101100011001100100010000000001010011110111100110001010111110101100001001111111100001001011101110110010101100000000'
flag = 0
for i in ans:
flag = (flag << 1) + int(i)
print(long_to_bytes(flag))
- 本文作者: nYapn
- 本文链接: http://nYapn.github.io/2022/11/22/2022-UNCTF-Crypto/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!