
Sandbox de clonagem de apps Android com uma CLI no estilo Frida que inicia ou se anexa a apps clonados e injeta scripts QuickJS usando hooks Gum Interceptor e Stalker.

Spindle é o cliente de linha de comando. Ele envia um script para o host BBA ou para um app clonado e imprime os logs de volta. As flags seguem a linha de comando do Frida: spawn com -f, attach com -n ou -p, carregar um arquivo com -l.
O BBA em si é um sandbox de clonagem de apps Android. O pacote host é com.android.bba. Um app clonado roda dentro desse pacote, não como uma instalação normal. Instale o APK, abra o clone pela UI do BBA e então use o Spindle. Os scripts rodam apenas em arm64, no QuickJS, com o Interceptor e o Stalker do Frida Gum.

A máquina de desenvolvimento nunca se conecta a um clone diretamente. Ela só fala com com.android.bba:black em 127.0.0.1:2408. O processo host e cada clone são agentes: eles se registram via Binder, recebem o script e enviam os logs de volta. O modo USB executa adb forward tcp:0 tcp:2408 para você.
A partir da raiz do repositório, com um dispositivo conectado:
# Stop the clone on user 0, start it, inject, then let it continue
python3 tools/spindle -U -f com.example.app -l tools/test_js_api.js
# Attach to a clone that is already running
python3 tools/spindle -U -n com.example.app -l tools/test_native_hook.js
# Attach to a pid, including the host process com.android.bba
python3 tools/spindle -U -p 12345 -l tools/test_js_api.js
# One line of script, no file
python3 tools/spindle -U -n com.example.app -e 'console.log("hi")'
# Registered processes, JSON
python3 tools/spindle -U --list
# Same list, as a table
python3 tools/spindle-ps -U
-f é spawn. O cliente envia o script e então UNLOCK. O clone espera no caminho de inicialização até que esse frame chegue, então o script está no lugar antes de Application.onCreate. -f sempre usa o usuário 0.
-n e -p fazem attach. O processo já deve ter se registrado. Um nome é o nome de processo que o Spindle registrou, geralmente o nome do pacote clonado. O processo de UI do host é com.android.bba.
Mais de um celular:
python3 tools/spindle -D <serial> -n com.example.app -l tools/test_js_api.js
Se a porta já estiver encaminhada, pule o adb:
python3 tools/spindle -H 127.0.0.1:2408 -n com.example.app -l tools/test_js_api.js
-H, -U e -D escolhem a conexão. Passe apenas um deles. Passe apenas um de -f, -n e -p.
O cliente permanece ativo e imprime console.log até o processo sair, o servidor cair ou você pressionar Ctrl-C.
Um script é JavaScript puro. Estes exemplos ficam em tools/:
| Arquivo | O que faz |
|---|---|
test_js_api.js | Memory, ponteiros, Module, Interceptor |
test_native_hook.js | Interceptor.attach("libz.so!deflate", …) |
test_java_hook.js | Java.hook em Activity.onCreate |
test_stalker.js | Stalker.follow de dentro de um hook |
test_rpc.js | rpc.exports chamado pela linha de comando |
console.log volta como uma linha de log. Em armeabi-v7a não há runtime; um RPC ali responde com js runtime is not in bba.
Chame um export depois que o script carregar. --args é um array JSON e se alinha com o --call correspondente:
python3 tools/spindle -U -n com.example.app -l tools/test_rpc.js --call ping --args '["hi"]'
Isso imprime pong hi e então continua aguardando logs.
Grupo de chat: openbba. O código expira em 20 de outubro de 2026.
