In the last post, I said I'd had this phone since April, which is true. What is definitely not true is that I'm writing these blog posts as the project progresses - that's just a narrative conceit to try and keep things consistent.
In actual fact, I did most of the early investigative work in May using a laptop I've since retired, then lost interest for several months. I used a native (as in, on-the-metal) install of Microsoft Windows on that laptop as a platform for the various tools I used to get data out of the phone. I no longer have access to that laptop and some of these tools were a little skeevy, so this is basically the story of me getting a VM up and running to achieve parity with the environment I used the first time around.
Something something unreliable narrator something.
During that first wave of investigative work back in May, the following findings were established:
There are many tools out there that can be used to read or write flash data from/to Android phones
Almost all of these tools are written for Windows
Many of these tools are of questionable provenance. That is to say, their source code is unavalailable and they are distributed as binary archives dropped on file sharing sites
Many of these tools have some sort of a dependency against the Android SDK, especially against adb
(the Android Debug Bridge) and the USB drivers used by adb
to talk to the device over a USB connection
Based on these findings, I'm going to need a Windows environment on which I can run potential malware in a safe fashion and which can connect to the phone over USB. A VM is a perfect match for that.
While I do have a bare-metal install of Windows on my current laptop, I spend >95% of my time on Linux. I have used VirtualBox to run VMs on a Linux host in the past and while I have nothing bad to say about VBox, I see it as a very heavy software package and I've found VBoxManage
difficult to work with for scripting purposes.
I decided to use a QEMU VM instead, managed through libvirt. In order to achieve higher performance, I'll be using KVM to leverage the virtualisation extensions built into my CPU (a AMD A8-5550M). Lastly, because I'm a heinous neckbeard I defined this VM using libvirt's XML interface.
libvirt calls VMs domains and serialises domain configuration as XML using a format documented here. Here's a dump of the domain I created:
<domain type='kvm'>
<name>NamPhone_VM</name>
<memory unit='KiB'>786432</memory>
<os>
<type arch='x86_64' machine='pc-i440fx-2.0'>hvm</type>
<bootmenu enable='yes'/>
</os>
<features>
<acpi/>
<apic/>
</features>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<disk type='dir' device='floppy'>
<driver name='qemu'/>
<source dir='/home/mboyer/tmp/Win_Stuff/SATA_Driver_floppy'/>
<target dev='fd0' bus='fdc'/>
<readonly/>
</disk>
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='/mnt/v12n/ISOs/virtio-win-0.1-81.iso'/>
<target dev='hda' bus='ide'/>
<readonly/>
</disk>
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/mnt/v12n/images/winxp.img'/>
<target dev='sda' bus='sata'/>
<boot order='2'/>
</disk>
<controller type='usb' index='0' model='ehci'>
</controller>
<interface type='network'>
<source network='Guests_to_host_private'/>
<model type='rtl8139'/>
</interface>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='spice' autoport='yes'/>
<hostdev mode='subsystem' type='usb' managed='no'>
<source startupPolicy='mandatory'>
<vendor id='0x0bb4'/>
<product id='0x0c03'/>
</source>
</hostdev>
</devices>
</domain>
That was a big blob of XML. The really relevant bits are as follows:
QEMU can be used for cross-platform emulation, which is definitely not what I want here. Therefore, to make use of hardware-assisted virtualisation the domain is defined with:
<domain type='kvm'>
<name>NamPhone_VM</name>
<memory unit='KiB'>786432</memory>
<os>
<type arch='x86_64' machine='pc-i440fx-2.0'>hvm</type>
<bootmenu enable='yes'/>
</os>
<features>
<acpi/>
<apic/>
</features>
This is enough to let libvirt know to use the right emulator, viz. /usr/sbin/qemu-system-x86_64
. The <features>
element and its children actually need to be defined in order to allow the Windows XP 64bit installer to execute.
From past experience using VirtualBox VMs, I've noticed that using a virtual SATA controller to handle I/O with the (virtual) disk on a VM yields better performance than using a IDE/PATA controller. I don't know whether that is true for QEMU/KVM domains as well, but I gave in to my cargo cult tendencies and defined the following storage devices on the domain:
<domain type='kvm'>
<devices>
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='/mnt/v12n/ISOs/virtio-win-0.1-81.iso'/>
<target dev='hda' bus='ide'/>
<readonly/>
</disk>
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/mnt/v12n/images/winxp.img'/>
<target dev='sda' bus='sata'/>
<boot order='2'/>
</disk>
I'm using a raw disk image for storage. Again, this is a mostly irrational decision based on poor experiences with qcow2
images in the past. Using a raw image means I cannot easily snapshot the domain, something I will probably need.
I used an old license of Windows XP for this VM. Windows XP has outlived many generations of hardware and an unfortunate side effect of this is that the drivers present in its install environment may not work with more modern hardware, such as the virtual SATA controller in the domain. To work around this, I've defined a virtual floppy drive using libvirt's dir
disk type to point its content to a directory on the host in which I've extracted the contents of the driver archive for the Intel ICH9R/DO/DH SATA AHCI Controller, the default (?) SATA controller type emulated by QEMU:
<domain type='kvm'>
<devices>
<disk type='dir' device='floppy'>
<driver name='qemu'/>
<source dir='/home/mboyer/tmp/Win_Stuff/SATA_Driver_floppy'/>
<target dev='fd0' bus='fdc'/>
<readonly/>
</disk>
Note that libvirt will automatically create the floppy, IDE and SATA controllers.
As mentioned above, the VM needs to be able to talk to the phone over a USB connection. QEMU has a USB pass-through feature that provides exactly that functionality. The domain will therefore need two things:
ehci
model after the default model crashed the guest OS several times:<domain type='kvm'>
<devices>
<controller type='usb' index='0' model='ehci'>
</controller>
And a hostdev
that will instruct QEMU what device on to pass through from the host to the guest. For USB devices, we can define the device in terms of a vendor id/product it pair. Here's what the host, ie. my laptop, sees:
$ lsusb
Bus 008 Device 003: ID 04f2:b2ea Chicony Electronics Co., Ltd Integrated Camera [ThinkPad]
Bus 008 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 006 Device 002: ID 04ca:2007 Lite-On Technology Corp.
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 007 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 003: ID 045e:0737 Microsoft Corp. Compact Optical Mouse 500
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 007: ID 0bb4:0c03 HTC (High Tech Computer Corp.) Android Phone [Fairphone First Edition (FP1)]
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
There's only one Android phone connected to my laptop so it's gotta be 0bb4:0c03
. It's certainly interesting that the phone reports itself as an HTC device. Anyway, I used this information to configure pass-through:
<domain type='kvm'>
<devices>
<hostdev mode='subsystem' type='usb' managed='no'>
<source startupPolicy='mandatory'>
<vendor id='0x0bb4'/>
<product id='0x0c03'/>
</source>
</hostdev>
Lastly, I'll need network connectivity on the VM to perform some tasks, such as installing the Android SDK. There are many networking options available in libvirt and the documentation doesn't really focus on their use-cases. I defined a libvirt network with the following configuration:
<network>
<name>Guests_to_host_private</name>
<forward mode='nat'/>
<bridge name='vm_bridge' stp='on' delay='0'/>
<ip address='172.16.16.1' netmask='255.255.255.0'>
</ip>
</network>
...and added a NIC to the domain's collection of virtual devices:
<domain type='kvm'>
<devices>
<interface type='network'>
<source network='Guests_to_host_private'/>
<model type='rtl8139'/>
</interface>
I installed the OS on the VM and then copied the following tools over:
This tool lets one visualise the USB bus tree as well as device properties, much like lsusb(1)
This includes adb
as well as DMMS which I use for phone screenshots
This is a dependency of the Android SDK. I might have gotten away with just installing a JRE.
I found this archive through a post on xda-developers.com. The driver is unsigned but it worked for me.
With all that in place, we can confirm that the VM "sees" the phone:
We can also use adb
to open a UNIX shell on the phone, albeit as an unprivileged user: