Проблема с комбинацией файлов JPG + Zip в формате Zip

StackOverflow https://stackoverflow.com/questions/1820291

  •  10-07-2019
  •  | 
  •  

Вопрос

Надеюсь, вы слышали о аккуратный взлом это позволяет вам объединить JPG и Zip-файлы в один файл, и это допустимый (или, по крайней мере, читаемый) файл для обоих форматов.Ну, я понял, что поскольку JPG допускает произвольный формат в конце, а ZIP - в начале, вы могли бы вставить туда еще один формат - в середине.Для целей этого вопроса предположим, что промежуточные данные представляют собой произвольные двоичные данные, которые гарантированно не конфликтуют с форматами JPG или ZIP (это означает, что они не содержат волшебного заголовка zip 0x04034b50).Иллюстрация:

0xFFD8 <- start jpg data end -> 0xFFD9 ... ARBITRARY BINARY DATA ... 0x04034b50 <- start zip file ... EOF

Я играю в кошки-мышки вот так:

кошка "mss_1600.jpg " filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea файл filea файл filea fileb filea файл "null.bytes" "randomzipfile.zip" > temp.zip

В результате получается файл размером 6318 КБ.IT не делает застегивается на 7-дюймовую молнию.Однако, когда я получаю на один "double" меньше (таким образом, вместо 13 filea и b, 12):

кошка "mss_1600.jpg " filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea fileb filea файлеб файлеа файлеб файлеа файлеб "null.байты" "randomzipfile.zip" > temp.zip

Он создает файл размером 5,996 КБ, который делает застегивается на 7-дюймовую молнию.

Итак, я знаю, что в моих произвольных двоичных данных нет волшебного заголовка Zip-файла, который мог бы их испортить.У меня есть справочные файлы по рабочий jpg + данные +zip и тот нерабочий jpg + данные +zip (сохранить как, потому что браузер считает, что это изображения, и добавьте расширения zip самостоятельно).

Я хочу знать, почему он терпит неудачу с 13 комбинациями и не работает с 12.Чтобы получить бонусные баллы, мне нужно как-то обойти это.

Это было полезно?

Решение

На самом деле это ответ из двух частей :)

Во-первых, независимо от того, что говорят люди, zip-файлы нельзя технически дословно поместить в конец файлов. Конец записи центрального каталога имеет значение, которое указывает смещение в байтах от начала текущего диска (если у вас есть только один файл .zip, это означает текущий файл). Сейчас многие процессоры игнорируют это, хотя папка zip в Windows этого не делает, поэтому вам нужно исправить это значение, чтобы оно работало в проводнике Windows (не то, чтобы вы заботились об этом; P) См. Zip APPNOTE для получения информации о формате файла. По сути, вы находите в шестнадцатеричном редакторе (или пишете инструмент), чтобы найти смещение & Начала центрального каталога относительно номера начального диска & Quot; значение. Затем найдите первую & Quot; центральную подпись заголовка файла & Quot; (hex 504b0102) и установите значение для этого смещения.

Теперь, увы, это не исправляет 7zip, но это связано с тем, как 7zip пытается угадать формат файла. По сути, он будет искать только первые 4MiB двоичной последовательности 504b0304, если он не найдет ее, то предположит, что это не Zip, и попробует другие форматы архивов. Именно поэтому добавление еще одного файла ломает вещи, оно выдвигает его за предел для поиска.

Теперь, чтобы исправить это, вам нужно добавить шестнадцатеричную строку в jpeg, не нарушая ее. Один из способов сделать это - добавить сразу после заголовка FFD8 JPEG SOI следующие шестнадцатеричные данные, FFEF0005504B030400. Это добавляет пользовательский блок с вашей последовательностью и является правильным, поэтому заголовки jpeg должны просто игнорировать его.

Другие советы

Я скачал исходники для 7-Zip и выяснил, что является причиной этого.

В CPP / 7zip / UI / Common / OpenArchive.cpp вы увидите следующее:

// Static-SFX (for Linux) can be big.
const UInt64 kMaxCheckStartPosition = 1 << 22;

Это означает, что только первые 4194304 байта файла будут искать заголовок. Если он там не найден, 7-Zip считает его неверным файлом.

Вы можете удвоить этот лимит, изменив 1 << 22 на 1 << 23. Я проверил это изменение, перестроив 7-Zip, и он работает.

РЕДАКТИРОВАТЬ . Чтобы обойти эту проблему, вы можете загрузить исходный код. внесите указанные выше изменения и создайте их. Я построил его с использованием VS 2008. Откройте командную строку VS, перейдите в extract-source-location \ CPP \ 7zip \ Bundles и введите «nmake». Затем в каталоге Alone запустите «7za t nonworking.jpg», и вы должны увидеть «Все в порядке».

