下学期要求密码和Re,现在这俩几乎是空白,趁着暑假的功夫,最近也能闲下来,就学一学crypto
,其实真正接触发现挺有意思的,各种密码的加密千奇百怪,层出不穷,也是需要慢慢积累经验,花了一天时间把攻防世界的密码入门全做了,这里简单说一下自己做的时候的思路,顺便练习python…python实在没学好,自己太辣鸡了。。。一些特别基础的就带过来,就写一些自己还没那么熟悉的
JiM3NjsmIzEyMjsmIzY5OyYjMTIwOyYjNzk7JiM4MzsmIzU2OyYjMTIwOyYjNzc7JiM2ODsmIzY5OyYjMTE4OyYjNzc7JiM4NDsmIzY1OyYjNTI7JiM3NjsmIzEyMjsmIzEwNzsmIzUzOyYjNzY7JiMxMjI7JiM2OTsmIzEyMDsmIzc3OyYjODM7JiM1NjsmIzEyMDsmIzc3OyYjNjg7JiMxMDc7JiMxMTg7JiM3NzsmIzg0OyYjNjU7JiMxMjA7JiM3NjsmIzEyMjsmIzY5OyYjMTIwOyYjNzg7JiMxMDU7JiM1NjsmIzEyMDsmIzc3OyYjODQ7JiM2OTsmIzExODsmIzc5OyYjODQ7JiM5OTsmIzExODsmIzc3OyYjODQ7JiM2OTsmIzUwOyYjNzY7JiMxMjI7JiM2OTsmIzEyMDsmIzc4OyYjMTA1OyYjNTY7JiM1MzsmIzc4OyYjMTIxOyYjNTY7JiM1MzsmIzc5OyYjODM7JiM1NjsmIzEyMDsmIzc3OyYjNjg7JiM5OTsmIzExODsmIzc5OyYjODQ7JiM5OTsmIzExODsmIzc3OyYjODQ7JiM2OTsmIzExOTsmIzc2OyYjMTIyOyYjNjk7JiMxMTk7JiM3NzsmIzY3OyYjNTY7JiMxMjA7JiM3NzsmIzY4OyYjNjU7JiMxMTg7JiM3NzsmIzg0OyYjNjU7JiMxMjA7JiM3NjsmIzEyMjsmIzY5OyYjMTE5OyYjNzc7JiMxMDU7JiM1NjsmIzEyMDsmIzc3OyYjNjg7JiM2OTsmIzExODsmIzc3OyYjODQ7JiM2OTsmIzExOTsmIzc2OyYjMTIyOyYjMTA3OyYjNTM7JiM3NjsmIzEyMjsmIzY5OyYjMTE5OyYjNzc7JiM4MzsmIzU2OyYjMTIwOyYjNzc7JiM4NDsmIzEwNzsmIzExODsmIzc3OyYjODQ7JiM2OTsmIzEyMDsmIzc2OyYjMTIyOyYjNjk7JiMxMjA7JiM3ODsmIzY3OyYjNTY7JiMxMjA7JiM3NzsmIzY4OyYjMTAzOyYjMTE4OyYjNzc7JiM4NDsmIzY1OyYjMTE5Ow==
密码的题很多就是给你个txt,好评,上来给你一串字符,判断为base64
,那么先base64decode
一下,得到:
LzExOS8xMDEvMTA4Lzk5LzExMS8xMDkvMTAxLzExNi8xMTEvOTcvMTE2LzExNi85Ny85OS8xMDcvOTcvMTEwLzEwMC8xMDAvMTAxLzEwMi8xMDEvMTEwLzk5LzEwMS8xMTkvMTExLzExNC8xMDgvMTAw
解密之后还是base64
,在这里说一下base编码的特征
base64:
(1)在base64中的可打印字符包括字母A-Z、a-z、数字0-9,+ / =。
(2)永远是4的倍数,不足四的用=补齐。
base32:
base32中只有大写字母(A-Z)和数字234567
base16:
base16中只有数字0-9以及大写字母ABCDEF
继续base64decode
得到
/119/101/108/99/111/109/101/116/111/97/116/116/97/99/107/97/110/100/100/101/102/101/110/99/101/119/111/114/108/100
很明显的ascii码
主要为了练习练习py,每个题都写了exp
#coding=utf-8
import base64
cipher_ascii = '119/101/108/99/111/109/101/116/111/97/116/116/97/99/107/97/110/100/100/101/102/101/110/99/101/119/111/114/108/100'
cipher_ascii = cipher_ascii.replace('/',',')
cipher_list = list(map(int,cipher_ascii.split(',')))
lst = []
for num in cipher_list:
lst.append(chr(num))
plain = "".join(lst)
print('cyberpeace{'+plain+'}')
#cyberpeace{welcometoattackanddefenceworld}
考点是云影密码
此密码运用了1248代码
原理很简单,有了1,2,4,8
这四个简单的数字,你可以以加法表示出0-9任何一个数字,例如0=28,7=124,9=18
。 这样,再用1-26来表示A-Z,就可以用作密码了。 为了不至于混乱,我个人引入了第五个数字0,来用作间隔,以避免翻译错误,所以还可以称“01248密码”。 题目:12401011801180212011401804
第一步,分割,即124 1 118 118 212 114 18 4
第二步,基本翻译,例如124可以表示7,也可以表示16(但不可能是34,因为不会超过26),所以可以放在一边,翻译其他没有异议的, 可得:124 a s s w o 18 d
第三步,推测得出明文。可以推测后面的18表示r,前面的为p最合适。 明文:password(密码)
cipher
是8842101220480224404014224202480122
因此根据云影密码的原理,写个脚本:
#coding=utf-8
num_str = '8842101220480224404014224202480122'
num = num_str.replace('0',',')
num_list = num.split(',')
print(num_list)
lst = []
asc2 = 0
for i in range(len(num_list)):
for j in num_list[i]:
asc2 += int(j)
lst.append(asc2)
asc2 = 0
flag = ''
for i in lst:
flag+=chr(i+96)
print('cyberpeace{'+flag.upper()+'}')
#cyberpeace{WELLDONE}
给的提示很直白,连我这个小新手都知道是栅栏密码,给的密钥是5,这里说明一下栅栏密码加密方式:
即把将要传递的信息中的字母交替排成上下两行,再将下面一行字母排在上面一行的后边,从而形成一段密码。栅栏密码是一种置换密码。
例如密文:TEOGSDYUTAENNHLNETAMSHVAED
解密过程:先将密文分为两行
**T E O G S D Y U T A E N N
H L N E T A M S H V A E D ****
再按上下上下的顺序组合成一句话
THE LONGEST DAY MUST HAVE AN END.
进阶
密文为:
PFEE SESN RETM MFHA IRWE OOIG MEEN NRMA ENET SHAS DCNS IIAA IEER BRNK FBLE LODI
去掉空格:PFEESESNRETMMFHAIRWEOOIGMEENNRMAENETSHASDCNSIIAAIEERBRNKFBLELODI
共64个字符,以8个字符为一栏,排列成8*8的方阵(凯撒方阵):
P F E E S E S N R E T M M F H A I R W E O O I G M E E N N R M A E N E T S H A S D C N S I I A A I E E R B R N K F B L E L O D I
从上向下竖着读:PRIMEDIFFERENCEBETWEENELEMENTSRESMONSIBLEFORHIROSHIMAANDNAGASAKI
插入空格:PRIME DIFFERENCE BETWEEN ELEMENTS RESMONSIBLE FOR HIROSHIMA AND NAGASAKI
但是在这里,发现用栅栏密码怎么也得不到看着靠谱的flag
,才知道这是W型栅栏密码 举个简单例子
#同样一个字符串:123456789
key=3
1----5----9 #让数字以W型组织,同样是三组,但每组的数量不一定相同
-2--4-6--8
--3----7--
#加密密文:159246837
因此直接在线W型栅栏密码
,密钥是5,直接出flag了。
这里mark一个网站:http://www.atoolbox.net/Tool.php
RSA、DES这样的应该是密码学题目的常态,因此原理还是得弄清楚,RSA是基于数学难题的,这点上学期的课没有白听,大致地说,RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qhMG25Qn-1593442175638)(C:\Users\86189\AppData\Roaming\Typora\typora-user-images\image-20200629183902255.png)]
题目描述是
在一次RSA密钥对生成中,假设p=473398607161,q=4511491,e=17 求解出d
因此在这里我们的目的是先求出r=(p-1)*(q-1)
,然后找到e*d % r ==1
这个d就是所求,在这里使用gmpy2.invert求逆元
d = gmpy2.invert(e,n) # 求逆元,de = 1 mod n
贴下exp:
#coding=utf-8
import gmpy2
p=473398607161
q=4511491
e=17
phin = (p-1)*(q-1)
d = gmpy2.invert(e,phin)
d = str(d)
print('cyberpeace{'+d+'}') #RSA私钥即为d
#cyberpeace{125631357777427553}
这题的考点主要就是给了一个pyc
文件,也就是类似java的class文件
,只需要将其反编译即可得到py文件,发现就是一个编码,三重编码得到密文,因此只需要对应写好解码,在依次解码即可得到flag
mark反编译pyc网站: https://tool.lu/pyc/
贴出exp:
#!/usr/bin/env python
# encoding: utf-8
import base64
def encode1(ans):
s = ''
for i in ans:
x = ord(i) ^ 36
x = x + 25
s += chr(x)
return s
def decode1(ans):
s = ''
for i in ans:
x = ord(i)
x = x - 25
x = x ^ 36
s+= chr(x)
return s
def encode2(ans):
s = ''
for i in ans:
x = ord(i) + 36
x = x ^ 36
s += chr(x)
return s
def decode2(ans):
s = ''
for i in ans:
x = ord(i)
x = x ^ 36
x = x - 36
s += chr(x)
return s
def encode3(ans):
return base64.b32encode(ans)
def decode3(ans):
return base64.b32decode(ans)
final = 'UC7KOWVXWVNKNIC2XCXKHKK2W5NLBKNOUOSK3LNNVWW3E==='
#if encode3(encode2(encode1(flag))) == final:
print(decode1(decode2(decode3(final).decode('ISO-8859-1'))))
#cyberpeace{interestinghhhhh}
值得注意到是,这里编码还只能是ISO-8859-1
,因为如果是其他的,python会用\xx
来表示,这样一直会报错,经过多次尝试编码是ISO-8859-1
时,才能够正确解码。
题目描述是
2: < KPBELNACZDTRXMJQOYHGVSFUWI <
3: < BDMAIZVRNSJUWFHTEQGYXPLOCK <
4: < RPLNDVHGFCUKTEBSXQYIZMJWAO <
5: < IHFRLABEUOTSGJVDKCPMNZQWXY <
6: < AMKGHIWPNYCJBFZDRUSLOQXVET <
7: < GWTHSPYBXIZULVKMRAFDCEONJQ <
8: < NOZUTWDCVRJLXKISEFAPMYGHBQ <
9: < XPLTDSRFHENYVUBMCQWAOIKZGJ <
10: < UDNAJFBOWTGVRSCZQKELMXYIHP <
11: < MNBVCXZQWERTPOIUYALSKDJFHG <
12: < LVNCMXZPQOWEIURYTASBKJDFHG <
13: < JZQAWSXCDERFVBGTYHNUMKILOP <
密钥为:2,3,7,5,13,12,9,1,8,10,4,11,6
密文为:NFQKSEVOQOFNP
给的提示就是轮转机加密,这种加密还挺有意思,并且它要结合具体语义的,即在最后是选取有语义的一条为明文,结合题目来说
通过所给顺序排序 : 2,3,7,5,13,12,9,1,8,10,4,11,6
将排序后的第一个字符串移位,使得N在字符串首部
第二个字符串移位,使得F在字符串首部
依次按照下列所给提示排序
NFQKSEVOQOFNP
也就是先按数字把每行字符串排好序,在按照密钥把每行的字符串给换一下,二次排完后再找列中有具体语义的。
贴出exp:
#coding=utf-8
"""
密钥为:2,3,7,5,13,12,9,1,8,10,4,11,6
密文为:NFQKSEVOQOFNP
"""
key = "2,3,7,5,13,12,9,1,8,10,4,11,6"
cipher_text = "NFQKSEVOQOFNP"
file = open("C:\\Users\\86189\\Desktop\\1.txt",encoding='utf-8')
cipher_str = []
for line in file:
cipher_str.append(line.strip())
key_index = key.split(',')
cipher_nowstr = []
for index in key_index:
cipher_nowstr.append(cipher_str[int(index) - 1])
table = 0
cipher_last = []
for c in cipher_text:
str = cipher_nowstr[table]
num = str.index(c)
cipher_last.append(str[num:]+str[:num])
table+=1
flag = ''
for str in cipher_last:
flag += str[-9] #倒数第九列有具体语义
print('flag{'+flag.lower()+'}')
#fireinthehole
这个题恐怕是耗费我时间最多的一题,一直在配置python环境,头大。。。这里是推荐使用CTF-RSA-TOOLS
,但是导入的很多包都没有,因此开始漫长入坑路,终于在我的vps下配置好了,那我们开始看题。
题目给了一个公钥的pem
文件还有一个flag.enc
,但是flag.enc
是无法打开的,当我们知道公钥和密文后是能够根据公钥来破解密文的内容从而获得明文的。
此时,(N,e)(N,e) 是公钥,(N,d)(N,d) 是私钥
首先需要将消息 m 以一个双方约定好的格式转化为一个小于 N,且与 N 互质的整数 n。如果消息太长,可以将消息分为几段,这也就是我们所说的块加密,后对于每一部分利用如下公式加密:
n e n^e ne≡ c (modN)
利用密钥 d 进行解密。
c d c^d cd≡n(modN)
我们可以知道,RSA公钥主要有两个信息:模数(modulus)和指数(exponent),也就是我们所说的N和e。只要有了这两个信息,我们便可以生成公钥,然后使用rsa库对数据进行加密
kali中有openssl
能够对pem文件提取出其模数n和指数e
openssl rsa -pubin -text -modulus -in warmup -in pubkey.pem
当得到模数n时,通过对它的因数分解分别能得到p和q,当得到这俩数之后和e之后,便可以通过这五个数来构造RSA私钥对密文进行解密了,这里可以直接使用RSA_TOOLS
python2 solve.py -k ../pubkey.pem --decrypt ../flag.enc # -k指定公钥 --decrypt 指定解密文件
或者也可以通过脚本来解密:
先通过openssl
得到了模数和指数,在分解模数n得到p和q
#coding=utf-8
import gmpy2
import rsa
q = 275127860351348928173285174381581152299
p = 319576316814478949870590164193048041239
n = 87924348264132406875276140514499937145050893665602592992418171647042491658461
e = 65537
d = int(gmpy2.invert(e,(p-1)*(q-1)))
pri_key = rsa.PrivateKey(n,e,d,p,q)
f = open('C:\\Users\\86189\\Desktop\\547de1d50b95473184cd5bf59b019ae8\\flag.enc','rb')
print(rsa.decrypt(f.read(),pri_key))
#b'PCTF{256b_i5_m3dium}\n'