Analyse on your own device
Dynamic analysis normally runs in our sandbox: you press a button and that's it. This guide is for when you want it to run on your machine — your emulator, your network, your hardware. The sample never leaves your computer; only the findings travel to Droidwatch, and they land in the report you already have.
About 20 minutes the first time. After that, one command.
Probably not. On droidwatch.app you press Run dynamic analysis and you're done: a disposable Android VM is created for your sample and destroyed afterwards. Nothing to install, nothing to plug in.
It is worth setting up if the sample cannot leave your network (compliance, an NDA'd app, an air-gapped lab), or if you need something the cloud sandbox does not do yet: screen recording, mitmproxy, mock C2, dex dumping, or the anti-VM bypass.
How it works
What you need
| What for | Check it with | |
|---|---|---|
adb |
Talking to the device | adb version |
frida |
Instrumenting the app | frida --version |
| An emulator without Google Play | Running the sample | see step 2 |
| A Droidwatch API key | Uploading the result | Profile → API keys |
An ordinary phone will not do. Frida needs root, and a retail phone does not have it. Use an emulator — it is also the right choice for malware, and what the Safety section recommends.
Step 1 · Install the tools
# macOS
brew install --cask android-platform-tools
python3 -m pip install --user frida-tools
# Debian / Ubuntu
sudo apt install -y android-tools-adb
python3 -m pip install --user frida-tools
Check that both answer:
adb version # Android Debug Bridge version 1.0.41
frida --version # 17.9.7
If
fridasays "command not found", the install did not fail.pip install --userputs the executable in a directory that is not on macOS'sPATHby default. It is the first thing almost everyone trips on. Add it:
bash echo 'export PATH="$(python3 -m site --user-base)/bin:$PATH"' >> ~/.zshrc export PATH="$(python3 -m site --user-base)/bin:$PATH" frida --versionThe first line makes it permanent; the second fixes the terminal you already have open. (On bash, swap
~/.zshrcfor~/.bashrc.)
Write down the frida version. You need it in step 3, and it has to match
exactly.
Step 2 · Create and start an emulator
From Android Studio: Device Manager → Create device. Or from the command line:
sdkmanager "system-images;android-30;google_apis;arm64-v8a"
avdmanager create avd -n dw-test -k "system-images;android-30;google_apis;arm64-v8a"
emulator -avd dw-test -no-snapshot-load
Pick an image without Google Play. In Android Studio, the ones marked (Google Play) will not work: they are production-signed and do not allow root, which is what Frida needs. Look for (Google APIs) on its own.
With the emulator running, check adb sees it:
adb devices
List of devices attached
emulator-5554 device
It has to say device. If it says offline, it is still booting — wait.
Step 3 · Install frida-server on the emulator
This is a program that runs inside the emulator. Two things have to match:
its version with your frida, and its architecture with the emulator's.
frida --version # e.g. 17.9.7
adb shell getprop ro.product.cpu.abi # e.g. arm64-v8a
Download the matching build from Frida's releases:
If abi says |
Download |
|---|---|
arm64-v8a |
frida-server-<version>-android-arm64.xz |
x86_64 |
frida-server-<version>-android-x86_64.xz |
armeabi-v7a |
frida-server-<version>-android-arm.xz |
Install and start it:
unxz frida-server-17.9.7-android-arm64.xz
adb push frida-server-17.9.7-android-arm64 /data/local/tmp/frida-server
adb shell chmod 755 /data/local/tmp/frida-server
adb root
adb shell /data/local/tmp/frida-server &
It prints nothing. That is correct — it keeps running in the background.
It dies when the emulator restarts. Every time you start the emulator, repeat the last two lines. If one day the analysis fails with frida-server not reachable, this is almost always why.
Step 4 · Check that Frida sees the device
frida-ps -Ua
PID Name Identifier
----- --------------- ----------------------------
2118 Calendar com.android.calendar
1893 Settings com.android.settings
If you get that list, the hard part is done. If this command fails, stop here: nothing below will work, and the problem is in step 2 or 3.
Step 5 · Create your key and get the agent
First the key, on droidwatch.app: Profile → API keys → create one. Copy it as soon as it appears — it is shown once.
export DROIDWATCH_API_KEY=dw_...
Then download the agent with it. It is not on a public index: your key is what gets you the file, and it stops working when your plan does.
curl -H "X-API-Key: $DROIDWATCH_API_KEY" \
https://droidwatch.app/api/agent/download -o droidwatch-agent.pyz
Check what you downloaded. You are about to run something that drives your device and handles malware, so verify it rather than trust it:
shasum -a 256 droidwatch-agent.pyz # macOS
sha256sum droidwatch-agent.pyz # Linux
Compare it with the hash this server reports:
curl -H "X-API-Key: $DROIDWATCH_API_KEY" https://droidwatch.app/api/agent/version
It is a single file of about 15 KB with no dependencies at all — it runs on
the python3 you already have from step 2. There is nothing to install and
nothing to uninstall; delete the file and it is gone.
python3 droidwatch-agent.pyz --help
Step 6 · Run the analysis
Leave the agent running in a terminal. It stays quiet until you ask for something:
python3 droidwatch-agent.pyz --api-key $DROIDWATCH_API_KEY
dispositivo: Pixel 2 · Android 11 · arm64-v8a (emulator-5554)
agent 0.1.0 running against https://droidwatch.app
If more than one device is plugged in it will stop and ask you to pick one with
--serial. That is deliberate: with a rootable AVD, one with Play Store and one
on 32 bits all on the desk, "the first one" is a coin toss, and the sample ends
up running where it should not.
Now go to droidwatch.app. Upload your APK as usual, wait for the static analysis and open the Dynamic tab. The dropdown offers My device, with the model, the Android version and the ABI of the emulator the agent can see — so you know what you are about to run the sample on before you run it.
Press Run dynamic analysis. The progress bar is the same one as for our own sandbox, because it is the same analysis; only the machine changes. Keep the emulator in view: you will see the app install and launch.
The sample is installed on your emulator and what it does happens on your network. When it finishes, the agent uploads only the findings and the artefacts, and the report fills in — labelled as analyst-supplied, because we did not watch the run ourselves.
If your plan does not include dynamic analysis, the agent says so and stops: the check lives on the server, not in the agent.
Step 7 · Read the results
Go back to the Dynamic tab and refresh. There is what the app did: the URLs it called, the SMS it read, the keys it built in memory, the screenshots and the network capture.
Next to your name and the date. It is not a penalty or a limitation: that run happened on your machine, we did not watch it, and a Droidwatch report can be shared publicly. Whoever reads it deserves to know who produced the evidence — and it works in your favour, because it distinguishes your work from the automated kind.
If something goes wrong
| What you see | What it means | What to do |
|---|---|---|
no adb device connected |
The emulator is not running, or adb cannot see it. |
Back to step 2. adb kill-server && adb devices fixes most cases. |
no online adb device (states: …) |
There is a device but it is not ready. The state in brackets says why: offline means still booting, unauthorized means a prompt on its screen is waiting for you. |
Wait, or look at the emulator's screen. |
frida-server not reachable on the device |
adb gets through but Frida does not. Almost always: frida-server is not running (a restart killed it) or its version does not match your frida. |
Repeat step 3 and compare the two versions. |
frida CLI not found in PATH |
The Frida CLI is not where it is looked for. Almost always: pip install --user left it off the PATH. |
See the note in step 1. Note which frida is no help here — it prints nothing precisely when it is missing. |
adb binary not found in PATH |
Same, for adb. |
Install platform-tools (step 1). |
The server answers 402 |
Your plan does not include dynamic analysis. | It is a Pro-and-above feature. |
The server answers 413 |
The bundle is over 200 MB. | Lower --duration, or turn screen recording off. |
Everything above reproduces with two commands in your own terminal: adb
devices and frida-ps -Ua. If those two work and it still fails, send us the
output of both.
Safety
You are about to install malware and run it. Three rules:
- Never on your phone. Use an emulator. A sample that gains root can survive even a factory reset.
- Isolate the network. While it runs, the sample reaches anything the device can reach: your NAS, your router's admin page, your other machines.
- Restore the emulator afterwards. The CLI uninstalls the app when it finishes, but a sample that gained persistence is not something an uninstall removes. Snapshot before, restore after — it is the only cleanup you can trust.