CTFshow question brushing diary MISC pictures (Part 2, 24-51) file structure and color channel

Keywords: Python Pycharm crawler CTF


Document structure

Misc24 BMP height change

Tip: the flag is above the picture

bmp format file

The real flag is on the picture. You can see it by changing the height

Misc25 PNG height change

Tip: the flag is under the picture

Just change the height


Tip: the flag is still under the picture, but how much is it?

Open the file with tweakpng

Get the image height through the python 2 script

# -*- coding: utf-8 -*-
import binascii
import struct


crc32key = 0xCBD6DF8A
for i in range(0, 65535):
  height = struct.pack('>i', i)
  data = '\x49\x48\x44\x52\x00\x00\x01\xF4' + height + '\x08\x06\x00\x00\x00'

  crc32result = binascii.crc32(data) & 0xffffffff

  if crc32result == crc32key:
    print ''.join(map(lambda c: "%02X" % ord(c), height))

Second script - piccrc32.py is recommended

import binascii
import struct

crcbp = open("misc26.png", "rb").read()
for i in range(2000):
    for j in range(2000):
        data = crcbp[12:16] + struct.pack('>i', i)+struct.pack('>i', j)+crcbp[24:29]
        crc32 = binascii.crc32(data) & 0xffffffff
        if(crc32 == 0xEC9CCBC6):
            print(i, j)
            print('hex:', hex(i), hex(j))

Get the correct height

Convert 0x25e to decimal, modify the height and save

Therefore, the flag is the content given in the picture on the 25e splicing

Misc27 JPG height change

Tip: the flag is under the picture

Modify height

Save as picture

Misc28 GIF change height

Tip: the flag is under the picture

Also change the picture height

Note that the picture is in gif format and has different frames, so there are width and height values in different blocks. You need to try more. Change this to be effective

misc29 multi frame gif height change

Multiframe gif motion graph

There are a lot of frames. You need to change the height. It is found that there is a flag in frame 8

Misc30 BMP change width

Tip: the correct width is 950

If you find that the picture is like this, you can modify the width according to the prompt

Misc31 BMP calculated width

Tip: the height is correct, but what is the correct width

bmp file format

This picture consists of 900 * 150 pixels, the file header occupies 53 bytes, and the end of the file is at 0x76F50. It is converted into hexadecimal 487248

Because each pixel is represented by three bytes (six hexadecimal bits), each byte is responsible for controlling a color, namely blue, green and red, so the number of pixels in the file is


The title suggests that the height of the picture is correct, so the width should be calculated

The width is the number of pixels divided by the height: 192398 / 150 = 1082 (if there is a remainder to be rounded off)

Change the picture width to 1082, save the picture and open it as flag

Similarly, the previous misc 24 question known width and height is also the same calculation method

Misc32 PNG calculation of crc width

Know the height and width of blasting, just like question 26, you can use the previous script

New script - the effect is the same. Both scripts need to change the crc value

import zlib
import struct

# Simultaneous blasting width and height
filename = "misc32.png"
with open(filename, 'rb') as f:
    all_b = f.read()
    data = bytearray(all_b[12:29])
    n = 4095
    for w in range(n):
        width = bytearray(struct.pack('>i', w))
        for h in range(n):
            height = bytearray(struct.pack('>i', h))
            for x in range(4):
                data[x+4] = width[x]
                data[x+8] = height[x]
            crc32result = zlib.crc32(data)
            #Replace with picture crc
            if crc32result == 0xE14A4C0B:
                print("Width:", end = '')
                print(width, end = ' ')
                print(int.from_bytes(width, byteorder='big'))
                print("Height:", end = '')
                print(height, end = ' ')
                print(int.from_bytes(height, byteorder='big'))

Just run Python 3

The width is 1044. Modify the width and save it

Misc33 pngcrc calculation width and height

The height and width are wrong. Use the script of 32 questions to calculate

Find the value of crc in 010

Change script run

Misc34 PNG blasting width

Tip: the author jumped over the wall and changed the CRC of IHDR block, but we know that the correct width must be greater than 900

