İşte tillberg'in daha fazla araştırması sayesinde “restore edilmiş” görüntüler:
Beklendiği gibi, her 0x4020 baytta bir 5 baytlık blok işaretleyici vardır . Biçim şu şekildedir:
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 */
};
İşaretçi okunduktan sonra, sonraki marker.len
baytlar dosyanın parçası olan bir blok oluşturur. marker.notlen
kontrol değişkenidir marker.len + marker.notlen == 0xffff
. Son blok öyle marker.tag == 1
.
Yapı muhtemelen aşağıdaki gibidir. Hala bilinmeyen değerler var.
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? */
};
Sonunda ne olduğunu anlayamadım, ancak PNG'ler dolguyu kabul ettiğinden, çok dramatik değil. Ancak, kodlanmış dosya boyutu açıkça son 4 baytın göz ardı edilmesi gerektiğini gösterir ...
Dosyanın başlangıcından hemen önce tüm blok işaretleyicilerine erişimim olmadığından, sonunda başlayan ve blok işaretleyicilerini bulmaya çalışan bu kod çözücüyü yazdım. Hiç sağlam değil ama iyi, test görüntüleriniz için çalıştı:
#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;
}
Daha eski araştırmalar
Bayt 0x4022
ikinci görüntüden kaldırılırken, ardından bayt kaldırılırken elde ettiğiniz budur 0x8092
:
Görüntüleri gerçekten “onarmaz”; Bunu deneme yanılma yoluyla yaptım. Bununla birlikte, her 16384 baytta beklenmedik veriler olduğu söylenir. Tahminim, görüntülerin bir tür dosya sistemi yapısında paketlenmesidir ve beklenmedik veriler sadece blok işaretleyicilerdir verileri okurken kaldırmanız gereken .
Blok işaretleyicilerinin tam olarak nerede olduğunu ve boyutlarını bilmiyorum, ancak blok boyutunun kendisi kesinlikle 2 ^ 14 bayt.
Ayrıca, görüntünün hemen öncesinde ve hemen sonrasında görünenlerin onaltılık dökümünü (birkaç düzine bayt) da sağlamanızda yardımcı olur. Bu, blokların başında veya sonunda ne tür bilgilerin saklandığı hakkında ipuçları verecektir.
Tabii ki çıkarma kodunuzda bir hata da olabilir. Dosya işlemleri için 16384 baytlık bir arabellek kullanıyorsanız, önce orayı kontrol ederim.