[PYTHON] Comment déguiser un fichier ZIP en fichier PNG

Questions fréquemment posées

Que signifie «usurper l'identité d'un fichier ZIP en tant que fichier PNG»?

À première vue, cela ressemble à un fichier PNG, et vous pouvez réellement afficher des images avec le décodeur PNG sans problème, mais si vous réécrivez l'extension en ZIP (dans le cas d'un système d'exploitation qui détermine le type de fichier par extension), il peut être traité comme un fichier ZIP Appelons un fichier ZIP déguisé en fichier PNG. En outre, la création d'un tel fichier s'appelle «usurper l'identité d'un fichier ZIP en tant que fichier PNG».

En d'autres termes, créez un fichier qui peut être utilisé à la fois comme fichier PNG et comme fichier ZIP.

Fondamentalement, il est censé usurper une combinaison d'un petit fichier PNG existant et d'un petit fichier ZIP existant.

D'un autre point de vue, il est possible de déguiser un fichier PNG en fichier ZIP.

Puis-je déguiser n'importe quel ZIP?

Il y a quelques restrictions.

De plus, si vous modifiez le fichier au format PNG ou ZIP (filtrage des images avec PNG, ajout / suppression de fichiers avec ZIP, etc.), il y a de fortes chances que vous ne puissiez pas l'utiliser comme un faux fichier après cela.

Il peut y avoir diverses autres restrictions d'implémentation.

Quels sont les avantages du déguisement?

Je ne sais pas.

Structure de base du fichier ZIP et méthode d'emprunt d'identité 1

Je n'entrerai pas dans les spécifications détaillées du format de fichier ZIP. Ignorez également ZIP64 et divisez le ZIP.

La structure de base d'un fichier ZIP peut être facilement comprise en la suivant à partir de la «Fin du répertoire central» (ci-après «EOCD») vers la fin du fichier.

«EOCD» a la position de «Répertoire central» (ci-après «CEN»), c'est-à-dire le décalage depuis le début du fichier. De plus, «CEN» existe pour le nombre de fichiers dans l'archive, et chaque «CEN» a la position (décalage) de «En-tête de fichier local» (ci-après «LOC»).

Le LOC est suivi du corps du fichier (compressé, non compressé, chiffré, texte brut, etc.). J'ai omis diverses explications.

zip_format.png

Avec cette structure, même s'il y a des données au début ou à la fin du fichier ZIP, ou entre chaque donnée, elles peuvent être traitées normalement comme un fichier ZIP.

À titre d'exemple spécifique, un fichier ZIP auto-extractible (fichier EXE) peut être traité comme un fichier ZIP normal par la plupart des archiveurs ZIP. D'un point de vue différent, le fichier ZIP auto-extractible peut être traité à la fois comme un fichier EXE et un fichier ZIP.

En raison de ces caractéristiques, même si le fichier ZIP entier est stocké dans un autre fichier, il peut être traité comme un fichier ZIP normal.

Cependant, lors de l'incorporation d'un fichier ZIP existant dans un autre fichier, il est nécessaire de corriger correctement la partie qui a le décalage depuis le début du fichier. Les points de correction spécifiques sont le décalage «CEN» dans «EOCD» et le décalage «LOC» dans chaque «CEN». (Si vous avez des données étendues pour ZIP64, il peut y avoir un décalage là aussi, mais cette fois je l'ignorerai)

À propos, l'ordre des octets des fichiers ZIP est un peu tondien.

Structure de base du fichier PNG et méthode d'emprunt d'identité 2

Je n'entrerai pas dans les spécifications détaillées du format de fichier PNG.

La structure de base de PNG est qu'il a une signature de fichier PNG de 8 octets au début, suivie de plusieurs morceaux. Certains blocs sont obligatoires et certains sont facultatifs (blocs auxiliaires). Certains morceaux ont un ordre fixe (par exemple, les morceaux ʻIHDR sont au début, les morceaux ʻIEND sont à la fin, etc.), mais d'autres sont dans n'importe quel ordre.

png_format.png

Chaque bloc se compose de «longueur (4 octets)», «type de bloc (4 octets)», «données de bloc (nombre arbitraire d'octets)» et «CRC (4 octets)». L'ordre des octets est big endian.

"Longueur" indique la longueur des "données de bloc" ("longueur" elle-même n'inclut pas le "type de bloc" et "CRC"). La valeur maximale est de 2 $ ^ {31} -1 $ octets. «CRC» est la valeur obtenue en calculant CRC32 pour la plage de «type de bloc» et de «données de bloc».

png_chunk.png

Le type de bloc est composé de 4 caractères alphabétiques en code ASCII. Il est sensible à la casse. (Dans les spécifications, il est dit qu'elles devraient être traitées comme des données binaires au lieu d'être traitées comme des caractères, mais elles seront décrites sur la base des caractères dans un souci de simplicité d'explication.)

De plus, la signification est différente selon les majuscules et les minuscules de chaque chiffre (dans les spécifications, juger par on / off du 5ème bit).

chiffre Nom du 5ème bit lettre majuscule(off) Minuscule(on)
1er chiffre Bit auxiliaire Morceau obligatoire Bloc auxiliaire
2ème chiffre Bit privé Morceau public Morceau privé
3e chiffre Bits réservés (pour une extension future) (Capital fixe) (N'utilisez pas de minuscules)
4e chiffre Bit copiable Ne peut pas être copié lorsque l'image est modifiée Peut être copié lorsque l'image est modifiée

Des morceaux obligatoires sont nécessaires pour afficher l'image, donc si le décodeur PNG rencontre un morceau requis inconnu, ce sera une erreur. Inversement, si vous rencontrez un bloc auxiliaire inconnu, vous pouvez l'ignorer.

Les blocs publics sont des blocs enregistrés dans les spécifications et les listes de blocs publics, et les blocs privés sont utilisés comme des blocs uniques à l'application. En général, je pense que vous avez besoin d'un garde capable de gérer les conflits entre les blocs privés.

Contrairement aux autres bits, le bit copiable indique si un morceau inconnu peut être copié tel quel lorsque l'image est traitée avec un éditeur PNG (un programme qui filtre les fichiers PNG, etc.) au lieu d'un décodeur PNG. ..

Cette fois, je voudrais créer mon propre "morceau qui stocke les fichiers ZIP" en tant que bloc auxiliaire. N'importe quel type de bloc est correct, mais comme il s'agit d'un "fragment de conteneur ZIP", je vais essayer de le faire ziPc. Je vais créer l'emplacement juste après le bloc ʻIHDR`. La taille du fichier ZIP emprunté doit être inférieure à 2 Go, car l'intégralité du fichier ZIP doit être stockée dans le bloc.

De plus, la raison pour laquelle le "fragment de conteneur ZIP" est placé immédiatement après le bloc ʻIHDR est que le bloc ʻIHDR a une longueur fixe et il est très probable que l'offset du fichier ZIP ne se déplacera pas même après avoir été traité par l'éditeur PNG. est. Bien sûr, cela ne fonctionne pas si vous insérez un autre bloc entre le bloc ʻIHDRet le blocziPc, ou si vous supprimez le bloc ziPc`.

Procédure d'usurpation d'identité

Enfin, organisez la procédure d'usurpation d'identité. Supposons que vous souhaitiez générer un faux fichier basé sur un fichier ZIP et un fichier PNG existants.

  1. Sortez la signature du fichier PNG
  2. Exportez le bloc IHDR d'un fichier PNG existant
  3. Exportez la taille du fichier ZIP existant (morceau de conteneur ZIP "longueur")
  4. Sortez le «type de bloc» «ziPc» du bloc de conteneur ZIP
  5. Sortie avant CEN du fichier ZIP existant (" chunk data "à partir d'ici)
  6. Sortie (répétition) tout en corrigeant le CEN du fichier ZIP existant
  7. Copiez tout ce qui se trouve entre la fin de «CEN» et «EOCD» dans le fichier ZIP existant
  8. Corriger et afficher «EOCD» du fichier ZIP existant
  9. Copiez tout ce qui suit ʻEOCD` dans le fichier ZIP existant (jusqu'ici "chunk data")
  10. Calculer et générer le CRC32 du «type de bloc» aux «données de bloc» ci-dessus («CRC» du bloc de conteneur ZIP)
  11. Tout afficher après le bloc IHDR du fichier PNG existant

c'est tout.

Exemple d'implémentation

Il n'y a pas de processus particulièrement difficile (le plus difficile est le calcul de CRC32), donc si vous pouvez faire fonctionner le fichier binaire, je pense qu'il peut être implémenté dans n'importe quelle langue.

Notez que ZIP est Little Endian et PNG est Big Endian.

Pour le moment, j'ai donné un exemple implémenté en java / javascript / python sur github.

Recommended Posts

Comment déguiser un fichier ZIP en fichier PNG
Comment créer un fichier de configuration
Comment utiliser un fichier autre que .fabricrc comme fichier de configuration
[Python] Comment stocker un fichier csv en tant que données de tableau à une dimension
Comment lire un fichier CSV avec Python 2/3
Comment créer un fichier JSON en Python
Comment lire des fichiers dans différents répertoires
Comment afficher DataFrame sous forme de tableau dans Markdown
Comment transformer un fichier .py en fichier .exe
Comment convertir un spectrogramme Mel en un fichier wav
Comment appeler une fonction
Télécharger un fichier sur Dropbox
Comment pirater un terminal
Comment utiliser Fujifilm X-T3 comme webcam sur Ubuntu 20.04
Comment mettre un lien hypertexte vers "file: // hogehoge" avec sphinx-> pdf
Comment exécuter un fichier Python à une invite de commande Windows 10
Comment importer NoteBook en tant que module dans Jupyter (IPython)
Comment importer des fichiers où vous le souhaitez en Python
Comment imprimer des caractères sous forme de tableau avec la fonction d'impression de Python
Comment utiliser cuML SVC comme classificateur CV Gridsearch
Comment enregistrer un package dans PyPI (à partir de septembre 2017)
[Python] Comment générer une table pandas dans un fichier Excel
Comment importer NoteBook en tant que module dans Jupyter (IPython)
Comment utiliser la fonction zip
Comment mettre un lien symbolique
Comment créer un bot slack
Comment créer un package Conda
Écrire la sortie standard dans un fichier
Comment créer un robot - Avancé
Comment créer une fonction récursive
Comment créer un pont virtuel
Comment créer un Dockerfile (basique)
[Blender] Comment créer un plug-in Blender
Comment supprimer un conteneur Docker
Comment créer un robot - Basic
Comment utiliser la fonction zip de python
Comment coller un fichier CSV dans un fichier Excel à l'aide de Pandas
Créez un fichier temporaire avec django sous forme de zip et renvoyez-le
Comment faire une commande pour lire le fichier de paramètres avec pyramide
Comment spécifier un fichier .py à charger au démarrage dans IPython 0.13
Comment afficher le résultat de sortie de la commande man Linux dans un fichier
Comment bien définir Jupytext lors de la gestion du code en équipe
Comment créer un fichier factice CSV contenant du japonais à l'aide de Faker
Comment déployer une application Web sur Alibaba Cloud en tant que pigiste
Comment obtenir un ingénieur de la trentaine
[ROS2] Comment lire un fichier bag avec le lancement au format python
[Python] Comment récupérer un fichier html local et le générer au format CSV à l'aide de Beautiful Soup
[Python] Comment convertir un fichier db en csv
Comment rendre le sélénium aussi léger que possible
Comment créer un clone depuis Github
Comment diviser et enregistrer un DataFrame
Comment créer un environnement de traduction sphinx
Comment créer un dossier git clone
Qiita (1) Comment écrire un nom de code
Comment ajouter un package avec PyCharm
[Python] Comment rendre une classe itérable
Comment dessiner un graphique avec Matplotlib
[Python] Comment convertir une liste bidimensionnelle en liste unidimensionnelle
Comment convertir Python en fichier exe