import zlib
import struct
filename = "misc34.png"
with open(filename, 'rb') as f:
    all_b = f.read()
    #w = all_b[16:20]
    #h = all_b[20:24]
    for i in range(901,1200):
        name = str(i) + ".png"
        f1 = open(name,"wb")
        im = all_b[:16]+struct.pack('>i',i)+all_b[20:]

Save all the generated pictures (it is recommended to be in an empty folder), and then use your eyes to see which is normal.

Finally, the correct width is 1123

w and h here need to open the picture to have a look

struct --- Interpret byte strings as packed binary data
struct.pack(format, v1, v2, ...)
Return a bytes Object that contains a string according to the format format Packaged values v1, v2, ... The number of parameters must exactly match the value required by the format string

Operation results

Misc35 JPG blasting width

Tip: the person who created the question fought tenaciously, but we know that the correct width must be greater than 900

#w = all_b[157:159]
#h = all_b[159:161]
import zlib
import struct
filename = "misc35.jpg"
with open(filename, 'rb') as f:
    all_b = f.read()
    #w = all_b[159:161]
    #h = all_b[157:159]
    for i in range(901,1200):
        name = str(i) + ".jpg"
        f1 = open(name,"wb")
        im = all_b[:159]+struct.pack('>h',i)+all_b[161:]

You need to raise the base height of the picture a little

When the height is adjusted to 600 and the width is in the range of 993-1000, you can get a flag

Misc36 GIF blasting width

gif picture, indicating that the correct width is between 920-950

Change the script

import zlib
import struct
filename = "misc36.gif"
with open(filename, 'rb') as f:
    all_b = f.read()
    #w = all_b[6:8]
    for i in range(920,950):
        name = str(i) + ".gif"
        f1 = open(name,"wb")
        im = all_b[:38]+struct.pack('>h',i)[::-1]+all_b[40:]

Note that height storage is upside down because

It is found that there is no flag after running. You need to increase the height of the picture and try again

Misc37 GIF frame by frame

Prompt flag in the picture

This is a gif graph. Different characters are found in some frames

Open with stegslove

The flag is hidden in different frames

Misc38 apng image separation

Tip: flag is in the picture

It's a png picture. Nothing is found in the picture browser of win10. Open it with chrome or honey picture browser and find that it's a movable png

Use the apngdis.exe (APNG Disassembler) tool to detach the file

flag fragment found

Misc39 GIF time difference flag

Tip: flag is like water, flowing fast and slowly

It is a gif, but here it is steganographic by using the interval between different frames.

Here, use the tool identify under linux

Installation command: sudo apt-get install imagemagick
 Basic command format:
  identify [options] input-fileidentify:Command name
  input-file:File name.
Extract command: identify -format "%T " misc39.gif > 1.txt

For the obtained strings 36 and 37, consider changing 37 to 1 and 36 to 0 to obtain a binary string with a length of 287. Consider converting one character every 7 bits (normally a group of 8 bits) to obtain a flag

for i in range(41): #287//7
    flag += chr(int(s[7i:7(i+1)],2))

misc-40apng time difference flag

Apng dynamic diagram, use APNG Disassembler tool to separate files, and generate txt files to record details

For example, 54 needs to be extracted and converted into the corresponding ascii code

for i in range(1,69):
    if i < 10:
        i = "0" + str(i)
    f = open("apngframe" + str(i) + ".txt")
    s = f.read()
    # delay=116/1000
    flag += chr(int(s.split("/")[0][6:]))

In fact, the flag appears when there are 28 pictures. You can change the range to 28,69

Misc42 Idat block length

Tip: how long is the flag? 2cm... Sorry, wrong number, 41

Open the picture with tweakpng and find that the length of IDAT data block converted into ASCII code is flag

misc43 collection error

Tip: mistakes hide the way to the right answer

tweakpng opens the picture and finds many error messages. Use pngdebugger to have a look

Many error codes are found and combined with prompts to convert them into strings

python sorting format

string ="E59387E50x93A62E630x746673680x6F777B360x656232350x383966660x666635650x333930660x653662380x373530340x646263300x3839327D"
for i in range(0,len(string),2):
    print((string[i:i+2]),end=" ")

Because the first two characters are not in the Chinese python character set, you are lazy and use tools directly

misc44 conversion error prompt

Tip: there are also pits hidden in the error

