Massacre
尝试多种基础方法后仍然无果。
解法
先去除图片中像素值为0的
img = Image.open(img_name) # Return an Image object
nozero = []
for rgb in list(img.getdata()): # Skipping zero rgb's
if rgb != (0, 0, 0):
nozero.append(rgb)
观察下rgb的分布情况
R = 0; G = 1; B = 2
R_set = set()
G_set = set()
B_set = set()
for i in nozero:
if i[0] % 10 != 0 or i[1] % 10 != 0 or i[2] % 10 != 0: # Some numbers don't end with 0, so we'll want it
R_set.add(i[R] // 10)
G_set.add(i[G] // 10)
B_set.add(i[B] // 10)
得到
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24} {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24} {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}
接着看下rgb的波动情况
R = 0; G = 1; B = 2
R_set = set()
G_set = set()
B_set = set()
for i in nozero:
if i[0] % 10 != 0 or i[1] % 10 != 0 or i[2] % 10 != 0: # Some numbers don't end with 0, so we'll want it
R_set.add(i[R] % 10)
G_set.add(i[G] % 10)
B_set.add(i[B] % 10)
得到
{0, 1, 2, 3} {0, 1, 2, 3, 4, 5, 6, 7} {0, 1, 2, 3, 4, 5, 6, 7}
看来R的波动范围小,GB的波动范围也没有达到8,9
R有四位,那就等于2^2, G和B有八位,那就是2^3和2^3
共2+3+3八位。
肯定可以将RGB按顺序(或反序)组成一个八位二进制
for i in nozero:
r = '{:08b}'.format(i[R] % 10)[6:8] # Get the last 2 bits of the octal obtained by doing module 10, and convert them to binary
g = '{:08b}'.format(i[G] % 10)[5:8] # Get the last 3 bits ----
b = '{:08b}'.format(i[B] % 10)[5:8] # Get the last 3 bits ----
str = r + g + b # All the bits represents a binary number
print(str)
break
{:08b}是按照八位二进制格式,因为r只有最后两位有效,所以取6:8。同理gb是后三位有效,取5:8,并按照顺序拼接成完整的八位二进制
再将这个二进制 转为 ASCII码,并一直循环每个像素点
i = chr(int(str[:8], 2)) # ASCII char from each 8 bits number converted to decimal
message = message + i # Joins each char to a message
最终得到一串可读的短文,其中flag就藏在其中
完整代码:
#!/usr/bin/env python3
from PIL import Image
import re
R = 0; G = 1; B = 2
img_name = 'massacre.png'
try:
img = Image.open(img_name) # Return an Image object
except:
print ('Put massacre.png file on this directory')
exit(1)
pixels = list(img.getdata()) # Gets the image's data
nozero = []
print("Extracting non zero pixels...")
for rgb in pixels: # Skipping zero rgb's
if rgb != (0, 0, 0):
nozero.append(rgb)
message = ""
print("Getting the message...")
# Getting the last digit from the RBG tuples
for i in nozero:
if i[0] % 10 != 0 or i[1] % 10 != 0 or i[2] % 10 != 0: # Some numbers don't end with 0, so we'll want it
r = '{:08b}'.format(i[R] % 10)[6:8] # Get the last 2 bits of the octal obtained by doing module 10, and convert them to binary
g = '{:08b}'.format(i[G] % 10)[5:8] # Get the last 3 bits ----
b = '{:08b}'.format(i[B] % 10)[5:8] # Get the last 3 bits ----
str = r + g + b # All the bits represents a binary number
i = chr(int(str[:8], 2)) # ASCII char from each 8 bits number converted to decimal
message = message + i # Joins each char to a message
print(message)
print("Looking for the flag...")
regex = re.compile("(HTB{.*})") # Creating the pattern to find the flag inside the message
found = regex.search(message) # Searching that regex in the message
if found:
print(found.group(1)) # Shows the match
exit(0)
else:
print ("Nothing works")
exit(1)