Dưới đây là những hình ảnh được phục hồi của người Viking, nhờ vào nghiên cứu sâu hơn của Untilberg:
Như mong đợi, có một điểm đánh dấu khối 5 byte mỗi khoảng 0x4020 byte. Các định dạng dường như là như sau:
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 */
};
Khi điểm đánh dấu đã được đọc, các marker.len
byte tiếp theo tạo thành một khối là một phần của tệp. marker.notlen
là một biến điều khiển sao cho marker.len + marker.notlen == 0xffff
. Khối cuối cùng là như vậy marker.tag == 1
.
Cấu trúc có lẽ là như sau. Vẫn còn những giá trị chưa biết.
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? */
};
Tôi đã không tìm ra cuối cùng là gì, nhưng vì PNG chấp nhận phần đệm, nên nó không quá ấn tượng. Tuy nhiên, kích thước tệp được mã hóa chỉ rõ rằng 4 byte cuối cùng sẽ bị bỏ qua ...
Vì tôi không có quyền truy cập vào tất cả các điểm đánh dấu khối ngay trước khi bắt đầu tập tin, tôi đã viết bộ giải mã này bắt đầu ở cuối và cố gắng tìm các điểm đánh dấu khối. Nó không mạnh mẽ chút nào nhưng tốt, nó hoạt động cho hình ảnh thử nghiệm của bạn:
#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;
}
Nghiên cứu cũ
Đây là những gì bạn nhận được khi xóa byte 0x4022
khỏi hình ảnh thứ hai, sau đó bằng cách xóa byte 0x8092
:
Nó không thực sự sửa chữa các hình ảnh trên mạng; Tôi đã làm điều này bằng thử nghiệm và lỗi. Tuy nhiên, những gì nó nói là có dữ liệu bất ngờ cứ sau 16384 byte. Tôi đoán là các hình ảnh được đóng gói trong một số loại cấu trúc hệ thống tập tin và dữ liệu không mong muốn chỉ đơn giản là các điểm đánh dấu khối mà bạn nên loại bỏ khi đọc dữ liệu.
Tôi không biết chính xác các điểm đánh dấu khối ở đâu và kích thước của chúng, nhưng kích thước khối chắc chắn là 2 ^ 14 byte.
Sẽ rất hữu ích nếu bạn cũng có thể cung cấp kết xuất hex (vài chục byte) những gì xuất hiện ngay trước ảnh và ngay sau đó. Điều này sẽ đưa ra gợi ý về loại thông tin được lưu trữ ở đầu hoặc cuối khối.
Tất nhiên cũng có khả năng có lỗi trong mã trích xuất của bạn. Nếu bạn đang sử dụng bộ đệm 16384 byte cho các hoạt động tệp của mình, thì trước tiên tôi sẽ kiểm tra ở đó.