
MD5-Monomorphic Shellcode Packer - todos los payloads tienen el mismo hash MD5
════════════════════════════════════╦═══
╔═╦═╗ ╔═╗ ╔═╗ ╔═╗ ╔═╦═╗ ╔═╗ ╔══╔═╗ ╠═╗
═╩ ╩ ╩═╚═╝═╩ ╩═╚═╝═╩ ╩ ╩═╚═╝═╩ ╠═╝═╩ ╩═
════════════════════════════════╩═══════
Por Retr0id
═══ MD5-Monomorphic Shellcode Packer ═══
USO: python3 monomorph.py archivo_entrada archivo_salida [archivo_payload]
## ¿Qué hace?
Empaqueta hasta 4KB de shellcode comprimido en un binario ejecutable, casi al instante. El archivo de salida *siempre* tendrá el mismo hash MD5: `3cebbe60d91ce760409bbe513593e401`
Actualmente, solo se admite Linux x86-64. Sería trivial portar esta técnica a otras plataformas, aunque cada versión terminaría con un MD5 diferente. También sería posible usar un archivo políglota multiplataforma como [APE](https://justine.lol/ape.html).
Ejemplo de uso:
$ python3 monomorph.py bin/monomorph.linux.x86-64.benign bin/monomorph.linux.x86-64.meterpreter sample_payloads/bin/linux.x64.meterpreter.bind_tcp.bin
## ¿Por qué?
Anteriormente, la gente ha [usado](https://www.mscs.dal.ca/~selinger/md5collision/) colisiones individuales para alternar un binario entre modos "bueno" y "malo". Monomorph lleva este concepto al siguiente nivel.
Algunas personas todavía insisten en usar MD5 para referenciar muestras de archivos, por varias razones que no me resultan lógicas. Si alguna de estas personas termina investigando código empaquetado con Monomorph, se va a confundir mucho.
## ¿Cómo funciona?
Por cada bit que queremos codificar, se ha precalculado un bloque MD5 colisionante usando [FastColl](https://github.com/cr-marcstevens/hashclash/tree/master/src/md5fastcoll). Como se resume [aquí](https://github.com/corkami/collisions/tree/master/hashquines#read-an-encoded-value), cada colisión nos da un par de bloques que podemos intercambiar sin cambiar el hash MD5 general. El cargador verifica qué bloque fue elegido en tiempo de ejecución para decodificar el bit.
Para codificar 4KB de datos, necesitamos generar 4\*1024\*8 colisiones (lo que lleva unas horas), ocupando 4MB de espacio en el archivo final.
Para acelerar esto, hice pequeñas modificaciones a FastColl para que sea aún más rápido en la práctica, permitiendo ejecutarlo en paralelo. Estoy seguro de que hay formas más inteligentes de paralelizarlo, pero mi enfoque ingenuo es iniciar N instancias simultáneamente y esperar a que la primera termine, luego matar a todas las demás.
Como ya he realizado el pre-cálculo, reconfigurar el payload se puede hacer casi al instante. Intercambiar el estado de los bloques precalculados se hace usando [una técnica](https://github.com/corkami/collisions/blob/master/hashquines/scripts/collisions.py) implementada por Ange Albertini.
## ¿Es detectable?
Sí. No es muy sigiloso, ni pretende serlo. Puedes detectar los bloques de colisión usando [detectcoll](https://github.com/cr-marcstevens/hashclash/tree/collisiondetection/src/collisiondetection).