Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
Ferramentas/GitHubGitHub/cenobyte-vincit/xspawn
Mecanismos de PersistênciaEvasão de IDS/IPSPós-ExploraçãoRed TeamingAtaque Adversário
GitHubcenobyte-vincit/xspawn

xspawn

Spawna programas macOS por meio da interface XPC privada do launchd, sem executá-los via exec, fazendo o EDR registrar o launchd como pai. Suporta jobs one-shot, KeepAlive e baseados em plist.

Ver Repositório
48há 2 mesesAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

xspawn

O xspawn inicia um programa no macOS através do launchd e nunca executa esse programa por conta própria. O objetivo é que um EDR registre o launchd como pai, e não esta ferramenta ou o shell que a invocou.

por cenobyte [email protected] 2026

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

Resumo

O xspawn abre xpc_pipe_create_from_port(bootstrap_port) e inicializa a execução de um programa através de _xpc_pipe_interface_routine, o mesmo pipe XPC privado usado pelo launchctl, e nunca executa o programa por conta própria.

  • Root é recusado. Não há modo para outro UID.
  • Uma invocação submete ou remove um job.
  • O cliente nunca executa /bin/launchctl.

Requisitos

Ambiente de execução

  • macOS (Darwin) com uma sessão gui/<uid>

Ambiente de compilação

  • macOS (Darwin) com Xcode Command Line Tools ou Xcode
  • Compilador C17 (cc)
  • make
  • cppcheck para desenvolvimento (brew install cppcheck)

Compilação

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
oneshotOne-shot (RunAtLoad + LaunchOnlyOnce)
submitKeepAlive
loadplist de propriedade do chamador, tal como escrita
removeDescarregar por label

One-shot (RunAtLoad + LaunchOnlyOnce; 0 significa sem pausa):

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

Os argumentos após -- são ProgramArguments. Isso inclui código inline (python3 -c, perl -e). O CrowdStrike Falcon para macOS registra a CommandLine completa, portanto use código inline com interpretadores com moderação.

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

Job KeepAlive, com o mesmo ciclo de vida do launchctl submit. Use sleep 60 para que o CrowdStrike Falcon para macOS e o launchctl print ainda vejam o processo:

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

Inspecione com launchctl print (apenas oracle; este cliente não o chama):

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

O sucesso exibe type = LaunchAgent (não Submitted), program como caminho absoluto e state = running ou, brevemente, xpcproxy. Submitted significa que o job não seguiu o caminho de bootstrap.

Remova um job de teste:

./xspawn remove -l com.example.svc

Carregue uma plist de propriedade do chamador (não excluída após a resposta):

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

<program> deve ser um caminho absoluto. O launchd não pesquisa $PATH.

load -p exige um caminho absoluto que termine em .plist.

-o / -e podem ser relativos. Eles são resolvidos em relação ao diretório de trabalho atual antes de serem gravados na plist. -o e -e omitidos são /dev/null.

oneshot e submit verificam o label em gui e user (descritor 708) antes de escrever a plist temporária. Um label já em uso faz o comando sair com label already loaded e sem stdout. Essa verificação existe para que um 800 condenado não grave $TMPDIR/XXXXXX/XXXXXX.plist (um artefato de DFIR; o CrowdStrike Falcon mantém o caminho em ASEPFilePath) nem imprima a cópia em XML do dicionário do job. Um label livre imprime o caminho temporário, depois esse XML e então envia o 800. load -p executa a mesma verificação de ocupação no Label do arquivo e então imprime o caminho do chamador e o XML. O diretório temporário é removido em todas as saídas. remove é por label.

Códigos de saída

CódigoSignificado
0Bootstrap ou bootout XPC bem-sucedido
1Erro de uso, label inválido, root ou rejeição do launchd/XPC

Verificação

Ambiente de compilação (make e a árvore de testes; frequentemente no mesmo local que uma sessão gui). Estas verificações não são uma prova de runtime limpo:

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

Limitações

  • Apenas gui/<uid> do mesmo usuário. Root é recusado. Sem alvo para outro UID.
  • Efêmero: não é persistente entre reinicializações ou logout.
  • As constantes privadas de load e bootout do XPC estão fixadas no macOS 26.6.1 build 25G76. Refaça a fixação se sw_vers -buildVersion mudar (veja ARCHITECTURE.md).
  • A plist temporária é $TMPDIR/XXXXXX/XXXXXX.plist ($TMPDIR deve ser absoluto, caso contrário /tmp). O diretório é removido em todas as saídas. Um label já em uso nunca cria esse arquivo.
  • O CrowdStrike Falcon para macOS registra o caminho da plist temporária no campo Auto-Start Extensibility Point (ASEPFilePath) no evento ProcessRollup2. O pai do processo permanece launchd.
  • Uma execução standalone do xspawn é visível como este cliente: histórico do shell e um evento de processo no EDR para este binário. O CrowdStrike Falcon para macOS registra a CommandLine completa, que inclui o caminho do programa e seus argumentos. Compile o cliente dentro de outras ferramentas quando essa imagem e argv forem distintivos. A incorporação não remove ASEPFilePath nem a linha de bootstrap no launchd.log (veja ARCHITECTURE.md, Parentage).
  • O launchd também registra o spawn em /private/var/log/com.apple.xpc.launchd/launchd.log (veja ARCHITECTURE.md, Parentage).
  • Não coloque uma chave XPCService em uma plist escrita à mão: o xpcproxy então faz fork e o CrowdStrike Falcon para macOS registra o pai como xpcproxy.

Protocolo XPC privado

O launchd é um servidor de bootstrap Mach. Este cliente não usa XPC público (xpc_connection_create). Ele abre um pipe privado da libxpc na bootstrap_port herdada com xpc_pipe_create_from_port(bootstrap_port, 4) e então envia _xpc_pipe_interface_routine. Esses símbolos estão na libxpc e não estão nos cabeçalhos do SDK.

O ID da rotina é o argumento descritor, não uma chave no dicionário da requisição. No macOS 26.6.1 build 25G76, load é o descritor 800 e bootout é 801. Os flags de interface são 6. Uma sessão gui/<uid> é obrigatória: a porta herdada é o domínio gui do launchd apenas dentro de uma sessão de login Aqua, e este cliente só envia type 8 com handle = uid.

Load (800) é um dicionário XPC. A definição do job não está no corpo da mensagem.

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

O launchd executa stat no caminho, faz o parse da plist e então executa posix_spawn do xpcproxy. O xpcproxy executa o programa no mesmo PID. O sucesso é retorno do pipe 0, sem xpc-fault, error 0, bootstrap-error 0.

Bootout (801) é por label: handle, type 8, name, no-einprogress, wait. Sem plist.

O canal é técnica anterior. Jonathan Levin (launjctl, 2015; Mac OS X and iOS Internals Vol. 1) mostrou que o launchctl conversa com o launchd por um pipe XPC privado e documentou xpc_pipe_create_from_port / xpc_pipe_routine com as chaves de dicionário type, handle, subsystem, routine e name. Patrick Wardle (The Art of Mac Malware Vol. 2) documentou _xpc_pipe_interface_routine como a entrada de envio posterior. Csaba Fitzl e Brandon Dalton (OBTS) mapearam a mesma família de dicionários e os códigos de tipo de domínio (gui é 8). Snippets públicos já usavam xpc_pipe_create_from_port(bootstrap_port, 4).

Baixar ferramenta