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.

Do you need this?
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

The analysis runs on your machine against your emulator; only the findings are uploaded droidwatch-agent + adb + frida (we send the APK) your emulator the sample frida-server droidwatch your report your machine — the sample stays here installs watches
The APK stays on your machine. What gets uploaded is the result: Frida output, logcat, screenshots and the network capture.

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 frida says "command not found", the install did not fail. pip install --user puts the executable in a directory that is not on macOS's PATH by 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 --version

The first line makes it permanent; the second fixes the terminal you already have open. (On bash, swap ~/.zshrc for ~/.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.

The section is labelled analyst-supplied.

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: