
MD5-Monomorphic Shellcode Packer - toutes les charges utiles ont le même hachage MD5
════════════════════════════════════╦═══
╔═╦═╗ ╔═╗ ╔═╗ ╔═╗ ╔═╦═╗ ╔═╗ ╔══╔═╗ ╠═╗
═╩ ╩ ╩═╚═╝═╩ ╩═╚═╝═╩ ╩ ╩═╚═╝═╩ ╠═╝═╩ ╩═
════════════════════════════════╩═══════
Par Retr0id
═══ Packeur de Shellcode Monomorphe MD5 ═══
UTILISATION : python3 monomorph.py fichier_entrée fichier_sortie [fichier_payload]
## Que fait-il ?
Il compacte jusqu'à 4 Ko de shellcode compressé en un binaire exécutable, quasi instantanément. Le fichier de sortie aura *toujours* le même hash MD5 : `3cebbe60d91ce760409bbe513593e401`
Actuellement, seul Linux x86-64 est supporté. Il serait trivial de porter cette technique à d'autres plateformes, bien que chaque version aboutirait à un MD5 différent. Il serait également possible d'utiliser un fichier polyglotte multi-plateforme comme [APE](https://justine.lol/ape.html).
Exemple d'utilisation :
$ python3 monomorph.py bin/monomorph.linux.x86-64.benign bin/monomorph.linux.x86-64.meterpreter sample_payloads/bin/linux.x64.meterpreter.bind_tcp.bin
## Pourquoi ?
Des gens ont [déjà](https://www.mscs.dal.ca/~selinger/md5collision/) utilisé des collisions uniques pour basculer un binaire entre les modes « bon » et « malin ». Monomorph pousse ce concept au niveau supérieur.
Certaines personnes insistent encore pour utiliser MD5 pour référencer des échantillons de fichiers, pour diverses raisons qui m'échappent. Si l'une de ces personnes finit par enquêter sur du code emballé avec Monomorph, elle va être très confuse.
## Comment ça marche ?
Pour chaque bit que nous voulons encoder, un bloc MD5 en collision a été précalculé avec [FastColl](https://github.com/cr-marcstevens/hashclash/tree/master/src/md5fastcoll). Comme résumé [ici](https://github.com/corkami/collisions/tree/master/hashquines#read-an-encoded-value), chaque collision nous donne une paire de blocs que nous pouvons échanger sans modifier le hash MD5 global. Le chargeur vérifie quel bloc a été choisi à l'exécution pour décoder le bit.
Pour encoder 4 Ko de données, nous devons générer 4\*1024\*8 collisions (ce qui prend quelques heures), occupant 4 Mo d'espace dans le fichier final.
Pour accélérer le processus, j'ai apporté quelques petites modifications à FastColl pour le rendre encore plus rapide en pratique, permettant de l'exécuter en parallèle. Je suis sûr qu'il existe des moyens plus intelligents de paralléliser, mais mon approche naïve consiste à lancer N instances simultanément et attendre que la première se termine, puis tuer toutes les autres.
Comme j'ai déjà effectué le pré-calcul, reconfigurer le payload peut se faire quasi instantanément. L'échange de l'état des blocs précalculés est effectué à l'aide [d'une technique](https://github.com/corkami/collisions/blob/master/hashquines/scripts/collisions.py) implémentée par Ange Albertini.
## Est-ce détectable ?
Oui. Ce n'est pas très furtif, et ce n'est pas l'intention. Vous pouvez détecter les blocs de collision avec [detectcoll](https://github.com/cr-marcstevens/hashclash/tree/collisiondetection/src/collisiondetection).