MITMing your own remote Android emulator traffic
Setting up an Android emulator on a remote machine (to avoid destroying my laptop battery) in a state to capture traffic from an app was a bit annoying, and I wanted to store the shortened set instructions somewhere so I can reference it later.
If you’re not me, replace 192.168.1.223
with whatever your host machine is on your LAN.
Setup
Host
Just in case the machine I really don’t care to backup bites the dust…
- Assuming a Debian-like system,
apt-get install default-jdk
- I initially tried to do this in a Linux Container (LXC) - but nested virtualization via
/dev/kvm
doesn’t pass through. Oh well.
- I initially tried to do this in a Linux Container (LXC) - but nested virtualization via
- Create or reuse a user. In my case, I did:
useradd -m android
usermod -a -G kvm android
(otherwise the emulator + nested virtualization won’t work)passwd android
to something I could remember (needed later)
su android
, install Android Platform tools, emulator, etc. One of the links below should help.- If it’s been a while,
sdkmanager --update
to pull the latest SDK
- If it’s been a while,
- Add android tools to path. e.g. create
.localrc
and set contents toPATH=$HOME/cmdline-tools/latest/bin:$HOME/platform-tools:$HOME/emulator:$PATH
- Get the image:
sdkmanager --install "system-images;android-35;google_apis;x86_64"
- Create AVD:
avdmanager create avd --name pixel-android-api-35 --package "system-images;android-35;google_apis;x86_64" --tag "google_apis" --abi "x86_64" --device "pixel_6"
- Install the mitmproxy cert into the emulator after making the system partiton writable. I won’t copy those steps, follow them here.
Client
brew install scrcpy
Execute
Host
- Start
screen
or similar - In one terminal of your main user with
sudo
:sudo docker run --rm -it -v ~/.mitmproxy:/home/kevin/.mitmproxy -p 0.0.0.0:8080:8080 -p 0.0.0.0:8081:8081 mitmproxy/mitmproxy:latest mitmweb --showhost --web-host 0.0.0.0
- In another terminal:
emulator -avd pixel-android-api-35 -writable-system -no-window -http-proxy http://192.168.1.223:8080
- In another terminal:
adb forward tcp:1234 tcp:5555
adb tcpip 5555
ssh -Nfg -L 1234:localhost:5555 localhost
Remote
adb connect 192.168.1.223:1234
scrcpy -m1024
- Open
http://192.168.1.223:8081
- Run your scenario and hopefully it’s captured. If not, you might have a problem with cert pinning or an app bypassing the proxy.
Unclear if this is necessary with the -http-proxy
argument with the emulator (I discovered that later), but found it useful enough to document. Run on either host or remote.
adb shell settings put global http_proxy 192.168.1.223:8080
adb shell settings put global global_http_proxy_host 192.168.1.223
adb shell settings put global global_http_proxy_port 8080
Future
At some point, I think I’m going to need a packet capture for my next step in the reverse engineering journey I started down…
Resources
This terse set of instructions was compiled from:
- https://gist.github.com/mrk-han/66ac1a724456cadf1c93f4218c6060ae
- https://gist.github.com/approovm/e550374428065ff1ecafca6a0488d384
- https://dev.to/andreisfedotov/how-to-install-android-emulator-without-installing-android-studio-3lce
- https://www.reddit.com/r/Crostini/comments/hqyjir/comment/fy1l0ar/?context=3
I never did get Frida working, it just hung on my emulator device and the client timed out connecting. But for my case, that wasn’t important.
Interesting things from 2025-01-05
- Using this Frida “codeshare” was really effective:
frida --codeshare akabe1/frida-multiple-unpinning -U -f <app_name>
- https://github.com/REAndroid/APKEditor - merge APKs like
java -jar APKEditor.jar m -i <directory>
- Sign a recompiled APK:
java -jar uber-apk-signer-1.3.0.jar -a <merged_apk>.apk
- https://apktool.org/
- https://medium.com/@vaishalinagori112/9-different-ways-to-bypass-ssl-pinning-in-android-2d8c7f81b837
- https://approov.io/blog/how-to-bypass-certificate-pinning-with-frida-on-an-android-app
- https://gist.github.com/approovm/e550374428065ff1ecafca6a0488d384#start-the-emulator-with-a-writable-file-system