HTB Stego write up for the Massacre[INSANE] challenge

316 阅读3分钟

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)