To search


w3pwnz, therefore we are

Tag - stegano

Entries feed Comments feed

Thursday, October 18 2012 16:04

HackYou CTF - Stego100, Stego200, Stego300 Writeups

Stego 100 - Perfect Concealment

Download file stg100.txt.
Notice there are weird uppercase letters in some words. Let's just extract these.

>>> ''.join(__import__('re').findall('\w\w*([A-Z])\w*', open("stg100.txt", "r").read()))

Flag: sexystegopandas

Stego 200 - Halloween

stg200.png Download file stg200.png

If we change the background color we can clearly see something like this:

..    . .. .  . .. ...  ... .   . ..... ..    . ..  ..  ...  . 
....... ....... ....... ....... ....... ....... ....... .......

..    . .. .  . ..  .   . ..... .. .... ..  ..  . ..... .. ... 
....... ....... ....... ....... ....... ....... ....... .......

.. .... . ..... ..  ... .. .    .. .... ...  .. ... .   ...  ..
....... ....... ....... ....... ....... ....... ....... .......

That's binary, let's extract the password from it:

>>> s="""1100001 1101001 1101110 1110100 1011111 1100001 1100110 1110010
... 1100001 1101001 1100100 1011111 1101111 1100110 1011111 1101110
... 1101111 1011111 1100111 1101000 1101111 1110011 1110100 1110011"""
>>> ''.join(chr(int(i, 2)) for i in s.replace("\n"," ").split(' '))

Flag: aint_afraid_of_no_ghosts

Stego 300 - Go Through the Tunnel

stg300.png Download file stg300.png
The text in the middle of the picture is a lure. THAT'S SO FUNNY.
Let's steganalyse this file more seriously, with StegSolve from Caesum (useful tool, although it's java).
Flag: 4E34B38257200616FB75CD869B8C3CF0

Monday, July 2 2012 21:08

NDH2k12-wargame Write-up What the file ?

Name What the file ?
Score 1000
Content While doing some forensics, an analyst found a weird file. Please help him.

We have this file unknown.bin

$ file unknown.bin.png
unknown.bin.png: PNG image data, CORRUPTED
$ pngcheck -vt7f unknown.bin
File: unknown.bin (1179008 bytes)
File is CORRUPTED.  It seems to have suffered EOL conversion.
It was probably transmitted in text mode.

Ok, it's a corrupted PNG that we have to patch.

We realized that the lengths and the chunks' names are affected by several alterations.

We begun by correcting those names and lengths for each chunk.

A quick reminder from the RFC 2083 about the chunk layout :

	A 4-byte unsigned integer giving the number of bytes in the
	chunk's data field. The length counts only the data field, not
	itself, the chunk type code, or the CRC.  Zero is a valid
	length.  Although encoders and decoders should treat the length
	as unsigned, its value must not exceed (2^31)-1 bytes.

Chunk Type
	A 4-byte chunk type code.  For convenience in description and
	in examining PNG files, type codes are restricted to consist of
	uppercase and lowercase ASCII letters (A-Z and a-z, or 65-90
	and 97-122 decimal).  However, encoders and decoders must treat
	the codes as fixed binary values, not character strings.  For
	example, it would not be correct to represent the type code
	IDAT by the EBCDIC equivalents of those letters.  Additional
	naming conventions for chunk types are discussed in the next

Chunk Data
	The data bytes appropriate to the chunk type, if any.  This
	field can be of zero length.

	A 4-byte CRC (Cyclic Redundancy Check) calculated on the
	preceding bytes in the chunk, including the chunk type code and
	chunk data fields, but not including the length field. The CRC
	is always present, even for chunks containing no data.  See CRC
	algorithm (Section 3.4).

No apparent problem for IHDR, sBIT, pHYs, tEXt(Software) and IEND chunks.

For IDAT chunks, we can understand that they're 8192 bytes long.
We scripted the thing to patch the file from offset 0x6A each 8204 bytes (8192 + 4 + 4 + 4) to 00 00 20 00 49 44 41 54 (Length + "IDAT").

$ pngcheck -vt7f unknown.bin.png
  chunk IDAT at offset 0x11c717, length 8192
  chunk IDAT at offset 0x11e723, length 8192:  EOF while reading data

