用Python解决ctf中常见的栅栏密码和凯撒密码
2015-12-01
事情的缘由是最近做了几场ctf比赛,看到有凯撒密码和栅栏密码,便用Python尝试了一下,发现还是蛮好使的,无所不能的Python。
IDF实验室–聪明的小羊
一只小羊跳过了栅栏,两只小样跳过了栅栏,一坨小羊跳过了栅栏...
tn c0afsiwal kes,hwit1r g,npt ttessfu}ua u hmqik e {m, n huiouosarwCniibecesnren.
这道题目已经明显的提示了是栅栏密码的题目,关于栅栏密码可以看这里。
大体思路就是将你的明文按行排列起来,然后按列读取密文,就像明文Baby,I Love You Forever!
,按两行排列起来就是:
Baby,I Love
You Forever!
所以从上往下一列一列的读取就是BYaobuy ,FIo rLeovveer !
。
这样的密文拿到之后我们先找到它的所有公因数,然后分别按它的公因数排成相应的行数,找到其中的一个最有意义的就是明文了。
不过如果仅是这样的话,那么有什么样的结果还要靠眼睛来寻找就太慢了,如果是在ctf比赛中,一般的flag都是有一定的规格的,比如说XXXX{},那么,我们只要找到了XXXX就可以判断这个就是明文了。
按照这样的思路,在idf中的flag一般是wctf{XXXX},所以我们找到wctf即可,代码如下:
#coding=utf-8
data1 = "tn c0afsiwal kes,hwit1r g,npt ttessfu}ua u hmqik e {m, n huiouosarwCniibecesnren."
length = len(data1)
for i in xrange(2,length):
if length%i==0:
s = ""
for j in range(i):
for m in range(j,length,i):
s = s+data1[m]
if "wctf" in s:
print s
结果是the anwser is wctf{C01umnar},if u is a big new,u can help us think more question,tks
.
ZJPC-CTF
也是一道栅栏密码的题目,密文如下。
T IFCCH NONY AZCA_N_PRHRLEEIEIF CPFGJ{IFCCH!EA N PRSUTERTL.PRLEEIE}
但是这道题就非常坑爹了,它一共是67个字符,没有公因数,那么我们要删掉一定的空格或者全部的空格才可以了。
那没有办法,我们就只能先分别删掉它的每一个空格使其为66位,然后再来找了。
#coding=utf-8
def deletespace(data):
s = data.split(" ")
m = []
for i in range(1,len(s)):
l = ""
for j in range(len(s)):
if j==i:
l = l+s[j]
else:
l = l+" "+s[j]
l = l.strip()
m.append(l)
return m
data = "T IFCCH NONY AZCA_N_PRHRLEEIEIF CPFGJ{IFCCH!EA N PRSUTERTL.PRLEEIE}"
d = deletespace(data)
for data1 in d:
length = len(data1)
for i in xrange(2,length):
if length%i==0:
s = ""
for j in range(i):
for m in range(j,length,i):
s = s+data1[m]
if "ZJPC" in s:
print s
结果竟然跑出来两个,还好答案只有一个。
THE RAILNFE CEPCIRHES IUNFTO ENCRYPT FLAG.ZJPC{RAIL_FENCE_CIPHER!}
THE RAIL FENCEPCIRHES IUNFTO ENCRYPT FLAG.ZJPC{RAIL_FENCE_CIPHER!}
ZJPC-CTF
凯撒密码
AKQD{dbftbs_jt_hppe_cvu_Xfbl!}
凯撒密码源于古罗马帝王凯撒,因为他当年想出了这种加密方式,故一次命名,关于凯撒密码可以看这里。
原理也很简单,就是按照26个英文字母的顺序分别用这个字符的前面或者后面第多少位来替换,做如下对应。
ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz
DEFGHIJKLMNOPQRSTUVWXYZABC defghijklmnopqrstuvwxyzabc
那么还是原来的那个例子,明文Baby,I Love You Forever!
,那么密文就是Edeb,L Oryh Vrx Iruhyhu!
。
这样的话,拿到了密文之后,我们分别将它的每一个字符进行移位,找到最有意义的那个就是flag了,当然,在这里,我们也需要用有没有flag特定的字符来判断是不是找到了真正的flag。
按照上面的思路,但是这里有两个地方有点困难,就是特殊标记不予替换和替换超长轮回,代码如下:
#coding=utf-8
def ischar(i):
if i>='a' and i<='z':
return 1
elif i>='A' and i<='Z':
return 2
else:
return 0
def litcha(j,i):
if chr(ord(j)+i)>'z':
return chr(ord('a')+ord(j)+i-ord('z')-1)
else:
return chr(ord(j)+i)
def bigcha(j,i):
if chr(ord(j)+i)>'Z':
return chr(ord('A')+ord(j)+i-ord('Z')-1)
else:
return chr(ord(j)+i)
data = "AKQD{dbftbs_jt_hppe_cvu_Xfbl!}"
for i in range(26):
data1 = ""
for j in data:
if ischar(j)==1:
j = litcha(j,i)
elif ischar(j)==2:
j = bigcha(j,i)
else:
pass
data1 = data1+j
if "ZJPC" in data1:
print data1
显得稍微复杂了一点,不过结果还是成功出来了,明文是ZJPC{caesar_is_good_but_Weak!}
,凯撒密码的保护能力有限,也就这样了。
ZJPC-CTF
凯撒密码的加强版。
Task:
I guess you are done with Caesar, aren't you?
The big problem with caesar is that it does not allow digits or other characters.
I have fixed this, and now I can use any ascii character in the plaintext.
The keyspace has increased from 26 to 128 too. \o/
37 23 32 33 38 23 25 30 30 33 3b
23 28 2d 2b 2d 38 37 23 33 36 23
33 38 2c 29 36 23 27 2c 25 36 25
27 38 29 36 37 0d 23 2c 25 3a 29
23 2a 2d 3c 29 28 23 38 2c 2d 37
23 25 32 28 23 32 33 3b 23 0d 23
27 25 32 23 39 37 29 23 25 32 3d
23 25 37 27 2d 2d 23 27 2c 25 36
25 27 38 29 36 23 2d 32 23 38 2c
29 23 34 30 25 2d 32 38 29 3c 38
2a 30 25 2b 1e 0e 14 07 3f 3d 33
39 23 36 23 3b 2d 32 41
看着这些数字,猜测应该是十六进制,题目中也提示了,凯撒密码从单纯的英文字母转到了128的ASCII码,好吧,其实是更简单了好么。。。
先将十六进制转换为ASCII码,然后分别替换,代码如下:
#coding=utf-8
data = """
37 23 32 33 38 23 25 30 30 33 3b
23 28 2d 2b 2d 38 37 23 33 36 23
33 38 2c 29 36 23 27 2c 25 36 25
27 38 29 36 37 0d 23 2c 25 3a 29
23 2a 2d 3c 29 28 23 38 2c 2d 37
23 25 32 28 23 32 33 3b 23 0d 23
27 25 32 23 39 37 29 23 25 32 3d
23 25 37 27 2d 2d 23 27 2c 25 36
25 27 38 29 36 23 2d 32 23 38 2c
29 23 34 30 25 2d 32 38 29 3c 38
2a 30 25 2b 1e 0e 14 07 3f 3d 33
39 23 36 23 3b 2d 32 41
"""
data1 = data.replace(" ","")
data2 = data1.replace("\n","")
data3 = data2.decode("hex")
def chang(j,i):
if ord(j)+i >=128:
return chr(ord(j)+i-128)
else:
return chr(ord(j)+i)
for i in range(128):
l = ""
for j in data3:
j = chang(j,i)
l = l+j
if "ZJPC" in l:
print l
好了,大概就讲这么多了,这道题的结果是s_not_allow_digits_or_other_charactersI_have_fixed_this_and_now_I_can_use_any_ascii_character_in_the_plaintextflagZJPC{you_r_win}
。
Python 无所不能。
本文固定链接:https://windard.com/project/2015/12/01/Python-In-Ctf
原创文章,转载请注明出处:用Python解决ctf中常见的栅栏密码和凯撒密码 By Windard