Unprintable
很头疼的一到题哈哈,基础分析都尝试无果。
解法
正方形,去解析每个小正方形的颜色,(0,0,0)->0 (255,255,255) ->1 转换成二进制
实验出10个像素点是一个小正方形,写两个loop读取到一串二进制字符串
from PIL import Image
def generate_binary_string():
try:
img = Image.open("Unprintable.png") # Open the img
except:
print('Put Unprintable.png file on this directory')
exit(1)
pixels = img.convert('RGB') # Convert it in RGB
width, height = img.size # Getting the img's dimension
binary_string = ""
# Loop every 10 pixels
for y in range(0, height, 10):
for x in range(0, width, 10):
r, g, b = pixels.getpixel((x, y))
if r == g == b == 0: # If the pixel is 0 = black = 0
binary_string += "0"
elif r == g == b == 255: # If the pixel is 255 = white = 1
binary_string += "1"
return binary_string
之后将二进制转为ASCII码看看有没有有用的信息,每八位提取出来。
def bitstring_to_bytes(s):
v = int(s, 2)
b = bytearray()
while v:
b.append(v & 0xff)
v >>= 8
return bytes(b[::-1])
def to_ascii(binary_string):
binary_values = [binary_string[i:i+8] for i in range(0, len(binary_string), 8)]
raw_str = ""
for i in range(len(binary_values)):
bs = bitstring_to_bytes(binary_values[i])
raw_str += str(bs).replace("b'","").replace("'","")
return raw_str
if __name__ == '__main__':
binary_string = generate_binary_string()
print(to_ascii(binary_string))
# to_ascii中参数为#0010110101011011001101110010110100111110001010110011110001011101001111100010110...
#输出为
#-[7->+<]>-.\x88[3\x83+\x86>-.[5\x83+\x86>2-.4\x80\x832+\x86\x8.\x80\x8e5+\x90>+.\x802\x8e+\x86\x88.[5\x83+\x90>3-.3+.2+.\x8[5\x83+\x86>.2\x803\x8e2+\x86>3
发现有很多\x88 \x83的东西,它是 RLE 编码的brainfuck,参考谷歌找到对于的编码
将 \x88 替换成 >-
将 \x83 替换成 ->
将 \x86 替换成 <]
将 \x80 替换成 -[
将 \x8 替换成 >-
将 \x90 替换成 <]
将 -e 和以及前面的一个字节替换成 -> 例如 >-e 替换成 ->
最终得到
-[7->+<]>-.>-[3->+<]>-.[5->+<]>2-.4-[->2+<]>-.-[->5+<]>+.-[2->+<]>-.[5->+<]>3-.3+.2+.>-[5->+<]>.2-[3->2+<]>3-..>-[5->+<]>.-[->2+<]>.5-.13-.6-.-[3->2+<]>+.3-[->2+<]>-.3+.[3->+<]>4-.[2->+<]>5-.3-.-[5->+<]>2-.8-.-[3->+<]>2-.+[->3+<]>+.8+.12-.+[2->+<]>+.[3->2+<]>3-.2+[->3+<]>.15+.2+[->5+<]>.2-[3->2+<]>.+[->3+<]>.7+.-[3->+<]>2-.7-.[3->+<]>3+.
这就是一个RLE压缩了,将他进行恢复,例如7- 就代表------- , 2+就代表++ 以此类推
def rle_decode(decoded_str):
final_decoded_string = ""
i = 0
while i < len(decoded_str):
if decoded_str[i].isdigit():
if decoded_str[i + 1].isdigit():
final_decoded_string += int(decoded_str[i] + decoded_str[i + 1]) * decoded_str[i + 2]
i += 3
else:
final_decoded_string += int(decoded_str[i]) * decoded_str[i + 1]
i += 2
else:
final_decoded_string += decoded_str[i]
i += 1
return final_decoded_string
最终得到
-[------->+<]>-.>-[--->+<]>-.[----->+<]>--.----[->++<]>-.-[->+++++<]>+.-[-->+<]>-.[----->+<]>---.+++.++.>-[----->+<]>.--[--->++<]>---..>-[----->+<]>.-[->++<]>.-----.-------------.------.-[--->++<]>+.---[->++<]>-.+++.[--->+<]>----.[-->+<]>-----.---.-[----->+<]>--.--------.-[--->+<]>--.+[->+++<]>+.++++++++.------------.+[-->+<]>+.[--->++<]>---.++[->+++<]>.+++++++++++++++.++[->+++++<]>.--[--->++<]>.+[->+++<]>.+++++++.-[--->+<]>--.-------.[--->+<]>+++.
bf编码进行解密即可得到flag
完整代码:
# !/usr/bin/env python3
from PIL import Image
def bitstring_to_bytes(s):
v = int(s, 2)
b = bytearray()
while v:
b.append(v & 0xff)
v >>= 8
return bytes(b[::-1])
def get_replace(binary_values,bs,next=False):
index = int.from_bytes(bs, "little") - 128
if(next):
_bs = bitstring_to_bytes(binary_values[index + 1])
else:
_bs = bitstring_to_bytes(binary_values[index])
return _bs
def generate_binary_string():
try:
img = Image.open("Unprintable.png") # Open the img
except:
print('Put Unprintable.png file on this directory')
exit(1)
pixels = img.convert('RGB') #Convert it in RGB
width, height = img.size #Getting the img's dimension
binary_string = ""
# Loop every 10 pixels
for y in range(0, height, 10):
for x in range(0, width, 10):
r, g, b = pixels.getpixel((x, y))
if r == g == b == 0: #If the pixel is 0 = black = 0
binary_string += "0"
elif r == g == b == 255: #If the pixel is 255 = white = 1
binary_string += "1"
return binary_string
def decode_binary(binary_string):
binary_values = [binary_string[i:i+8] for i in range(0, len(binary_string), 8)]
decoded_str = ""
raw_str=""
for i in range(len(binary_values)):
bs = bitstring_to_bytes(binary_values[i])
raw_str += str(bs).replace("b'","").replace("'","")
try:
decoded_str += bs.decode()
except:
_bs = get_replace(binary_values,bs)
try:
decoded_str += _bs.decode()
except:
__bs = get_replace(binary_values, _bs)
decoded_str += __bs.decode()
__bs = get_replace(binary_values, _bs, True)
decoded_str += __bs.decode()
continue
_bs = get_replace(binary_values, bs, True)
try:
decoded_str += _bs.decode()
except:
__bs = get_replace(binary_values, _bs)
decoded_str += __bs.decode()
__bs = get_replace(binary_values, _bs, True)
decoded_str += __bs.decode()
print("The raw decoded string is:\n" + raw_str )
return decoded_str
def rle_decode(decoded_str):
final_decoded_string = ""
i = 0
while i < len(decoded_str):
if decoded_str[i].isdigit():
if decoded_str[i + 1].isdigit():
final_decoded_string += int(decoded_str[i] + decoded_str[i + 1]) * decoded_str[i + 2]
i += 3
else:
final_decoded_string += int(decoded_str[i]) * decoded_str[i + 1]
i += 2
else:
final_decoded_string += decoded_str[i]
i += 1
return final_decoded_string
if __name__ == "__main__":
binary_string = generate_binary_string()
print("The binary string is:\n" + binary_string)
decode_binary = decode_binary(binary_string)
print("The binary string properly decoded is: \n" + decode_binary)
final_decoded_string = rle_decode(decode_binary)
print("The brainfuck string is: \n" + final_decoded_string)
bf解密