csaw-ctf-2016-quals_sleeping-guard
-
- D e s c r i p t i o n Description Description
- A n a l y s i s Analysis Analysis
- S o l v i n g c o d e Solving~code Solving code
- R e f e r e n c e Reference Reference
k e y w o r d s : keywords: keywords: 文件头异或得到key
D e s c r i p t i o n Description Description
import base64
from twisted.internet import reactor, protocol
import osPORT = 9013import struct
def get_bytes_from_file(filename):return open(filename, "rb").read()KEY = "[CENSORED]"def length_encryption_key():return len(KEY)def get_magic_png():image = get_bytes_from_file("./sleeping.png")encoded_string = base64.b64encode(image)key_len = length_encryption_key()print 'Sending magic....'if key_len != 12:return ''return encoded_stringclass MyServer(protocol.Protocol):def connectionMade(self):resp = get_magic_png()self.transport.write(resp)class MyServerFactory(protocol.Factory):protocol = MyServerfactory = MyServerFactory()reactor.listenTCP(PORT, factory)reactor.run()
PS: xctf中没有这段代码描述(但是实际上flag
也是可以做出来的)
只有真正的hacker才能看到这张图片
A n a l y s i s Analysis Analysis
先nc
得到一串base64
字符
解码得到的是乱码
现在来看看题目给出的代码描述了什么过程
def get_magic_png():image = get_bytes_from_file("./sleeping.png")encoded_string = base64.b64encode(image)key_len = length_encryption_key()print 'Sending magic....'if key_len != 12:return ''return encoded_string
没有提及加密的过程而是直接将原图像的数据转换为base64
写入了文件
但是这里又提到了key
,那么一定是加密了但是加密过程没有写上代码
而且key_len==12
现在来排除可能的加密方式,首先需要这样的密钥的加密方式:在古典密码中,可能就是维吉尼亚密码;现代密码就是常见的分组密码AES,DES以及一些衍生的小众加密
排除一下,首先当我们把base64
解码后得到字符不是分组加密得到的密文长度,所以排除
维吉尼亚密码加密的是字母而不是这里的乱码
这里我们得到的密文是几乎与图像长度等长的乱码,又需要key
很可能是异或
那么由于图像文件格式就只有几种,那么密文开头解密之后一定是独特的文件头格式
所以将已知的文件头格式与密文异或,查看结果是否为有意义的字符串,那么这就是key
,而由于key_len==12
,所以我们可以只截取 12 12 12位的密文与文件头格式进行异或
最后是png
图片的文件头格式异或成功得到有意义的字符串
那么key=="WoAh_A_Key!?"
之后就扩充key
到密文长度进行异或即可
S o l v i n g c o d e Solving~code Solving code
import base64
from Crypto.Util.strxor import strxor
from tqdm import tqdmf = open("cipher.txt","r")
cipher = f.read()
txt = base64.b64decode(cipher)
f.close()
# print(list(txt))
key = "WoAh_A_Key!?"
key = (key * (len(txt) // len(key) + 1))[:len(txt)]
result= []
ls1 = list(txt)
ls2 = list(map(ord,list(key)))
for i in tqdm(range(len(txt))):result.append(ls1[i] ^ ls2[i])
result = bytearray(result)print(result)
f = open("plaint.png","wb")
f.write(result)
R e f e r e n c e Reference Reference
CSAW 2016]Sleep Guard Writeup – Megabeets