Berikut adalah gambar-gambar yang "dipulihkan", berkat penelitian lebih lanjut tillberg:
Seperti yang diharapkan, ada penanda blok 5 byte setiap sekitar 0x4020 byte. Formatnya tampaknya sebagai berikut:
struct marker {
uint8_t tag; /* 1 if this is the last marker in the file, 0 otherwise */
uint16_t len; /* size of the following block (little-endian) */
uint16_t notlen; /* 0xffff - len */
};
Setelah marker dibaca, marker.len
byte berikutnya membentuk blok yang merupakan bagian dari file.marker.notlen
adalah variabel kontrol sedemikian rupa sehingga marker.len + marker.notlen == 0xffff
. Blok terakhir adalah seperti itu marker.tag == 1
.
Strukturnya mungkin sebagai berikut. Masih ada nilai yang tidak diketahui.
struct file {
uint8_t name_len; /* number of bytes in the filename */
/* (not sure whether it's uint8_t or uint16_t) */
char name[name_len]; /* filename */
uint32_t file_len; /* size of the file (little endian) */
/* eg. "40 25 01 00" is 0x12540 bytes */
uint16_t unknown; /* maybe a checksum? */
marker marker1; /* first block marker (tag == 0) */
uint8_t data1[marker1.len]; /* data of the first block */
marker marker2; /* second block marker (tag == 0) */
uint8_t data2[marker2.len]; /* data of the second block */
/* ... */
marker lastmarker; /* last block marker (tag == 1) */
uint8_t lastdata[lastmarker.len]; /* data of the last block */
uint32_t unknown2; /* end data? another checksum? */
};
Saya belum tahu apa yang ada di akhir, tetapi karena PNG menerima bantalan, itu tidak terlalu dramatis. Namun, ukuran file yang disandikan dengan jelas menunjukkan bahwa 4 byte terakhir harus diabaikan ...
Karena saya tidak memiliki akses ke semua penanda blok tepat sebelum permulaan file, saya menulis dekoder ini yang dimulai pada bagian akhir dan mencoba untuk menemukan penanda blok. Sama sekali tidak kuat, tetapi berfungsi baik untuk gambar uji Anda:
#include <stdio.h>
#include <string.h>
#define MAX_SIZE (1024 * 1024)
unsigned char buf[MAX_SIZE];
/* Usage: program infile.png outfile.png */
int main(int argc, char *argv[])
{
size_t i, len, lastcheck;
FILE *f = fopen(argv[1], "rb");
len = fread(buf, 1, MAX_SIZE, f);
fclose(f);
/* Start from the end and check validity */
lastcheck = len;
for (i = len - 5; i-- > 0; )
{
size_t off = buf[i + 2] * 256 + buf[i + 1];
size_t notoff = buf[i + 4] * 256 + buf[i + 3];
if (buf[i] >= 2 || off + notoff != 0xffff)
continue;
else if (buf[i] == 1 && lastcheck != len)
continue;
else if (buf[i] == 0 && i + off + 5 != lastcheck)
continue;
lastcheck = i;
memmove(buf + i, buf + i + 5, len - i - 5);
len -= 5;
i -= 5;
}
f = fopen(argv[2], "wb+");
fwrite(buf, 1, len, f);
fclose(f);
return 0;
}
Penelitian yang lebih tua
Inilah yang Anda dapatkan saat menghapus byte 0x4022
dari gambar kedua, kemudian dengan menghapus byte 0x8092
:
Itu tidak benar-benar "memperbaiki" gambar; Saya melakukan ini dengan coba-coba. Namun, yang diceritakan adalah bahwa ada data yang tidak terduga setiap 16384 byte. Dugaan saya adalah bahwa gambar-gambar tersebut dikemas dalam semacam struktur sistem file dan data yang tak terduga hanyalah blokir penanda yang harus Anda hapus ketika membaca data.
Saya tidak tahu di mana tepatnya marka blok dan ukurannya, tetapi ukuran blok itu sendiri sudah pasti 2 ^ 14 byte.
Ini akan membantu jika Anda juga bisa memberikan hex dump (beberapa lusin byte) dari apa yang muncul tepat sebelum gambar dan setelahnya. Ini akan memberi petunjuk tentang jenis informasi apa yang disimpan di awal atau di akhir blok.
Tentu saja ada juga kemungkinan ada bug dalam kode ekstraksi Anda. Jika Anda menggunakan buffer 16384 byte untuk operasi file Anda, maka saya akan memeriksa dulu di sana.