Hier sind die "restaurierten" Bilder, dank der weiteren Recherche von tillberg:
Wie erwartet gibt es alle ca. 0x4020 Bytes einen 5-Byte-Block-Marker . Das Format scheint wie folgt zu sein:
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 */
};
Nachdem der Marker gelesen wurde, bilden die nächsten marker.len
Bytes einen Block, der Teil der Datei ist. marker.notlen
ist eine Regelgröße, so dass marker.len + marker.notlen == 0xffff
. Der letzte Block ist so, dass marker.tag == 1
.
Die Struktur ist wahrscheinlich wie folgt. Es gibt noch unbekannte Werte.
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? */
};
Ich habe nicht herausgefunden, was am Ende ist, aber da PNGs das Auffüllen akzeptieren, ist es nicht zu dramatisch. Die verschlüsselte Dateigröße zeigt jedoch deutlich an, dass die letzten 4 Bytes ignoriert werden sollten ...
Da ich kurz vor Beginn der Datei nicht auf alle Blockmarkierungen zugreifen konnte, habe ich diesen Decoder geschrieben, der am Ende beginnt und versucht, die Blockmarkierungen zu finden. Es ist überhaupt nicht robust, aber gut, es hat für Ihre Testbilder funktioniert:
#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;
}
Ältere Forschung
Dies erhalten Sie, wenn Sie das Byte 0x4022
aus dem zweiten Image entfernen und dann das Byte entfernen0x8092
:
Die Bilder werden nicht wirklich „repariert“. Ich habe das durch Ausprobieren gemacht. Es wird jedoch darauf hingewiesen, dass alle 16384 Byte unerwartete Daten vorliegen. Ich vermute, dass die Bilder in einer Art Dateisystemstruktur gepackt sind und die unerwarteten Daten einfach Blockmarkierungen sind , die Sie beim Lesen der Daten entfernen sollten.
Ich weiß nicht genau, wo sich die Blockmarkierungen befinden und wie groß sie sind, aber die Blockgröße selbst beträgt mit Sicherheit 2 ^ 14 Bytes.
Es wäre hilfreich, wenn Sie auch einen hexadezimalen Speicherauszug (ein paar Dutzend Bytes) dessen bereitstellen könnten, was direkt vor dem Bild und direkt danach angezeigt wird. Dies würde Hinweise darauf geben, welche Informationen am Anfang oder Ende der Blöcke gespeichert sind.
Natürlich gibt es auch die Möglichkeit, dass Ihr Extraktionscode einen Fehler enthält. Wenn Sie einen Puffer von 16384 Bytes für Ihre Dateioperationen verwenden, würde ich zuerst dort überprüfen.