tweakpng is still a pile of errors, and this time there are a lot of data blocks in IDAT

Export the output as a document using pngDebugger

Then write a script to replace CRC OK with 1 and CRC FAILED with 0

for i in s.split():
    if "OK!" == i:
        flag += "1"
    elif "FAILED" ==i:
        flag += "0"
print(len(flag)) #344
for i in range(43):

misc45 conversion format

Tip: sometimes you need to change your thinking style

In fact, there are other files hidden in the picture, but because the reading methods of PNG and bmp format picture pixels are different, the file cannot be separated in PNG format. First, convert the picture from PNG format to bmp format, and extract flag.png in binwalk

Online conversion website: https://cn.onlineconvert.com/pdf-to-bmp

misc46-49 volume is obsolete


It's a gif

Extract its details: identify misc46. GIF > / 1.txt (here, directly generate 1.txt in the root directory, easy to find)

The content is about as long as this. Among them, 0 + 0, 174 + 49 and 196 + 47 are offsets. This problem uses this to draw a diagram.

Write a very simple script to extract the coordinates

f = open("1.txt","r")
x = f.readlines()

f = open("out.txt","w")
for i in x:
    f.write(" ")

Then use gnuplot to draw the picture. The result is a little fuzzy and can be adjusted by yourself

Flip it again to get the flag


Gave a png, opened it and found no content. Open it with a browser and confirm that it is apng

The idea is the same as the above topic, but it is a little more complicated. First, learn about the apng file structure through this article. In short, there will be a fcTL block in front of each IDAT block, which contains the horizontal and vertical offset

As follows, the corresponding coordinate points are (182,52)

Some masters had a little problem with the previous script, so they changed it

from PIL import Image

im = Image.new('RGB', (400, 80), 255)
f = open('1.txt','r') #Export the hexadecimal image and save it as 1.txt
c = f.read()

lt = c.split("6663544C")
for i in range(2,len(lt)):
    x = int(lti,16)
    y = int(lti,16)


Open it with 010editor and find a prompt

1. Count the number of FF and subtract 1
2. ctfshow {} contains 32 characters

Yes, but there is no complete prompt, because the first prompt actually refers to the statistics of the number of FF between each two meaningful blocks minus one

The purple one in the figure is the FF at the beginning, because there is only one, minus 1 is 0; Next is 12, 11, 0

Because the flag length is 32 bits, only the first 32 are counted, that is:

0 12 11 0 7 10 13 13 9 0 9 13 0 13 6 0 10 9 2 1 0 1 10 8 11 5 12 7 2 2 3 10

After converting to hexadecimal respectively, connect them together to obtain: ctfshow{0cb07add909d0d60a92101a8b5c7223a}

Tip: there are sixteen of them. This question is a little brain hole and can be skipped

The brain hole problem of the eight gods can't be solved by myself. Refer to wp decisively

When you open it with winhex, you can see a lot of strings. This is actually a hint given by the eight gods, although I didn't get it

The point is that FFE has appeared before these strings? There are a lot of data in this format after searching

Save all hexadecimal numbers in 2.txt and process them with a small script


for i in range(1,len(l)):
    flag += li
print(flag.lower()[:32]) #Put ctfshow{}

In fact, the character behind the FFE is extracted and connected together, a total of 32 bits (), which is flag.

There was a small mistake in writing the script here. This is also counted, so only the first 32 bits are correct.

Copyright notice: This is the original article of CSDN blogger "z.volcano", which follows the CC 4.0 BY-SA copyright agreement. Please attach the source link and this notice for reprint.
Original link: https://blog.csdn.net/weixin_45696568/article/details/115261347

Color channel

Misc50 stegslove a shuttle

Now that the color channel is prompted

The rest are in the back channels


  1. The above misc picture questions basically include the questions in ctf, but they do not involve steganography. f5, outguess, blind watermark and so on do not appear
  2. misc picture questions have a fixed routine, which requires more careful observation and patience. In the process of doing the questions, we also found many blind spots that we didn't pay attention to before
  3. We grow and progress together

Reference link


thank z.volcano The article written by master gave me great inspiration

Posted by kaspari22 on Sat, 11 Sep 2021 23:02:31 -0700