Pular para o conteúdo
Todos os conceitos

Por dentro do ZIP

Cada arquivo de um ZIP vem com um cabeçalho local que diz nome, tamanhos e método; o índice do fim só repete isso.

O conceito Arquivos ZIP mostrou que o ZIP termina com um índice, o diretório central. Mas antes dele, cada arquivo vem precedido de um cabeçalho local com quase tudo o que é preciso para extraí-lo:

Posição Tamanho Campo
0 4 assinatura 50 4B 03 04 (PK..)
6 2 flags (bit mais baixo ligado = cifrado)
8 2 método: 00 00 guardado sem compressão, 08 00 deflate
14 4 CRC-32 do conteúdo original
18 4 tamanho comprimido
22 4 tamanho original
26 2 tamanho do nome (n)
28 2 tamanho do campo extra (m)
30 n nome do arquivo
30 + n + m ... os dados

Aqui os números ficam com o byte menos importante primeiro (little-endian): 2C 01 00 00 é 0x12C, ou 300. Os dados de um arquivo terminam onde começa o cabeçalho do próximo.

Exemplo: um cabeçalho começa na posição 200 e o nome tem 9 bytes, sem campo extra. Os dados começam em 200 + 30 + 9 = 239.

cabeçalho local dados cabeçalho local dados índice do fim: não chegou o download parou aqui 30 bytes fixos assinatura 50 4B 03 04 flags, método, CRC, tamanhos n 09 00 m 00 00 nome, 9 bytes carta.txt dados 200 230 239 os dados começam em 200 + 30 + 9 = 239
Cada arquivo do ZIP vem depois do seu cabeçalho local, com 30 bytes fixos e o nome: com o cabeçalho na posição 200 e um nome de 9 bytes, os dados começam em 239. Se o download para, falta o índice do fim, mas os cabeçalhos locais continuam lá.

Quando um download para no meio, o índice do fim não chega, e o unzip reclama que não acha o End-of-central-directory. Os cabeçalhos locais continuam lá, e há três caminhos:

  • zip -FF quebrado.zip --out consertado.zip procura os cabeçalhos locais e monta um índice novo;
  • o 7-Zip lê os cabeçalhos locais mesmo sem índice;
  • à mão: com método 8, os dados são um fluxo deflate puro. No CyberChef, recorte o trecho com Take bytes (ou descarte o começo com Drop bytes) e aplique Raw Inflate. Em Python, zlib.decompress(dados, -15) faz o mesmo (o -15 diz que não há cabeçalho zlib).

As ferramentas de reparo encontram cada arquivo procurando a assinatura 50 4B 03 04. Um cabeçalho com a assinatura danificada passa despercebido por elas, mas os outros campos continuam legíveis no editor hexadecimal.

Aparece nestes desafios