We almost got a proper and genuine png file from pngcheck's point of view, except the latest IDAT chunk. This is normal, as this chunk is the latest one and isn't 8192 bytes long.

We fixed this by correcting with that value : size until the end of file - IEND chunk (12 bytes) - checksum (4 bytes) = 5705 bytes (0x1649).

$ pngcheck -vt7f unknown.bin.png
  chunk IDAT at offset 0x11c717, length 8192
  chunk IDAT at offset 0x11e723, length 5705
  CRC error in chunk IDAT (actual 66b9b445, should be 68cf7786)
  chunk IEND at offset 0x11fd78, length 0

Weird, the checksum is not correct, unlike all the IDAT checksums so far...We'll see later.

As the image can be open with several editors, some others won't because of the latest chunk's checksum. Nevertheless, we can see our old Chuck Norris and only half of the flag.



So at this time we have the first part of the flag...

The wrong checksum of the last IDAT is probably a good clue to get the second part of the flag.
At the end of the file, we can see above IEND chunk a ...zTX3..., maybe a zTXt chunk ? Let's give it a try...

The length will be 27 bytess, 0x1B.
We also changed the length of the last IDAT chunk, 5705 - 27 - 12 = 5666 that's to say 0x1622.

Excellent, this time no more problem with checksums.

$ pngcheck -vt7f unknown.bin.png
  chunk IDAT at offset 0x11e723, length 5666
  chunk zTXt at offset 0x11fd51, length 27:   keyword has control characters, keyword: x\DA\D3\D3C\05\96\A9\06\C9\16\A6I\86\86i\89I\A6\A6\C9f
    (compressed zTXt text)
  zTXt chunk contains one or more control characters
  chunk IEND at offset 0x11fd78, length 0

Then let's decompress the string with zlib.

import zlib
print zlib.decompress("78 DA D3 D3 43 05 96 A9 06 C9 16 A6 49 86 86 69 89 49 A6 A6 C9 66 00 6D 17 07 6F".replace(" ","").decode("hex"))


w3ll done

Sunday, March 25 2012 14:47

NDH2k12 Prequals - We are looking for a real hacker - Wallpaper image

The bmp file has no padding bytes, and its size matches the image dimensions (4374054 = 810*1800*3 +0x36 for the header).
On the other hand, applying an LSB filter reveals that something is wrong on the left side of the image (the 630 first columns from the left look filled with random bits).
The three colors are affected in the same way, and the second LSB is normal. So, we certainly have an LSB encoding with one bit per byte.

The fact that the bits form a rectangle suggests the encoding was done following the image order rather than the file order. The two most logical choices (for occidentals) are left-to-right and up-to-down. I was going for the former; the grace of the random Bug made me do the latter first.

Here is how the data begin:

00 02 eb 9b 78 9c d4 b9 65 54 ...

The index of coincidence reveals a flat distribution. The data could be either encrypted or compressed. But then, the two first bytes are suspiciously low.
0x2eb9b (191387) is also very close to the rectangle size: 630*810*3 / 8 = 191362. And as it happens, 78 9C is a typical beginning for strings compressed with zlib (deflate algorithm).

Quote from :

The header byte 78 meaning “deflate compression with a 32 KiB window”.
The informational byte 9c meaning “the default compression algorithm was used” (plus a checksum).”

So all that has to be done is to extract the least significant bits in column-major (up-to-down), skip the first four bytes indicating the size of the file, and decompress the rest with zlib.

The output file is a pdf describing a few products from SCIOS. This file is the flag.

import sys, zlib,Image, struct
bmp ="sp113.bmp")
pix = bmp.load()
lsb = []
for x in range(640):
    for y in range(810):
        lsb.extend( str(i&1) for i in pix[(x,y)] )
lsb = "".join(lsb)
lsb = "".join(chr(int(lsb[i:i+8],2)) for i in range(0,len(lsb),8))
length = struct.unpack(">I",lsb[:4])[0]
pdf = zlib.decompress(lsb[4:4+length])
outfile = open("sp113.pdf","wb") #"b" is for windows users