PNG structure for beginner

0xwan
6 min readNov 7, 2021

--

Learn PNG file structure to solve basic forensics challenge

Assalamualaikum, peace be upon you

Hey readers! In this blog I want to share what I have learnt about PNG file structure when I tried to solve some simple forensics challenge. I dont have much interest in forensics tbh but for the sake of learning and improving my ctf skills, so why not? Now let’s get started.

Introduction

PNG is a short form of Portable Network Graphics and it is an image file. Everyone knows about it. So let’s move to a bit more complicated part that not everyone knows. By the way to better understand this, it is recommended to use hex editor as a reference on how the structure looks like.

FILE STRUCTURE

1. File Signature

First part in a PNG file (every file also the same), we have a signature. Signature is the part that tells what type of file a certain file is. Normally we look at the extension of a file to identify what type of file it is. But extensions can be spoof to anything without corrupting the file, while file signature can’t. For example, I can rename my image file to ‘image.zip’ and the image file can still be opened. But when I change the file signature to other thing, the file cant be opened. To see a PNG file header we can use hex editor and look at the first row.

As you can see the first 8 bytes that I highlighted is the part that tells this is a PNG file and you can see at the right part it literally says ‘PNG’. So every PNG file should have this 8 bytes 89 50 4E 47 0D 0A 1A 0A. To learn more about various file signature or file header, you can refer to this.

Chunks

Before moving to other chunks like IHDR, PLTE (I will not cover this chunk here), IDAT and IEND, let’s learn the important part in chunks. Each chunk has 4 parts which is length of the chunk data, type of chunk, chunk data and CRC. The first part is length of the chunk, it has 4 bytes and it tells how many byte the chunk data has. Second part is type of chunk and it also has 4 bytes. This part tells whether it is a IHDR, IDAT or IEND. Third part is chunk data. This part contains the data of the chunk. The size of this part will be written in the first part of the chunk that I mention earlier. And lastly we have CRC that also has 4 bytes.

Parts in chunk:

Example of chunk and its components

If you dont understand my explanation earlier, look at the image above. First, find the type of the chunk which is in this case is IHDR the red one. It is easy to find what type of chunk by looking at the right side of hex editor and the type is human readable. Remember, the ‘type of chunk’ is the second part. So the first part is, obviously the 4 bytes that sit before IHDR is the ‘size of chunk data’ part (green).

If you look at the value it says 00 00 00 0D, that is 13 in hex, so the ‘chunk data’ will have 13 bytes. And if you count the blue underline part, yes it’s 13 bytes. The ‘chunk data’ sit right after the ‘chunk type’ part. So the rest is CRC which is 4 bytes (purple) and it is the last part of a chunk (in the image I forgot to include the last byte that’s why it’s only 3 bytes of CRC).

Other type of chunk like IDAT also has these 4 parts in it.

2. IHDR chunk

IHDR is a chunk that contains the image information such as width, height, size of color byte, color type, compression, filter and enlacement method. These information can be found inside ‘chunk data’ part. Here is how you can identify the image information in ‘chunk data’ :

Distribution of bytes in chunk data IHDR

IHDR has 13 bytes for its ‘chunk data’ so these 13 bytes are distributed according to the image above.

This is example of IHDR chunk from real PNG image.

IHDR example

And this is how the bytes distributed base on each part in chunk.

Bytes distribution in IHDR

And then from the ‘chunk data’ 00 00 06 6A 00 00 04 47 08 02 00 00 00, I split it according to the ‘chunk data’ parts so you can understand which byte is the width or height or color type of a PNG image.

3. IDAT chunk

According to the PNG Specification,

The IDAT chunk contains the output datastream of the compression algorithm. To read the image data, reverse this process. There can be multiple IDAT chunks; if so, they must appear consecutively with no other intervening chunks. The compressed datastream is then the concatenation of the contents of all the IDAT chunks.

So to summarize it, IDAT chunk contains the bytes that will appear or render on the screen. Same as IHDR chunk, IDAT also has 4 parts. The difference is IDAT ‘chunk data’ size is larger.

Example of IDAT chunk data size

As you can see the 4 bytes before IDAT (chunk type) is ‘size of chunk data’ part so it contains the ‘chunk data’ size. the value shows that this IDAT has 0xFFA5 size of data compare to IHDR that only has 0x0D.

4. IEND

Last chunk in PNG file is IEND. if you open PNG file in hex editor you will find IEND sits at the bottom. As usual, same as the other chunks, IEND has 4 parts. Let take a look how the chunk looks like :

IEND chunk

In this example IEND has 0x00000000 size of chunk data which mean it doesn’t have any chunk data. Image below will help you understand better.

Bytes distribution in IEND

Conclusion

In conclusion, a PNG file has a signature and some important chunks such as IHDR, IDAT and IEND. If the file missing or misspelled one of these chunk, the image cant be opened. So if you have a PNG file that cant be opened, you can use this blog and try to recover the PNG by looking at each chunk and inspect each part in the chunk. If you play CTF you probably know this type of challenge exist.

reference:

http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html#:~:text=The%20IDAT%20chunk%20contains%20the%20output%20datastream%20of%20the%20compression,of%20all%20the%20IDAT%20chunks.

image — https://lh3.googleusercontent.com/proxy/fuj-2V335sY7INZ0j4rcXUqufb0yUwrahcqvU_f9DNcZGdHEziazgff97Re_TR3s7GbmbCPw-UC1zP0PNPeyMPMzByhp

https://www.garykessler.net/library/file_sigs.html

--

--