題目信息
題目給了服務器及端口號和一份python代碼(攻防世界給掉了)
import base64
from twisted.internet import reactor, protocol
import os
PORT = 9013
import 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_string
class MyServer(protocol.Protocol):
def connectionMade(self):
resp = get_magic_png()
self.transport.write(resp)
class MyServerFactory(protocol.Factory):
protocol = MyServer
factory = MyServerFactory()
reactor.listenTCP(PORT, factory)
reactor.run()
我們從服務器收到了base64編碼的文本。
它可能是python代碼中提到的png圖像所以我們解碼並將其保存到爲out.png:
nc 111.198.29.45 47726 | base64 --decode > out.png
試圖打開圖像,圖像查看器無法打開文件。使用文本查看器打開文件,看到沒有PNG標頭。所以現在我們有圖像,但它以某種方式編碼,我們需要找出如何解碼它。
讓我們看一下腳本,答案可能就在那裏。在使用base64對文件進行編碼後,腳本將檢查加密密鑰的大小是否爲12。
關鍵代碼:
KEY = "[CENSORED]"
def length_encryption_key():
return len(KEY)
if key_len != 12:
除了編碼本身之外,我們在腳本中看不到任何加密,但我們可以假設在原始腳本中使用12字節長密鑰完成加密。但加密什麼?有十億種選擇,我們如何找到合適的解密算法?嗯,答案很簡單 - 這是一個CTF,管理員知道我們不能嘗試所有可能的解密方法,所以它可能是平庸的選擇:異或。
在選擇我們的加密方法後,讓我們考慮如何找到密鑰本身。我們知道該文件是PNG圖像,因此我們可以將加密文件的前12個字節與正常PNG文件的前12個字節進行異或。
89 50 4E 47 0D 0A 1A 0A 00 00 00 0D XOR DE 3F 0F 2F 52 4B 45 41 65 79 21 32 == 57 6F 41 68 5F 41 5F 4B 65 79 21 3F
在ASCII中是:“ WoAh_A_Key!?”
現在我們有了密鑰,我們可以運行python腳本,要在Linux環境下運行,得到的圖片才能打開,windows環境下不行
def xor(data, key):
l = len(key)
return bytearray((
(data[i] ^ key[i % l]) for i in range(0,len(data))
))
# Read the encrypted image as bytearray
data = bytearray(open('out.png', 'rb').read())
# This is our key as bytearray: "WoAh_A_Key!?"
key = bytearray([0x57, 0x6f, 0x41, 0x68, 0x5f, 0x41, 0x5f, 0x4b, 0x65, 0x79, 0x21, 0x3f])
with open('decrypted.png', 'w') as file_:
file_.write(xor(data,key))
得到flag