I have been asked recently to try to recover some data from a broken phone. The catch: the data was in the internal memory, the option to connect the phone as an external drive via USB was turned off and the touchscreen was broken. So what can you do in such a situation? It turns out that quite a lot, and even though I haven't eventually managed to recover the data, the fight with the phone was pretty interesting and I think it deserves a bit of attention.
Data recovery attempts
First things first: I needed to find a way to interact with the phone in any way at all. Since it was an Android-based smartphone, I quickly came up with the idea of using ADB - the "Android Debug Bridge". It's an option used mostly by mobile app developers, allowing one to control the phone via USB, and even to connect to a terminal. There was just one problem: this has to be turned on on the phone as well, and it of course wasn't. So we're back at square one.
Some googling soon told me that there are ways of turning ADB on via USB. However, they required another thing that was absent on this particular phone - a proper "recovery" software. Recovery is a special program that you can run when turning on the phone, and it allows you to repair a broken system - edit the files in the phone's memory etc. As it turns out, ADB can be turned on by editing some files, but you need to have access to them first. The smartphone I was working with wouldn't give it to me, of course.
Oh well, let's keep trying. We don't have a proper recovery, so we need to upload one. A well-known and liked piece of software used by people modding their phones is so-called ClockworkMod Recovery (or CWM for short). I found an appropriate image and tried to flash it onto the phone... but surprise, surprise, it's not so easy. The software was rejected every time because it wasn't properly signed. Smartphones are secured partially by a thing called a bootloader lock - it prevents people from loading the phone with software that hasn't been digitally signed by the phone's vendor. The vendor (HTC in this case) obviously hasn't signed CWM Recovery, so it wasn't possible to load it.
I had a stroke of luck here - as it turns out, HTC allows for unlocking the bootloaders in their phones for free. You just have to turn the phone on in the fastboot mode, execute a command written on the website, copy and paste some data that the phone outputs, then execute another command. Ok, let's try: I chose an appropriate model, at which point the site informed me that I have to update the phone's software first. I decided to try that later, because I feared losing the data I was supposed to recover. The phone entered the fastboot mode and printed the token that I had to paste on the website, which I did. The website responded with an unlocking key... that didn't work. Eh.
Ok, then - I downloaded the software needed for the update and launched it, but the update wouldn't work. The software wouldn't detect the phone at first, and when it finally did, the flashing was ending with an error. I almost gave up at that point.
Fortunately, while desperately looking for a solution, I stumbled upon a tutorial for bootloader unlocking, where the author said to pick an "Other model" option on the appropriate screen, instead of choosing a particular one. I tried it - I generated the token again, pasted it on the website, then used the key I got... and it worked, the bootloader got unlocked! All the trouble with trying to update the software was totally unnecessary.
Having unlocked the bootloader, I uploaded recovery and I succeeded in connecting to a shell on the phone. The website that described the process of turning ADB on talked about modifying two files:
/system/build.props. I edited them and rebooted the phone, but ADB still didn't work. I checked the files again, and to my surprise, there was no trace of my modifications. What the hell?
Long story short - it turned out that the files I edited were only present in the RAM. The appropriate partitions weren't mounted by default. I mounted them and managed to turn ADB on, but I noticed a scary thing in the meantime - namely, that the data partition, which was supposed to contain the data to be recovered, looked pretty empty. Apparently at some point (and I suspect the unnecessary update attempts...) I did something that reset the partitions to the factory state. Fail.
Regaining control - hacking the touchscreen
I lost the data, but I decided that I will at least find a way to control the phone to some extent. I knew that there exists a possibility of controlling the phone somehow via ADB, so I started looking for programs that did that. One of them, ADB Control, looked exactly like something I wanted - it showed a screenshot from the phone in a window and was sending all mouse clicks and drags to the phone as touchscreen events.
I downloaded the program and tried to launch it, but again - it would be too easy. It did start, I admit, but it didn't download any screenshots and just displayed a black window. A glance at the console told me that there was a problem in making screenshots.
A deeper look at the problem showed that the Android version on the phone didn't contain many nice applications that ADB Control tried to use. Among others, it didn't have a program for taking screenshots, nor one for sending touchscreen events. Brilliant. But for now let's start with the screenshots.
A short trip to Google allowed me to find a ready program for taking screenshots. I uploaded it to the phone and executed it via ADB - it worked. Awesome. I modified ADB a bit (fortunately, the author made the source code available - bless him) and the screen started correctly showing in the window. I still didn't have working touch events, though.
Modern Android versions have a program called
input that supplies two interesting commands:
input tap and
input swipe. The first one simulates a tap on the screen, and the second one - a swipe (duh). This was what the author of ADB Control used. Unfortunately, the version on the phone I was taking care of didn't have those commands. I managed to find some mentions of a
sendevent command, which also makes it possible to simulate touch events, but much less pleasantly. Oh well, at least I had something.
Tough luck, though - the examples with
sendevent I found weren't working. I was sending correct (according to the Internet) event codes to every input device possible, but there was just no reaction. It looked like the end of the fun again.
I found a way of monitoring the input devices and it turned out that a small part of the touchscreen shows some residual activity. When touched, it was sending some data to the system... but this data was completely different from what I was seeing on the Internet. Nothing extraordinary, then, that I couldn't make the phone react. The only problem now was, I knew that the data I was sending was incorrect, but I still didn't know what was correct. Analysing what the real touchscreen was sending didn't tell me much, because it was only sending two things again and again. I couldn't make much of it.
There was one last thing I could try. One last place, where I could find out what the kernel expects from the touchscreen - the source code of the aforementioned kernel. Fortunately, Android is based on Linux, which means that its code is GPL-licensed and had to be made available by the phone's vendor. And indeed, on the HTC website you can download the full source code of the software for various models. I found the correct one and downloaded the file.
Finding the driver's code turned out to be surprisingly easy. I managed to get the driver's name from the console earlier, so I just grepped for that and found the correct file:
drivers/input/touchscreen/cy8c_tma_ts.c. I opened the file and started browsing.
It was also surprisingly easy to find an interesting part: the
cy8c_ts_probe function, containing some references to event codes I've seen before in the Internet. I managed to deduce the correct event format from it. Of course, it turned out to be totally different than in most phones, so that explained why the examples I was finding didn't work. I also found out what the data sent by the last surviving part of the screen meant - those were signals of a touch event at one particular point and some info about the touch pressure.
Knowing the appropriate event codes, I modified ADB Control a bit, so that it was using them to simulate taps and swipes. After small corrections (the touchscreen apparently used different coordinates than the display and some scaling was needed) - success! I managed to unlock the screen with a virtual swipe and start to browse the phone's contents.
Unfortunately, I confirmed that there wasn't any data to be recovered anymore. The main goal was lost, but at least I learned something.
First, hacking things is fun! :p The fight with hardware and slowly bending it to my will was really exciting.
Second - Open Source is great. Had the kernel code been unavailable to the public, I would have never found out how to emulate this particular touchscreen.
And third - there is no reason to fear the operating system's source code. Of course, it does some advanced things, but at the end of the day it's just another program. Its code looks totally incomprehensible at the beginning, but that's how it is with every code you don't know yet. After a while you start seeing patterns and you can understand quite a bit. Of course, I expect that the Linux kernel developers deserve much credit here, as they care about the code being as clean as possible :)
To sum up - such low-level hacking is really entertaining, and you can learn a lot from it. 10/10, would hack again ;)