编码
hex
hex是将信息转化为16进制,密码学中大部分操作都是进行数学计算的过程。我们无法直接对字符串进行数学计算,所以需要将字符串转换为数字。可以通过hex编码的方式进行转换,将原始的字符串转化为十六进制字符串,再进行进一步的数学计算。以下为demon。
s = 'flag'
s_by = bytes(s, 'UTF-8') # 转换成编码
print(s_by, type(s_by))
s_str = s_by.hex() # 转换成16进制字符串
print(str, type(str))
s_int = int(s_str, 16) # 转换成10进制整数
print(s_int, type(s_int))
s_hex = hex(s_int) # 转换成16进制字符串,也可以直接+0x
print(s_hex, type(s_hex))
print(ord('a')) # 对单字符可以直接用ord函数
num = 584734024210391580014049650557280915516226103165
num_str = hex(num)
print(num_str, type(num_str)) # hex结果是字符串
num_hex = num_str[2:]# 截取第三个到最后
print(num_hex) #若有L,则[2:-1]截取到倒数第二个字符串,前闭后开
flag = ''
for i in range(0, len(num_hex), 2):
tmp = num_hex[i:i + 2]
flag += chr(int(tmp, 16))
print(flag)
print(bytes_to_long(bytes("flag{this_is_a_flag}", 'UTF-8')))
print(long_to_bytes(num).decode())
'''
b'flag' <class 'bytes'>
<class 'str'> <class 'type'>
1718378855 <class 'int'>
0x666c6167 <class 'str'>
97
0x666c61677b746869735f69735f615f666c61677d <class 'str'>
666c61677b746869735f69735f615f666c61677d
flag{this_is_a_flag}
584734024210391580014049650557280915516226103165
flag{this_is_a_flag}
'''
urlencode
urlencode主要用于浏览器和网站之间的数据交换,这种编码是在特殊字符的hex基础上,每个字符前置一个“%”,demon如下:
import urllib.parse
print(urllib.parse.quote('flag{url_encode_1234_!@#$}'))
#quote处理字符转义,在特殊字符hex的基础上,每个字符前置一个%
d={'name':'bibi@flappypig,club','flag':'flag{url_encode_1234_!@#$}'}
print(urllib.parse.urlencode(d))
'''
flag%7Burl_encode_1234_%21%40%23%24%7D
name=bibi%40flappypig%2Cclub&flag=flag%7Burl_encode_1234_%21%40%23%24%7D
quote对字符串进行url编码,可以使用unquote函数进行解码
urlencode函数对字典模式的键值对进行url编码
'''
morsecode
摩斯电码由长音和短音构成的,使用“.”表示短音,“-”表示长音,“/”表示分隔符,解码可以用在线工具列举如下:
https://www.atool99.com/morse.php
http://www.zhongguosou.com/zonghe/moErSiCodeConverter.aspx
http://www.bejson.com/enc/morse/
https://www.jb51.net/tools/morse.htm
如果碰到摩斯电码与MISC音频题结合起来出题,求稳可以用Cool Edit进行编辑,可以明显观察长音和短音,(自信听力好可以直接听)然后将电码抄录,最后解码。用python进行解码的code如下:
alphabet_to_morse = {
"A": ".-",
"B": "-.-.",
"C": "-.-.",
"D": "-..",
"E": ".",
"F": "..-.",
"G": "--.",
"H": "....",
"I": "..",
"J": ".---",
"K": "-.-",
"L": ".-..",
"M": "--",
"N": "-.",
"O": "---",
"P": ".--.",
"Q": "--.-",
"R": ".-.",
"S": "...",
"T": "-",
"U": "..-",
"V": "...-",
"W": ".--",
"X": "-..-",
"Y": "-.--",
"Z": "--..",
"0": "-----",
"1": ".----",
"2": "..---",
"3": "...--",
"4": "....-",
"5": ".....",
"6": "-....",
"7": "--...",
"8": "---..",
"9": "----.",
".": ".-.-.-",
",": "--..--",
":": "---...",
";": "-.-.-.",
"?": "..--..",
"-": "-....-",
"_": "..--.-",
"(": "-.--.",
")": "-.--.-",
"=": "-...-",
"+": ".-.-.",
"/": "-..-.",
"@": ".--.-.",
"$": "...-..-",
"&": "....",
"'": ".----.",
"!": "-.-.--",
'"': ".-..-.",
}
morse_to_alphabet = {v: k for k, v in alphabet_to_morse.items()}
def _morseremoveunusablecharacters(uncorrected_string):
return filter(lambda char: char in alphabet_to_morse,
uncorrected_string.upper())
'''filter() 函数用于过滤序列,过滤掉不符合条件的元素,
返回由符合条件元素组成的新列表function -- 判断函数。iterable -- 可迭代对象
匿名函数lambda:是指一类无需定义标识符(函数名)的函数或子程序。
lambda 函数可以接收任意多个参数 (包括可选参数) 并且返回单个表达式的值。
'''
def morseencode(decoded):
"""
:param decoded:
:return:
"""
morsestring = []
decoded = _morseremoveunusablecharacters(decoded)
decoded = decoded.upper()
words = decoded.split(' ')
for word in words:
letters = list(word)
morseword = []
for letter in letters:
morseletter = alphabet_to_morse[letter]
morseword.append(morseletter)
word = "/".join(morseword)
morsestring.append(word)
return " ".join(morsestring)
def morsedecode(encoded):
"""
:param encoded:
:return:
"""
characterstring = []
words = encoded.split(" ")
for word in words:
letters = word.split("/")
characterword = []
for letter in letters:
characterletter = morse_to_alphabet[letter]
characterword.append(characterletter)
word = "".join(characterword)
characterstring.append(word)
return " ".join(characterstring)
jsfuck
jsfuck仅使用6个字符“()+[]!”就可以书写任意的Javascript代码,可以在下面两个网站解码:
https://utf-8.jp/public/jsfuck.html
uuencode
uuencode是一种将二进制文本转化为可见字符文本的一种编码,编码之后出现的是ASC码32-95的字符,也就是没有小写字母,还是比较容易识别的。也有在线解码网站:https://www.qqxiuzi.cn/bianma/uuencode.php
base
Crypto一定要提到大名鼎鼎的base家族,如base64、base32、base16等,还有一些可能不太熟悉的,如base36、base58、base62、base85、base91、base92。其中base16就是hex,也就是用16个字符去表示256个字符(4bit的内容去表示16bit的内容),如果用更多的字符就也就是后面的base32、base64。
那么如何识别base家族呢,首先看结尾有没有补位的“=”如果有就一定是,没有再看对应的字母是不是在base家族对应的字符集上。下面列举base家族对应的字符集
base | 字符集 |
---|---|
base16 | 0-9,A-F共16个以及补位的“=” |
base32 | A-Z,2-7共32个以及补位的“=” |
base64 | a-z,0-9,A-F,+,/共64个以及补位的“=” |
下面举个base64例子说明它是如何将3个字符用4个字符进行表示的
A S T |
---|
65 83 84 |
01000001 01010011 01010100 |
010000 010101 001101 010100 |
16 21 13 20 |
如上所示,先将找字符对应的asc码,再转化为二进制,然后6bit一组切分,将6bit组成的数字转化为十进制,最后查表得到字符。其它如base32也是进行类似操作。
至于没有列举的(不太常见的)可以自行查阅字符集,有些题目可能就是会用多种base进行多次编码,相应的也需要多次解码,所以判断在哪一次用了那种编码就十分重要,下面是一个非常好用的在线解码网站(对ctf来说都很好用),能进行base家族的多种编码解码http://ctf.ssleye.com/。
最后Python demon如下
import base64
s = 'flag'
s_by = bytes(s, 'UTF-8') # 转换成编码
print(s_by, type(s_by))
s_base64_by = base64.b64encode(s_by)
print(s_base64_by, type(s_base64_by)) # 类型还是编码
s_base64 = s_base64_by.decode()
print(s_base64, type(s_base64)) # decode变为字符串
print(base64.b16encode(bytes('flag', 'UTF-8')).decode())
print(base64.b32encode(bytes('flag', 'UTF-8')).decode())
print(base64.b64encode(bytes('flag', 'UTF-8')).decode())
print(base64.b16decode("666C6167".upper()))
print(base64.b32decode("MZWGCZY=")) # 结果为编码
print(base64.b64decode("ZmxhZw==")) # 结果为编码
'''
b'flag' <class 'bytes'>
b'ZmxhZw==' <class 'bytes'>
ZmxhZw== <class 'str'>
666C6167
MZWGCZY=
ZmxhZw==
b'flag'
b'flag'
b'flag'
'''
Quoted-printable
http://web.chacuo.net/charsetquotedprintable/
http://www.mxcz.net/tools/quotedprintable.aspx
Rabbit
http://tool.chinaz.com/Tools/TextEncrypt.aspx
中文电码
曼彻斯特编码
网上有现成工具。