前言
写CTF题目总是会碰到很多需要解密的地方,比如常见的base家族和url编码转化,恰逢看到一些师傅的博客,受到启发利用python尝试实现了一下,目的是能够判断是base家族的什么加密方式并进行解密。然而期末将近未能实现目的,不过实现了一些加密解密功能,经过测试仍存在一些问题,在此进行分享学习。代码中已给出注释,可添加联系方式一起交流学习,期待你的建议与指导。
代码只是调用了一些标准库和第三方库(第三方库请自行进行下载(pip install xxxx)),容易理解且读者可自行添加自己所需要的功能。
python实现
# -*- coding:utf-8 -*-
import hashlib # 用于md5、sha1的加密解密
import base64 # base64、32、16,85的加密解密
# 需要注意的是base64自带的base85的加密解密对应base85四种种类里的两种
# python3中的a85encode --> ASCII85 encoding. This is the default. 0x00000000 is compressed to z. Spaces are not compressed.
# python3中的b85encode --> Character set from RFC1924 which is an April fools joke. Spaces and zeroes are not compressed.
# from urllib import quote, unquote
from urllib.parse import quote, unquote # quote进行url编码 , unquote进行url解码
import argparse # 编写用户友好的命令行接口
import base58 # 用于base58的加密解密
import base91 # 用于base91的加密解密
# import base92 #用于base92的加密解密 #由于下载不成功base92的库,所以暂时搁置
import base36 # 用于base36的加密解密
# import base62 #用于base62的加密解密 #由于下载不成功base62的库,所以暂时搁置
# import binascii
"""
名字:ctf_crypto_tool
作者:Force
时间:2020-11-24
QQ :1049453191
Wechat:ForcesWang
"""
def menu():
usage = """
-m MD5 encryption(32-bit lowercase)
-s SH1 encryption
-h Show help information
-b64 Base64 encode
-b32 Base32 encode
-b16 Base16 encode
-b85_1 Base85_1 encode
-b85_2 Base85_2 encode
-b36 Base36 encode
-b58 Base58 encode
-b91 Base91 encode
-db64 Base64 decode
-db32 Base32 decode
-db16 Base16 decode #可
-db85_1 Base85_1 decode
-db85_2 Base85_2 decode
-db36 Base36 decode
-db58 Base58 decode
-db91 Base91 decode
-urlen URL encode
-urlde URL decode
-bin Binary To Decimal #二进制到十进制
-octal Octal to Decimal #八进制到十进制
-hex Hexadecimal to Decimal #十六进制到十进制
-dbin Decimal To Binary #十进制到二进制
-doctal Decimal to Octal #十进制到八进制
-dhex Decimal to Hexadecimal #十进制到十六进制
-ord Letter To ASCII #字母到ASCII Example -ord asdfasfa -ord='dfafs afasfa asfasf'
-chr ASCII To Letters #ASCII到字母 Example -chr 105 -chr = '102 258 654'
"""
# 在使用ord 和chr命令的时候要注意如果输入的字符和数字不包含空格则直接实用例子前面的命令如果包含空格则使用后面的命令
parser = argparse.ArgumentParser()
parser.add_argument('-m', dest='md', help='MD5 encryption')
parser.add_argument('-s', dest='sh', help='SH1 encryption')
parser.add_argument('--h', action="store_true", help='Show help information')
parser.add_argument('-b64', dest='b64', help='Base64 encode')
parser.add_argument('-b32', dest='b32', help='Base32 encode')
parser.add_argument('-b16', dest='b16', help='Base16 encode')
parser.add_argument('-b85_1', dest='b85_1', help='Base85_1 encode')
parser.add_argument('-b85_2', dest='b85_2', help='Base85_2 encode')
parser.add_argument('-b36', dest='b36', help='Base36 encode')
parser.add_argument('-b58', dest='b58', help='Base58 encode')
parser.add_argument('-b91', dest='b91', help='Base91 encode')
parser.add_argument('-db64', dest='db64', help='Base64 decode')
parser.add_argument('-db32', dest='db32', help='Base32 decode')
parser.add_argument('-db16', dest='db16', help='Base16 decode')
parser.add_argument('-db85_1', dest='db85_1', help='Base85_1 decode')
parser.add_argument('-db85_2', dest='db85_2', help='Base85_2 decode')
parser.add_argument('-db36', dest='db36', help='Base36 decode')
parser.add_argument('-db58', dest='db58', help='Base58 decode')
parser.add_argument('-db91', dest='db91', help='Base91 decode')
# parser.add_argument('-dbfamily', dest='dbfamily', help='basefamily decode')
parser.add_argument('-urlen', dest='urlen', help='URL encode')
parser.add_argument('-urlde', dest='urlde', help='URL decode')
parser.add_argument('-bin', dest='bin', help='Binary To Decimal')
parser.add_argument('-octal', dest='octal', help='Octal to Decimal')
parser.add_argument('-hex', dest='hex', help='Hexadecimal to Decimal')
parser.add_argument('-dbin', dest='dbin', help='Decimal To Binary ')
parser.add_argument('-doctal', dest='doctal', help='Decimal to Octal ')
parser.add_argument('-dhex', dest='dhex', help='Decimal to Hexadecimal')
parser.add_argument('-ord', dest='ord',
help="Letter To ASCII Example -ord aaaaaa , -ord=\"aaa aaa\"")
parser.add_argument('-chr', dest='chr',
help="ASCII To Letter Example -chr 105 , -chr = \"101 101\" ")
options = parser.parse_args()
if options.md:
s = options.md
md5(s)
elif options.sh:
s = options.sh
sh1(s)
elif options.b64:
s = options.b64
stringToB64(s)
elif options.b32:
s = options.b32
stringToB32(s)
elif options.b16:
s = options.b16
stringToB16(s)
elif options.b85_1:
s = options.b85_1
stringTobase85_1(s)
elif options.b85_2:
s = options.b85_2
stringTobase85_2(s)
elif options.b36:
s = options.b36
stringTobase36(s)
elif options.b58:
s = options.b58
stringTobase58(s)
elif options.b91:
s = options.b91
stringTobase91(s)
elif options.db85_1:
s = options.db85_1
base85_1Tostring(s)
elif options.db85_2:
s = options.db85_2
base85_2Tostring(s)
elif options.db36:
s = options.db36
base36Tostring(s)
elif options.db58:
s = options.db58
base58Tostring(s)
elif options.db91:
s = options.db91
base91Tostring(s)
# elif options.dbfamily:
#
# s = options.dbfamily
#
# basefamily(s)
elif options.db64:
s = options.db64
b64ToString(s)
elif options.db32:
s = options.db32
b32ToString(s)
elif options.db16:
s = options.db16
b16ToString(s)
elif options.urlen:
s = options.urlen
urlEncode(s)
elif options.urlde:
s = options.urlde
urlDecode(s)
elif options.bin:
s = options.bin
binToDec(s)
elif options.octal:
s = options.octal
octToDec(s)
elif options.hex:
s = options.hex
hexToDec(s)
elif options.dbin:
s = options.dbin
decToBin(s)
elif options.doctal:
s = options.doctal
decToOct(s)
elif options.dhex:
s = options.dhex
decToHex(s)
elif options.doctal:
s = options.doctal
decToOct(s)
elif options.dhex:
s = options.dhex
decToHex(s)
elif options.ord:
s = options.ord
lettToASCII(s)
elif options.chr:
s = options.chr
asciiToLett(s)
else:
helpInfo()
def helpInfo():
print("""
-m MD5 encryption(32-bit lowercase)
-s SH1 encryption
-h Show help information
-b64 Base64 encode
-b32 Base32 encode
-b16 Base16 encode
-b85_1 Base85_1 encode
-b85_2 Base85_2 encode
-b36 Base36 encode
-b58 Base58 encode
-b91 Base91 encode
-db64 Base64 decode
-db32 Base32 decode
-db16 Base16 decode
-db85_1 Base85_1 decode
-db85_2 Base85_2 decode
-db36 Base36 decode
-db58 Base58 decode
-db91 Base91 decode
-urlen URL encode
-urlde URL decode
-bin Binary To Decimal
-octal Octal Decimal to Decimal
-hex Hexadecimal to Decimal
-dbin Decimal To Binary
-doctal Decimal to Octal
-dhex Decimal to Hexadecimal
-ord Letter To ASCII attention: Example -ord asdfasfa -ord="dfafs afasfa asfasf"
-chr ASCII To Letters attention: Example -chr 105 -chr="102 258 654"
""")
# 进行MD5加密
def md5(s):
original = s
md = hashlib.md5()
s = s.encode(encoding='utf-8')
md.update(s)
print('Original:' + original)
print('Md5 Encryption:' + md.hexdigest())
# 进行sh1加密
def sh1(s):
original = s
sh = hashlib.sha1()
# s = s.encode(encoding='utf-8')
print('Original:' + original)
print('SH1 Encryption:' + sh.hexdigest())
# 将字符串转换为base64编码格式
def stringToB64(s):
encode = base64.b64encode(s)
print('Original:' + s)
print('Base64 encode:' + str(encode))
# 将base64编码格式转化为正常的字符类型
def b64ToString(s):
decode = base64.b64decode(s)
# print('Base64:' + s)
print('Base64 decode:' + str(decode))
# 将字符串转为b32编码格式
def stringToB32(s):
encode = base64.b32encode(s)
print('Original:' + s)
print('Base32 encode:' + str(encode))
# 将base32编码格式转化为正常的字符类型
def b32ToString(s):
decode = base64.b32decode(s)
# print('Base32:' + s)
print('Base32 decode:' + str(decode))
# 将字符串转为base16编码格式
def stringToB16(s):
encode = base64.b16encode(s)
print('Original:' + s)
print('Base16 encode:' + str(encode))
# 将base16编码格式转化为正常的字符类型
def b16ToString(s):
decode = base64.b16decode(s)
# print('Base16:' + s)
print('Base16 decode:' + str(decode))
# 将字符串转为base85的第一个种类的编码格式
def stringTobase85_1(s):
encode = base64.a85encode(s)
print('Original:' + s)
print('Base85_1 encode:' + str(encode))
# 将base85的第一个种类的编码格式转化为正常的字符类型
def base85_1Tostring(s):
decode = base64.a85decode(s)
# print('Base85_1:' + s)
print('Base85_1 decode:' + str(decode))
# 将字符串转为base85的第二个种类的编码格式
def stringTobase85_2(s):
encode = base64.b85encode(s)
print('Original:' + s)
print('Base85_2 encode:' + str(encode))
# 将base85的第一个种类的编码格式转化为正常的字符类型
def base85_2Tostring(s):
decode = base64.b85decode(s)
# print('Base85_2:' + s)
print('Base85_2 decode:' + str(decode))
# 将字符串转为base36编码格式
def stringTobase36(s):
encode = base36.loads(s)
print('Original:' + s)
print('Base36 encode:' + str(encode))
# 将base36编码格式转化为正常的字符类型
def base36Tostring(s):
decode = base36.dumps(int(s))
# print('Base36:' + s)
print('Base36 decode:' + str(decode))
# 将字符串转化为base58编码格式
def stringTobase58(s):
encode = base58.b58encode(str(s))
print('Original:' + s)
print('Base58 encode:' + str(encode))
# 将base58编码格式转化为正常的字符类型
def base58Tostring(s):
encode = base58.b58decode(s)
print('Base58 decode:' + str(encode))
# 将字符串转化为base91编码格式
def stringTobase91(s):
encode = base91.encode(s)
print('Original:' + s)
print('Base91 encode:' + str(encode))
# 将base58编码格式转化为正常的字符类型
def base91Tostring(s):
decode = base91.decode(s)
# print('Base91:' + s)
print('Base91 decode:' + str(decode))
# 将字符串转为base全家桶编码格式
# def basefamily(s):
# b64ToString(s)
# b32ToString(s)
# b16ToString(s)
# base58Tostring(s)
# base91Tostring(s)
# base36Tostring(s)
# base85_1Tostring(s)
# base85_2Tostring(s)
# 进行url编码
def urlEncode(s):
encode = quote(s)
print('Original:' + s)
print('URL encode:' + encode)
# 进行url编码
def urlDecode(s):
decode = unquote(s)
print('URL encode:' + s)
print('URL decode:' + decode)
# 将二进制转化为十进制
def binToDec(s):
result = int(s, 2)
print('Binary :' + str(s))
print('Decimal :' + str(result))
# 将八进制转化为十进制
def octToDec(s):
result = int(s, 8)
print('Octal :' + str(s))
print('Decimal :' + str(result))
# 将十六进制转化为十进制
def hexToDec(s):
result = int(s, 16)
print('Hex :' + str(s))
print('Decimal :' + str(result))
# 将十进制转化为二进制
def decToBin(s):
s = int(s)
result = bin(s)
print('Decimal:' + str(s))
print('Binary:' + str(result))
# 将十进制转化为八进制
def decToOct(s):
s = int(s)
result = oct(s)
print('Decimal :' + str(s))
print('Octal :' + str(result))
# 将十进制转化为十六进制
def decToHex(s):
s = int(s)
result = hex(s)
print('Decimal :' + str(s))
print('Hex :' + str(result))
# 将字母转化为对应的ASCII
def lettToASCII(s):
print('Letters:' + s)
result = ''
for i in s:
result = result + str(ord(i)) + ' '
print('ASCII :' + result)
# 将ASCII转化为对应的字母以及字符
def asciiToLett(s):
list = s.split(' ')
result = ''
print('ASCII :' + s)
for i in list:
i = int(i)
result = result + chr(i)
print('Letters :' + result)
if __name__ == '__main__':
menu()
测试与总结
以下展示一些页面和测试用例,以及其中出现的一些问题
此为启动提示界面
接下来是base91的解码:
此为md5的加密(此处需要注意的是提供的是32小写的加密数据)
特别还需要注意的是将字母转化为对应的ASCII的时候如果您输入的是字母是用空格分开的时候需要添加双引号,如果是一段字符串则不需要添加双引号
python ctf_crypto_tool.py -ord "Force is the author"
python ctf_crypto_tool.py -ord abaaba
否则会出现报错(由于时间关系我没进行报错的异常处理,笔者可以自行添加)
同样的,将ASCII转化为对应的字母以及字符同上原理。 在提示信息的地方已经给出了提示和使用示例。
出现的一些问题:
目前笔者测试了base64、32、16、36、58、91的解密,发现base58的解密在用网上在线网站得到的base58测试集进行测试的时候会出现例如这样的情况
目前笔者的猜测可能是我使用的base58这个第三方库和在线网站背后的解码原理不相同(仅个人猜测,望读者给予解答,感谢)
由于时间问题就未能仔细往下研究,待考试结束后会继续研究base全家桶并把之前的目的实现。
python这门语言十分的好玩简洁有趣,望能坚持学习下去并能不断实现一些有趣的案例加强自己的学习兴趣。
PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取