Introduction to Android VM Forensics
The proliferation of Android devices, coupled with the increasing complexity of mobile applications and operating systems, has made virtual machines (VMs) an indispensable tool for app development, security research, and malware analysis. Android Virtual Devices (AVDs), Genymotion, and custom QEMU/KVM setups provide sandboxed environments that mirror physical Android devices. For forensic investigators, these virtual environments present unique challenges and opportunities. While traditional device forensics often involves physical acquisition, VM forensics requires understanding the underlying virtualization technology to extract artifacts like disk images and volatile memory efficiently. This article delves into techniques for automating the acquisition of critical forensic data from Android VMs, specifically focusing on disk and memory dumps.
Automating this process is crucial for scaling investigations, ensuring consistency, and reducing human error, especially when dealing with multiple VMs or conducting iterative analysis in a lab environment.
Understanding Android Virtual Machines and Forensic Targets
Android VMs, at their core, are instances of QEMU (Quick EMUlator) running an ARM or x86 Android system. The Android SDK’s AVD Manager primarily leverages QEMU. Regardless of the specific platform, the primary forensic targets remain consistent:
- Disk Images: These contain the persistent storage of the VM, including the Android operating system, user data, installed applications, and any files created or downloaded by the user. Key files typically include
userdata.qcow2(for AVDs) or rawuserdata.img, and potentiallysdcard.img. - Memory Dumps: Volatile memory (RAM) holds crucial runtime information such as active processes, network connections, open files, encryption keys, and unencrypted data that might not be present on disk. Live memory acquisition is particularly challenging but incredibly valuable.
The ability to reliably acquire these assets forms the bedrock of a thorough forensic examination.
Automated Disk Image Acquisition
Locating AVD Disk Images
Android Virtual Devices store their configuration and disk images within your user directory. The typical path is ~/.android/avd/<AVD_NAME>.avd/. Inside this directory, you’ll find files like userdata-qemu.qcow2 (the primary user data partition), cache.qcow2, and sdcard.img.
# Example: List files in an AVD directorycd ~/.android/avd/Pixel_3a_API_30.avd/ls -l
The .qcow2 format is a QEMU Copy-On-Write image, which can be converted to a raw .img format if needed, using qemu-img convert. For forensic purposes, it’s often best to acquire the original .qcow2 file directly.
Scripting Disk Image Copy
To ensure data integrity, it’s recommended to shut down the Android VM before acquiring its disk image. While an ‘online’ acquisition might be possible with tools like adb pull for mounted partitions, directly copying the underlying disk image from the host system while the VM is off or suspended provides the most consistent snapshot.
#!/bin/bashAVD_NAME="Pixel_3a_API_30"AVD_PATH="$HOME/.android/avd/${AVD_NAME}.avd"OUTPUT_DIR="/mnt/forensics/android_vm_dumps"TIMESTAMP=$(date +%Y%m%d_%H%M%S)echo "[INFO] Ensuring output directory exists..."mkdir -p "$OUTPUT_DIR/$AVD_NAME/$TIMESTAMP"if [ ! -d "$AVD_PATH" ]; then echo "[ERROR] AVD path not found: $AVD_PATH" exit 1fi# Step 1: Stop the AVD (if running)echo "[INFO] Attempting to stop AVD: $AVD_NAME"# Using adb kill-server can be a sledgehammer, better to try 'adb emu kill' if connected.adb devices | grep "emulator"if [ $? -eq 0 ]; then # Assuming only one emulator is running, or target specific echo "[WARN] Please manually shut down the AVD named '$AVD_NAME' before proceeding, or implement specific AVD shutdown logic." # A more robust solution involves identifying the specific emulator instance and using 'adb -s <emulator-id> emu kill' # For simplicity, we assume the VM is off or suspended for a clean disk acquisition. sleep 2 # Give user time to reactfi# Step 2: Copy primary disk imagesecho "[INFO] Copying disk images from $AVD_PATH to $OUTPUT_DIR/$AVD_NAME/$TIMESTAMP"cp -v "$AVD_PATH/userdata-qemu.qcow2" "$OUTPUT_DIR/$AVD_NAME/$TIMESTAMP/userdata-qemu_${TIMESTAMP}.qcow2"cp -v "$AVD_PATH/cache.qcow2" "$OUTPUT_DIR/$AVD_NAME/$TIMESTAMP/cache_${TIMESTAMP}.qcow2"if [ -f "$AVD_PATH/sdcard.img" ]; then cp -v "$AVD_PATH/sdcard.img" "$OUTPUT_DIR/$AVD_NAME/$TIMESTAMP/sdcard_${TIMESTAMP}.img"fielse echo "[WARN] sdcard.img not found for $AVD_NAME"fiecho "[INFO] Disk image acquisition complete for $AVD_NAME."echo "[INFO] Dumps saved to: $OUTPUT_DIR/$AVD_NAME/$TIMESTAMP"
Automated Memory Acquisition
Acquiring live memory from a running Android VM is more intricate than disk image acquisition. The most effective method involves interacting directly with the QEMU process that backs the AVD.
Method 1: Suspend and Copy State (Memory Snapshot)
When an AVD is suspended, its entire state, including RAM, CPU registers, and device states, is saved to a file. For AVDs, this is typically part of the .qcow2 file or a separate snapshot file.
#!/bin/bashAVD_NAME="Pixel_3a_API_30"# Ensure the emulator is launched with snapshot support (default for AVD Manager)echo "[INFO] Attempting to save snapshot for AVD: $AVD_NAME"# This command will gracefully save the emulator state.emulator -avd "$AVD_NAME" -snapshot-save "${AVD_NAME}_live_state" -no-window -no-audio -no-boot-anim & # Launch in backgroundsleep 30 # Give it time to save the state, adjust as neededpid=$!kill $pid # Kill the emulator after state save (or it will just run)wait $pid 2>/dev/null # Wait for it to actually dieecho "[INFO] Snapshot saved for $AVD_NAME. You can now copy its .qcow2 and associated state files."# The .qcow2 file itself will contain the suspended state if 'Quick boot' is enabled.
Method 2: Live Memory Dump via QEMU Monitor
This is the preferred method for a truly live memory dump. It requires launching the AVD’s QEMU instance with a monitor exposed.
- Launch AVD with QEMU Monitor:
emulator -avd "Pixel_3a_API_30" -qemu -monitor telnet::5554,server,nowaitThis command launches the AVD and makes the QEMU monitor accessible via telnet on port 5554. Replace
Pixel_3a_API_30with your AVD name. Keep this terminal open as it runs the emulator. - Connect to QEMU Monitor and Dump Memory:
In a separate terminal, use
netcatortelnetto connect to the monitor and issue thedump-guest-memorycommand.#!/bin/bashAVD_NAME="Pixel_3a_API_30"OUTPUT_DIR="/mnt/forensics/android_vm_dumps"TIMESTAMP=$(date +%Y%m%d_%H%M%S)MEMORY_DUMP_FILE="$OUTPUT_DIR/$AVD_NAME/$TIMESTAMP/memory_${TIMESTAMP}.bin"QEMU_MONITOR_PORT=5554echo "[INFO] Ensuring output directory exists..."mkdir -p "$(dirname "$MEMORY_DUMP_FILE")"echo "[INFO] Attempting to connect to QEMU monitor on port $QEMU_MONITOR_PORT and dump memory."# Send the command to QEMU monitor.echo "dump-guest-memory $MEMORY_DUMP_FILE" | nc localhost $QEMU_MONITOR_PORT >/dev/nullsleep 5 # Give QEMU time to start the dump process. You might need to adjust this.echo "[INFO] Memory dump command sent. Check '$MEMORY_DUMP_FILE' for progress/completion."echo "[INFO] Remember to manually close the QEMU monitor connection if it remains open, or kill the emulator."The
dump-guest-memorycommand will write the entire physical memory of the guest (Android VM) to the specified file on the host system. The size of this file will correspond to the allocated RAM for your AVD.
Combining Disk and Memory Acquisition into a Unified Script
#!/bin/bash# --- Configuration ---AVD_NAME="Pixel_3a_API_30"AVD_PATH="$HOME/.android/avd/${AVD_NAME}.avd"OUTPUT_BASE_DIR="/mnt/forensics/android_vm_dumps"QEMU_MONITOR_PORT=5554# --- Pre-checks ---if ! command -v emulator &>/dev/null; then echo "[ERROR] Android 'emulator' command not found. Ensure Android SDK is installed and configured." exit 1fiif ! command -v nc &>/dev/null; then echo "[ERROR] 'netcat' (nc) command not found. Please install it (e.g., sudo apt install netcat)." exit 1fiif [ ! -d "$AVD_PATH" ]; then echo "[ERROR] AVD path not found: $AVD_PATH" exit 1fi# --- Setup Output Directory ---TIMESTAMP=$(date +%Y%m%d_%H%M%S)CURRENT_DUMP_DIR="$OUTPUT_BASE_DIR/$AVD_NAME/$TIMESTAMP"mkdir -p "$CURRENT_DUMP_DIR"echo "[INFO] Forensic dump directory created: $CURRENT_DUMP_DIR"# --- Step 1: Launch AVD with QEMU Monitor ---echo "[INFO] Launching AVD '$AVD_NAME' with QEMU monitor on port $QEMU_MONITOR_PORT..."# It's crucial to run this in the background and capture its PIDemulator -avd "$AVD_NAME" -qemu -monitor telnet::${QEMU_MONITOR_PORT},server,nowait >/dev/null 2>&1 &EMULATOR_PID=$!echo "[INFO] Emulator PID: $EMULATOR_PID"# Wait for the emulator and QEMU monitor to fully initializeecho "[INFO] Waiting for emulator to boot and monitor to become active (approx. 60 seconds)..."sleep 60# --- Step 2: Acquire Live Memory Dump ---echo "[INFO] Initiating live memory dump..."MEMORY_DUMP_FILE="$CURRENT_DUMP_DIR/memory_${TIMESTAMP}.bin"echo "dump-guest-memory $MEMORY_DUMP_FILE" | nc localhost $QEMU_MONITOR_PORT >/dev/nullsleep 30 # Give QEMU time to start dumping. This might take longer for larger RAM.echo "[INFO] Memory dump initiated. Check file size at '$MEMORY_DUMP_FILE'."# --- Step 3: Stop AVD and Acquire Disk Images ---echo "[INFO] Shutting down AVD for disk image acquisition..."# Send 'quit' command to QEMU monitor to gracefully shutdownecho "quit" | nc localhost $QEMU_MONITOR_PORT >/dev/nullwait $EMULATOR_PID # Wait for the emulator process to terminate gracefullyif [ $? -eq 0 ]; then echo "[INFO] AVD shut down successfully."else echo "[WARN] AVD might not have shut down gracefully. Forcing kill..." kill -9 $EMULATOR_PID >/dev/null 2>&1 wait $EMULATOR_PID 2>/dev/nullfi# Copy disk imagesecho "[INFO] Copying disk images from $AVD_PATH to $CURRENT_DUMP_DIR"cp -v "$AVD_PATH/userdata-qemu.qcow2" "$CURRENT_DUMP_DIR/userdata-qemu_${TIMESTAMP}.qcow2"cp -v "$AVD_PATH/cache.qcow2" "$CURRENT_DUMP_DIR/cache_${TIMESTAMP}.qcow2"if [ -f "$AVD_PATH/sdcard.img" ]; then cp -v "$AVD_PATH/sdcard.img" "$CURRENT_DUMP_DIR/sdcard_${TIMESTAMP}.img"fielse echo "[WARN] sdcard.img not found for $AVD_NAME"fiecho "[INFO] Disk image acquisition complete."echo "[INFO] All forensic artifacts for '$AVD_NAME' saved to: $CURRENT_DUMP_DIR"echo "[INFO] Don't forget to analyze memory dump using Volatility and disk images with tools like Autopsy."
Analysis Considerations
Once you have acquired the disk and memory dumps, standard forensic tools can be employed:
- Disk Images: Use tools like Autopsy, FTK Imager, or EnCase to mount and analyze the
.qcow2or.imgfiles. You can convert.qcow2to raw.imgusingqemu-img convert -f qcow2 userdata-qemu.qcow2 -O raw userdata.imgfor broader tool compatibility. - Memory Dumps: Volatility Framework is the go-to tool for analyzing memory dumps. You will need to identify the correct profile for your Android version and architecture (e.g.,
LinuxAndroid_x64_P_4.4.4). Volatility can extract processes, network connections, loaded modules, and much more.
Conclusion
Automating the acquisition of disk and memory dumps from Android virtual machines is a critical capability for modern mobile forensics and incident response. By leveraging QEMU’s monitor capabilities and shell scripting, investigators can create consistent, repeatable, and efficient workflows for collecting volatile and non-volatile evidence. This approach not only streamlines the forensic process but also ensures that crucial artifacts are captured accurately, setting the stage for in-depth analysis and uncovering critical insights within Android virtual environments.
Android Mobile Specs & Compare Directory
Are you researching mobile hardware properties, processor SoCs, GPU chipsets, or RAM configurations? Access our complete specs catalog to compare up to 5 devices side-by-side!
Compare Devices Specs →