Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
xspawn — Lanza programas de macOS a través de la interfaz XPC privada de launchd sin ejecutarlos mediante exec, haciendo que el EDR registre a launchd como proceso padre. Admite trabajos one-shot, KeepAlive y basados en plist. | Kitploit
Herramientas/GitHubGitHub/cenobyte-vincit/xspawn
Mecanismos de PersistenciaEvasión de IDS/IPSPost-ExplotaciónRed TeamingAtaque Adversario
GitHubcenobyte-vincit/xspawn

xspawn

Lanza programas de macOS a través de la interfaz XPC privada de launchd sin ejecutarlos mediante exec, haciendo que el EDR registre a launchd como proceso padre. Admite trabajos one-shot, KeepAlive y basados en plist.

Ver Repositorio
48hace 2 mesesAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

xspawn

xspawn inicia un programa en macOS a través de launchd y nunca ejecuta (exec) ese programa por sí mismo. El objetivo es que un EDR registre a launchd como el proceso padre, no esta herramienta ni el shell que la invoca.

por cenobyte [email protected] 2026

https://github.com/cenobyte-vincit/xspawn

Resumen

xspawn abre xpc_pipe_create_from_port(bootstrap_port) y arranca (bootstraps) la ejecución de un programa a través de _xpc_pipe_interface_routine, la misma tubería XPC privada que usa launchctl, y nunca ejecuta (exec) el programa por sí mismo.

  • Se rechaza la ejecución como root. No existe modo para otro UID.
  • Una invocación envía o elimina un trabajo.
  • El cliente nunca ejecuta (exec) /bin/launchctl.

Requisitos

Host de ejecución

  • macOS (Darwin) con una sesión gui/<uid>

Host de compilación

  • macOS (Darwin) con Xcode Command Line Tools o Xcode
  • Compilador C17 (cc)
  • make
  • cppcheck para desarrollo (brew install cppcheck)

Compilación

make

Uso

xspawn oneshot -l <label> [-o <stdout>] [-e <stderr>] [--] <program> [args...]
xspawn submit  -l <label> [-o <stdout>] [-e <stderr>] [--] <program> [args...]
xspawn remove  -l <label>
xspawn load    -p <plist>
SubcomandoCiclo de vida
oneshotDe un solo disparo (RunAtLoad + LaunchOnlyOnce)
submitKeepAlive
loadPlist propiedad del llamante tal como se escribe
removeDescargar por etiqueta

Un solo disparo (RunAtLoad + LaunchOnlyOnce; 0 significa sin espera):

./xspawn oneshot -l com.example.once -- /tmp/helloworld 0

Los argumentos después de -- son ProgramArguments. Eso incluye código en línea (python3 -c, perl -e). CrowdStrike Falcon para macOS registra el CommandLine completo, así que usa código en línea con intérpretes con moderación.

./xspawn oneshot -l com.example.py -o /tmp/py.out -- \
	/usr/bin/python3 -c "print('hello world')"

Trabajo KeepAlive, el mismo ciclo de vida que launchctl submit. Con sleep 60 para que CrowdStrike Falcon para macOS y launchctl print sigan viendo el proceso:

./xspawn submit -l com.example.svc \
	-o /tmp/out.log -e /tmp/err.log -- /tmp/helloworld 60

Inspecciona con launchctl print (solo oráculo; este cliente no lo invoca):

launchctl print gui/$(id -u)/com.example.svc

El éxito muestra type = LaunchAgent (no Submitted), program como ruta absoluta y state = running o brevemente xpcproxy. Submitted significa que el trabajo no tomó la ruta de bootstrap.

Limpia un trabajo de prueba:

./xspawn remove -l com.example.svc

Carga un plist propiedad del llamante (no se elimina después de la respuesta):

./xspawn load -p /tmp/job.plist

<program> debe ser una ruta absoluta. launchd no busca en $PATH.

load -p requiere una ruta absoluta que termine en .plist.

-o / -e pueden ser relativas. Se resuelven contra el directorio de trabajo actual antes de escribirse en el plist. Si se omiten -o y -e, son /dev/null.

oneshot y submit comprueban la etiqueta en gui y user (descriptor 708) antes de escribir el plist temporal. Una etiqueta ocupada sale con label already loaded y sin salida estándar. Esa comprobación existe para que un 800 condenado al fracaso no escriba $TMPDIR/XXXXXX/XXXXXX.plist (un artefacto DFIR; CrowdStrike Falcon conserva la ruta en ASEPFilePath) ni imprima la copia XML del diccionario del trabajo. Una etiqueta libre imprime la ruta temporal, luego ese XML y después envía 800. load -p ejecuta la misma comprobación de ocupación sobre el Label del archivo y luego imprime la ruta del llamante y el XML. El directorio temporal se elimina en cada salida. remove es por etiqueta.

Códigos de salida

CódigoSignificado
0El bootstrap o bootout XPC se realizó correctamente
1Error de uso, etiqueta no válida, root o rechazo de launchd/XPC

Verificación

Host de compilación (make y el árbol de pruebas; a menudo ubicado junto con una sesión gui). Estas comprobaciones no son una prueba de ejecución limpia:

make
make test
make test-unit
make test-functional
./xspawn oneshot -l com.example.once -- /tmp/helloworld 0

Limitaciones

  • Solo gui/<uid> del mismo usuario. Se rechaza root. No se puede apuntar a otro UID.
  • Efímero: no persiste entre reinicios o cierres de sesión.
  • Las constantes privadas de carga y bootout de XPC están fijadas a macOS 26.6.1 build 25G76. Vuelve a fijarlas si sw_vers -buildVersion cambia (ver ARCHITECTURE.md).
  • El plist temporal es $TMPDIR/XXXXXX/XXXXXX.plist ($TMPDIR debe ser absoluto; si no, /tmp). El directorio se elimina en cada salida. Una etiqueta ocupada nunca crea ese archivo.
  • CrowdStrike Falcon para macOS registra la ruta del plist temporal en el campo Auto-Start Extensibility Point (ASEPFilePath) en el evento ProcessRollup2. El proceso padre sigue siendo launchd.
  • Una ejecución independiente de xspawn es visible como este cliente: historial del shell y un evento de proceso del EDR para este binario. CrowdStrike Falcon para macOS registra el CommandLine completo, que incluye la ruta del programa y sus argumentos. Compila el cliente dentro de otras herramientas cuando esa imagen y argv resulten distintivos. Incrustarlo no elimina ASEPFilePath ni la línea de bootstrap de launchd.log (ver ARCHITECTURE.md, Parentage).
  • launchd también registra el lanzamiento en /private/var/log/com.apple.xpc.launchd/launchd.log (ver ARCHITECTURE.md, Parentage).
  • No pongas una clave XPCService en un plist escrito a mano: entonces xpcproxy hace fork y CrowdStrike Falcon para macOS registra a xpcproxy como padre.

Protocolo XPC privado

launchd es un servidor de bootstrap de Mach. Este cliente no usa XPC público (xpc_connection_create). Abre una tubería privada de libxpc en el bootstrap_port heredado con xpc_pipe_create_from_port(bootstrap_port, 4) y luego envía _xpc_pipe_interface_routine. Esos símbolos están en libxpc y no están en los encabezados del SDK.

El ID de rutina es el argumento descriptor, no una clave en el diccionario de solicitud. En macOS 26.6.1 build 25G76, load es el descriptor 800 y bootout es 801. Los indicadores de interfaz son 6. Se requiere una sesión gui/<uid>: el puerto heredado es el dominio gui de launchd solo dentro de una sesión de inicio de sesión de Aqua, y este cliente solo envía type 8 con handle = uid.

Load (800) es un diccionario XPC. La definición del trabajo no está en el cuerpo del mensaje.

handle   uid (uint64)
type     8 (gui)
paths    [absolute .plist]
by-cli   true

launchd hace stat de la ruta, analiza el plist y luego hace posix_spawn de xpcproxy. xpcproxy hace exec del programa en el mismo PID. El éxito es que la tubería devuelva 0, sin xpc-fault, error 0, bootstrap-error 0.

Bootout (801) es por etiqueta: handle, type 8, name, no-einprogress, wait. Sin plist.

El canal es técnica previa (prior art). Jonathan Levin (launjctl, 2015; Mac OS X and iOS Internals Vol. 1) demostró que launchctl se comunica con launchd a través de una tubería XPC privada y documentó xpc_pipe_create_from_port / xpc_pipe_routine con las claves de diccionario type, handle, subsystem, routine y name. Patrick Wardle (The Art of Mac Malware Vol. 2) documentó _xpc_pipe_interface_routine como la entrada de envío posterior. Csaba Fitzl y Brandon Dalton (OBTS) mapearon la misma familia de diccionarios y los códigos de tipo de dominio (gui es 8). Los fragmentos públicos ya usaban xpc_pipe_create_from_port(bootstrap_port, 4).

Descargar herramienta