Pregunta

Espero que hayas oído hablar de hack ordenado que le permite combinar un archivo JPG y un archivo Zip en un solo archivo y es un archivo válido (o al menos legible) para ambos formatos. Bueno, me di cuenta de que, dado que JPG permite cosas arbitrarias al final y ZIP al principio, puedes pegar un formato más allí, en el medio. Para los fines de esta pregunta, suponga que los datos intermedios son datos binarios arbitrarios garantizados para no entrar en conflicto con los formatos JPG o ZIP (lo que significa que no contiene el encabezado mágico zip 0x04034b50). Ilustración:

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

Estoy haciendo esto así:

  

cat " mss_1600.jpg " filea fileb   filea fileb filea fileb filea   fileb filea fileb filea fileb filea   fileb filea fileb filea fileb filea   fileb filea fileb filea fileb filea   fileb " null.bytes "   " randomzipfile.zip " > temp.zip

Esto produce un archivo de 6,318 KB. no se abre en 7-Zip. Sin embargo, cuando obtengo un 'doble' menos (así que en lugar de 13 filea y b, 12):

  

cat " mss_1600.jpg " filea fileb   filea fileb filea fileb filea   fileb filea fileb filea fileb filea   fileb filea fileb filea fileb filea   fileb filea fileb filea fileb   " nulos.bytes " " randomzipfile.zip " >   temp.zip

Produce un archivo de 5,996 KB que abre en 7-Zip.

Así que sé que mis datos binarios arbitrarios no tienen el Encabezado mágico del archivo Zip para arruinarlo. Tengo archivos de referencia de jpg + data + zip de trabajo y el no funciona jpg + data + zip (guardar porque el navegador piensa que son imágenes y agrega el extensiones zip usted mismo).

Quiero saber por qué falla con 13 combinaciones y no con 12. Para obtener puntos de bonificación, necesito solucionar esto de alguna manera.

¿Fue útil?

Solución

En realidad es una respuesta de dos partes realmente :)

En primer lugar, no importa lo que la gente diga, los archivos zip no pueden técnicamente ponerse literalmente al final de los archivos. El final del registro del directorio central tiene un valor que indica el desplazamiento de bytes desde el inicio del disco actual (si solo tiene un archivo .zip, eso significa el archivo actual). Ahora muchos procesadores ignoran esto, aunque la carpeta zip de Windows no lo hace, por lo que debe corregir ese valor para que funcione en el explorador de Windows (no es que le importe; P) Consulte Zip APPNOTE para obtener información sobre el formato de archivo. Básicamente, se encuentra en un editor hexadecimal (o escribe una herramienta) para encontrar el & "; Desplazamiento del inicio del directorio central con respecto al número de disco inicial &"; valor. Luego encuentre la primera & "; Firma del encabezado del archivo central &"; (hex de 504b0102) y establezca el valor en ese desplazamiento.

Ahora, por desgracia, eso no soluciona 7zip, pero eso se debe a la forma en que 7zip intenta adivinar el formato del archivo. Básicamente, solo buscará en el primer ~ 4MiB la secuencia binaria 504b0304, si no la encuentra, asume que no es Zip y prueba sus otros formatos de archivo. Obviamente, esta es la razón por la que agregar un archivo más rompe las cosas, lo lleva al límite de la búsqueda.

Ahora, para solucionarlo, lo que debe hacer es agregar esa cadena hexadecimal al JPEG sin romperla. Una forma de hacerlo es agregar, justo después del encabezado FFD8 JPEG SOI, los siguientes datos hexadecimales, FFEF0005504B030400. Eso agrega un bloque personalizado con su secuencia y es correcto, por lo que los encabezados jpeg simplemente deberían ignorarlo.

Otros consejos

Descargué la fuente de 7-Zip y descubrí qué está causando que esto suceda.

En CPP / 7zip / UI / Common / OpenArchive.cpp, verá lo siguiente:

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

Eso significa que solo se buscarán los primeros 4194304 bytes del archivo para el encabezado. Si no se encuentra allí, 7-Zip lo considera un archivo no válido.

Puede duplicar ese límite cambiando 1 << 22 a 1 << 23. Probé ese cambio reconstruyendo 7-Zip y funciona.

EDITAR : para solucionar este problema, puede descargar la fuente , realice el cambio anterior y compílelo. Lo construí usando VS 2008. Abra el símbolo del sistema VS, vaya a ubicación-fuente-extraída \ CPP \ 7zip \ Bundles y escriba 'nmake'. Luego, en el directorio Alone, ejecute '7za t nonworking.jpg' y debería ver 'Everything is Ok'.

Entonces, para cualquiera que encuentre esta pregunta, esta es la historia:

Sí, Andy es literalmente correcto en cuanto a por qué 7-Zip falla en el archivo, pero no ayuda a mi problema ya que no puedo hacer que la gente use MI versión de 7-Zip.

tyranid, sin embargo, me dio la solución.

  • Primero, agregar una pequeña cadena de bytes al JPG como él sugiere permitirá que 7-Zip lo abra. Sin embargo, está ligeramente alejado de un fragmento JPG válido, debe ser FFEF00 07 504B030400: la longitud estaba desactivada en 2 bytes.
  • Esto permite que 7-Zip lo abra, pero no extrae archivos, falla silenciosamente. Esto se debe a que las entradas en el directorio central tienen punteros / desplazamientos internos que apuntan a la entrada del archivo. Ya que pones un montón de cosas antes de eso, ¡debes corregir todos esos punteros!
  • Para que el zip se abra con el soporte zip integrado de Windows, necesita, como dice tyranid, corregir el desplazamiento & "; inicio del directorio central con respecto al número de disco inicial &"; Aquí hay un script de Python para hacer las dos últimas, aunque es un fragmento, no copypasta-ready-to-use

#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()

Puede producir archivos ZIP JPG + híbridos utilizando DotNetZip . DotNetZip puede guardar en una secuencia, y es lo suficientemente inteligente como para reconocer el desplazamiento original de una secuencia preexistente antes de que comience a escribir contenido zip en ella. Por lo tanto, en pseudocódigo, puede obtener un JPG + ZIP de esta manera:

 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

Todos los desplazamientos están correctamente calculados. La misma técnica se utiliza para producir un archivo autoextraíble. Puede abrir la secuencia en el EXE, luego buscar hasta el final y escribir el contenido ZIP en esa secuencia. Todos los desplazamientos se calculan correctamente si lo hace de esta manera.

Otra cosa: con respecto a uno de los comentarios en otra publicación ... ZIP puede tener datos arbitrarios al principio y al final del archivo. Hasta donde sé, no hay ningún requisito de que el directorio central de zip debe estar al final del archivo, aunque eso es típico.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top