Writeup c0rrupt

picoCTF 2019

Posted by rmn0x01 on Saturday, November 2, 2019

We found this file. Recover the flag

Intro

File yang diberikan berupa

$ file mystery 
mystery: data

TLDR

  1. Perbaiki file-header
  2. Perbaiki chunks
  3. Get the flag

Full Steps

Hint yang diberikan adalah

Try fixing the file header

Sehingga langkah pertama yang dilakukan adalah menganalisis hex-value-nya menggunakan hex editor atau hex viewer, disini saya menggunakan Bless Bless

Delapan bytes pertama terlihat seperti membentuk file header PNG namun tidak sempurna, sehingga diubah ke file header PNG yang benar

Dari

89 65 4E 34 0D 0A B0 AA

Ke

89 50 4E 47 0D 0A 1A 0A

Pengecekan dengan command file masih belum berubah, namun dengan pngcheck terdapat informasi lain

$ pngcheck -v mystery 
File: mystery (202940 bytes)
  invalid chunk name "C"DR" (43 22 44 52)
ERRORS DETECTED in mystery

Berdasarkan referensi [1], diketahui bahwa:

The PNG datastream consists of a PNG signature (see 5.2: PNG signature) followed by a sequence of chunks. Each chunk has a chunk type which specifies its function. This clause defines the PNG chunk types standardized in this International Standard

Dengan Critical Chunks dari PNG adalah:

  1. IHDR: image header, which is the first chunk in a PNG datastream.
  2. PLTE: palette table associated with indexed PNG images.
  3. IDAT: image data chunks.
  4. IEND: image trailer, which is the last chunk in a PNG datastream.

Berdasarkan informasi tersebut, diasumsikan invalid chunk name C”DR seharusnya IHDR, ubah kembali menggunakan Bless Bless 2

Kini file mystery telah terbaca, meskipun belum dapat dilihat gambarnya karena masih terdapat error lain

$ file mystery 
mystery: PNG image data, 1642 x 1095, 8-bit/color RGB, non-interlaced
$ pngcheck -v mystery 
File: mystery (202940 bytes)
  chunk IHDR at offset 0x0000c, length 13
    1642 x 1095 image, 24-bit RGB, non-interlaced
  chunk sRGB at offset 0x00025, length 1
    rendering intent = perceptual
  chunk gAMA at offset 0x00032, length 4: 0.45455
  chunk pHYs at offset 0x00042, length 9: 2852132389x5669 pixels/meter
  CRC error in chunk pHYs (computed 38d82c82, expected 495224f0)
ERRORS DETECTED in mystery

Masih berdasarkan referensi [1], diketahui bahwa layout sebuah chunk adalah:

  • 4-bytes Length
  • 4-bytes Chunk Type
  • x-bytes Chunk Data (x tergantung Length yang didefinisikan sebelumnya)
  • 4-bytes Cyclic Redundancy Cycle (CRC)

Berdasarkan error message terdapat kesalahan di CRC milik chunk pHYs, namun jika diteliti lebih lanjut terdapat angka yang terlalu besar di chunk pHYs tersebut, yaitu 2852132389, sehingga inisiatif yang dilakukan adalah mengubah ukuran tersebut menjadi 5669 daripada memperbaiki CRC-nya. Cari layout chunk data milik pHYs (offset 00000046), ubah dari

AA 00 16 25

karena 0xaa001625 = 2852132389 menjadi

00 00 16 25

0x00001625 = 5669

Simpan, kemudian cek kembali error message-nya

$ pngcheck -v mystery 
File: mystery (202940 bytes)
  chunk IHDR at offset 0x0000c, length 13
    1642 x 1095 image, 24-bit RGB, non-interlaced
  chunk sRGB at offset 0x00025, length 1
    rendering intent = perceptual
  chunk gAMA at offset 0x00032, length 4: 0.45455
  chunk pHYs at offset 0x00042, length 9: 5669x5669 pixels/meter (144 dpi)
:  invalid chunk length (too large)
ERRORS DETECTED in mystery

Terdapat error message invalid chunk length namun tidak disebutkan chunk yang error, analisis bytes setelah chunk pHYs berakhir melalui Bless didapatkan:

Bytes penanda chunk length

AA AA FF A5

dan Bytes penanda chunk type

AB 44 45 54

Chunk Type 0xab444554 = \xabDET tidak dikenali sebagai chunk type dari PNG, dan diasumsikan paling mendekati adalah Chunk IDAT, sehingga diubah menjadi 0x49444154

Untuk chunk length 0xaaaaffa5 = 2863333285 diasumsikan terlalu besar, sehingga perlu diubah. Berdasarkan referensi [1], tertera bahwa:

There can be multiple IDAT chunks; if so, they must appear consecutively with no other intervening chunks.

Sehingga, untuk memperbaiki chunk length perlu dicari chunk IDAT lainnya, kemudian dihitung selisihnya. Apabila tidak ada chunk IDAT lain, selisih yang dicari adalah dengan chunk IEND. Analisis dari Bless, terdapat total 4 chunk IDAT dimana IDAT pertama (yang sedang diperbaiki) berada pada offset 0x00057, sedangkan IDAT kedua berada pada offset 0x10008. Selisih keduanya adalah

0x10008 - 0x00057 = 0xFFB1

0xFFB1 masih harus dikurangi dengan bytes length dari IDAT 1 (4 bytes), CRC dari IDAT 1 (4 bytes) dan chunk type dari IDAT 2 (4 bytes), sehingga total 12 bytes

0xFFB1 - 0xC = 0xFFA5

0xFFA5 merupakan length dari IDAT pertama, sehingga edit kembali bytes penanda length IDAT pertama dari

AA AA FF A5

menjadi

00 00 FF A5

Hasil dari pngcheck menandakan tidak ada error lagi

$ pngcheck -v mystery 
File: mystery (202940 bytes)
  chunk IHDR at offset 0x0000c, length 13
    1642 x 1095 image, 24-bit RGB, non-interlaced
  chunk sRGB at offset 0x00025, length 1
    rendering intent = perceptual
  chunk gAMA at offset 0x00032, length 4: 0.45455
  chunk pHYs at offset 0x00042, length 9: 5669x5669 pixels/meter (144 dpi)
  chunk IDAT at offset 0x00057, length 65445
    zlib: deflated, 32K window, fast compression
  chunk IDAT at offset 0x10008, length 65524
  chunk IDAT at offset 0x20008, length 65524
  chunk IDAT at offset 0x30008, length 6304
  chunk IEND at offset 0x318b4, length 0
No errors detected in mystery (9 chunks, 96.3% compression).

Sehingga file mystery dapat dibuka mystery

Flag

picoCTF{c0rrupt10n_1847995}

References

  1. https://www.w3.org/TR/PNG