Итак, для всех, кто еще задается этим вопросом, вот история:

Да, Энди буквально прав относительно того, почему 7-Zip не работает с файлом, но это не помогает моей проблеме, поскольку я точно не могу заставить людей использовать мою версию 7-Zip.

однако тиранид подсказал мне решение.

  • Во-первых, добавление небольшой байтовой строки в JPG, как он предлагает, позволит 7-Zip открыть его.Однако он немного отличается от допустимого фрагмента JPG, он должен быть FFEF00 07 504B030400 - длина была уменьшена на 2 байта.
  • Это позволяет 7-Zip открывать его, но не извлекать файлы, он завершается беззвучно.Это связано с тем, что записи в центральном каталоге имеют внутренние указатели / смещения, которые указывают на запись файла.Поскольку вы поместили перед этим кучу всего, вам нужно исправить все эти указатели!
  • Чтобы открыть zip-файл со встроенной поддержкой zip в Windows, вам необходимо, как говорит tyranid, исправить "смещение начала центрального каталога относительно номера начального диска".Вот скрипт на Python для выполнения последних двух, хотя это фрагмент, а не копипаста, готовый к использованию

#Now we need to read the file and rewrite all the zip headers.  Fun!
torewrite = open(magicfilename, 'rb')
magicdata = torewrite.read()
torewrite.close()

#Change the Central Repository's Offset
offsetOfCentralRepro = magicdata.find('\x50\x4B\x01\x02') #this is the beginning of the central repo
start = len(magicdata) - 6 #it so happens, that on my files, the point is stored 2 bytes from the end.  so datadatadatdaata OF FS ET !! 00 00 EOF where OFFSET!! is the 4 bytes 00 00 are the last two bytes, then EOF
magicdata = magicdata[:start] + pack('I', offsetOfCentralRepro) + magicdata[start+4:]

#Now change the individual offsets in the central directory files
startOfCentralDirectoryEntry = magicdata.find('\x50\x4B\x01\x02', 0) #find the first central directory entry
startOfFileDirectoryEntry = magicdata.find('\x50\x4B\x03\x04', 10) #find the first file entry (we start at 10 because we have to skip past the first fake entry in the jpg)
while startOfCentralDirectoryEntry > 0:
    #Now I move a magic number of bytes past the entry (really! It's 42!)
    startOfCentralDirectoryEntry = startOfCentralDirectoryEntry + 42

    #get the current offset just to output something to the terminal
    (oldoffset,) = unpack('I', magicdata[startOfCentralDirectoryEntry : startOfCentralDirectoryEntry+4])
    print "Old Offset: ", oldoffset, " New Offset: ", startOfFileDirectoryEntry , " at ", startOfCentralDirectoryEntry
    #now replace it
    magicdata = magicdata[:startOfCentralDirectoryEntry] + pack('I', startOfFileDirectoryEntry) + magicdata[startOfCentralDirectoryEntry+4:]

    #now I move to the next central directory entry, and the next file entry
    startOfCentralDirectoryEntry = magicdata.find('\x50\x4B\x01\x02', startOfCentralDirectoryEntry)
    startOfFileDirectoryEntry = magicdata.find('\x50\x4B\x03\x04', startOfFileDirectoryEntry+1)

#Finally write the rewritten headers' data
towrite = open(magicfilename, 'wb')
towrite.write(magicdata)
towrite.close()

Вы можете создавать гибридные файлы JPG + ZIP, используя DotNetZip . DotNetZip может сохранять данные в потоке, и он достаточно умен, чтобы распознавать исходное смещение ранее существовавшего потока, прежде чем он начнет записывать в него содержимое ZIP. Поэтому в псевдокоде вы можете получить JPG + ZIP следующим образом:

 open stream on an existing JPG file for update
 seek to the end of that stream
 open or create a zip file
 call ZipFile.Save to write zip content to the JPG stream
 close

Все смещения правильно рассчитаны. Эта же техника используется для создания самораспаковывающегося архива. Вы можете открыть поток в EXE-файле, затем перейти к концу и записать содержимое ZIP в этот поток. Все смещения правильно рассчитаны, если вы сделаете это таким образом.

Другое дело - в отношении одного из комментариев в другом посте ... ZIP может содержать произвольные данные в начале и в конце файла. Насколько я знаю, требования нет, поскольку центральный каталог zip должен находиться в конце файла, хотя это типично.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top