Armed with Al’s recent blog on SMS PDUs we now have a way of launching an attack against one of these devices, but in order to find weaknesses to exploit, we must heed General Tsu’s words and have a clear idea of the attack surface that is presented to us. Knowing ourselves means we better get the coffee brewing, we’re going to need it.
With the first cup of coffee brewed we start at where the received radio signals become bits and bytes in the modem (aka baseband) of the phone.
In modern phones, the baseband can be considered a separate entity to the main application processor (the one running Android/iOS etc) since it uses a separate processor and runs a real-time operating system (RTOS). Architectures for the baseband can vary, with some running on ARM CPUs and others (such as those running with Qualcomm System-on-a-Chip systems) using a Digital Signal Processor (DSP) with a bespoke ‘Hexagon’ architecture.
From a vulnerability research perspective, the bad news is that Qualcomm is by far the industry leader in terms of being the most popular chipset on the market ( in 2015, 65% of all LTE/4G basebands ), yet its baseband architecture is the least well understood. There have been attempts to create IDA Pro plugins to correctly disassemble the hexagon firmware code but they are far from complete and do not appear to be being maintained. The silver lining to this is that experience tells us that the less well understood and documented a technology is, the greater the chances of finding bugs.
Regardless of architecture, the good news for baseband bug-hunting is that the firmware images are easy to get hold of, commonly being present in system recovery images in Android systems at least.
Bridging the Gap
As the second cup of coffee brews, it is worth reflecting on what it might mean to become a ‘Man-in-the-Modem’ and why it may not necessarily be the God-Mode that an attacker may seek. Make no mistake, having malware running on the baseband would give you a powerful capability to intercept calls and SMS messages, and be damn near undetectable while you did it. These days however, smart phones are much more than devices used for GSM calling and SMS, and being stuck in the baseband would give you no visibility of the personal data (photos/messages/address books etc) on the device and very limited capability to intercept encrypted messaging being sent over the Internet.
So, in order to achieve true greatness, it is necessary to bridge the gap between baseband and application processor (AP) or, depending on your end-goal, let the baseband do its job as intended and focus on exploiting code running on the main application processor.
No Man’s Land
Now we enter the wilderness that is the interface between the baseband and the Android framework. Given the market share, the Qualcomm approach is used here as a case study, and given that we had one lying around, we used an HTC Nexus 5 for our research.
Traditionally, a well-defined AT standard has been used to communicate with modems, but a bit of Googling revealed that Qualcomm have developed a proprietary alternative to this, known as the Qualcomm MSM Interface (QMI). We must locate the binaries responsible for processing this protocol in order to add them to our attack surface list.
Starting with the assumption that communication with the modem will most likely be a serial connection of some sort, we can use the UNIX tool lsof to find running processes with open file handles to USB/serial devices. After trying some common naming conventions, the following command revealed a promising candidate:
Excellent, the binary starts with a ‘q’ and is running as the Radio user. If more proof were needed that this is an interesting place to look, running strings on the binary revealed:
This looks like it might be what we’re after so let’s investigate further. Using lsof again to reveal the full list of file handles opened by qmuxd:
Apart from the serial devices, the sockets also look interesting. By reading /proc/net/unix the following sockets were found that matched the inode numbers (the numbers in square brackets) in the output of lsof:
The names of the sockets suggest that qmuxd handles the QMI protocol messages for a number of services including the GPS, audio, Bluetooth and what we are specifically interested in, the radio. In order to follow the path of the radio messages, we needed to determine what was at the other end of the Unix domain socket. There are many ways to go about trying to achieve this (none of them particularly definitive) but given that we identified a number of libraries in /vendor/lib that are prefixed with libqmi_, simply looking for the string “/dev/socket/qmux_radio/qmux_connect_socket” in these libraries seemed like a good, low-tech way to start.
Doing this revealed that libqmi-client-qmux.so was responsible for handling the connection to this socket. Using IDA Pro to trace through the call graph within libqmi-client-qmux.so until we found a path that linked this socket connection with an exported function, and then using readelf –s on other binaries to find those that imported it, we were able to build up the following picture of what components were involved in handling communications between the modem, native binaries running on the application processor and ultimately how it talks to Java apps running within Android
While a Qualcomm-based device was used in this example, there was nothing Qualcomm specific in our approach to identifying the attack surface. Variations on this approach could easily be used to reveal a similar map in other non-Qualcomm devices, for example some Samsung devices (such as the European variant of the Galaxy Edge S7) use their own Exynos System-on-a-Chip and talk to the modem using their own proprietary IPC protocol.
In RIL Life
At this point, we reach the boundary between proprietary vendor code that controls the modem and its interaction with the Android framework.
In the diagram above, RILD is where we start to hit Android code. RILD forms part of the Radio Interface Layer and it imports the QMI libraries that we have already covered, but also bridges the gap between native code and the Java code that is used by the Android telephony services (e.g. SMS and phone apps). The RILD has two key components: RILC and RIL. RILC handles the event scheduling whereas the RIL (often referred to as the vendor RIL) handles communication with the baseband. The vendor RIL is closed-source proprietary code and in this instance is written in C, which makes it an attractive target. There is a reasonable amount of information available on the Internet describing the RIL interactions and the AOSP has a reference RIL which can be used as a guide when analysing a closed source implementation.
Source code at last…
Given that we are attempting to define an attack surface in which we want to find bugs, it is worth defining a few components of RILJ that handle messages that the device sends and receives.
The two main components in RILJ that may be of interest from an attacker perspective are RILReceiver and RILSender, which are used to communicate with RILC. Given that we are primarily interested in code executed when we send a message to the device, the RILReceiver is of particular importance.
Referring to the Android Open Source Project (AOSP), the RILReceiver is implemented in RIL.java and is responsible for reading a single RIL message off the socket, unmarshalling it, determining its type and forwarding on to the endpoint for processing. This endpoint could be the GSMPhone app, the SMS app or one of the many other Android apps that handle communication with the outside world.
Finally we have a complete map and we can go and hunt for treasure. Before we decide on where to focus our efforts, it is worth noting that as we rise higher in stack, from baseband all the way to the Android app that presents an SMS, our privileges to gain access to the system are constantly diminishing. A bug in the baseband may open up unrestricted access to all that the baseband provides, but moving just one level higher with a bug in qmuxd (or its equivalent) would leave us in a less-than-root environment on most modern implementations, requiring extra bugs to be found to elevate our privileges. Exploiting a bug in a Java app may leave you with very limited options, unless other bugs are chained together. Despite this, you never know. Remote code execution may be the ultimate goal but logic bugs and denial of service effects can be considered serious issues to fix and so depending on your experience, knowledge and objective, don’t shy away from bug-hunting at higher levels.
Until next time when we shall describe some interesting bugs that we have discovered and disclosed to the relevant vendors, happy hunting!
Contact and Follow-Up
Tom and Neil both work in Context's Research team, in our Cheltenham office. See the contact page for ways to get in touch.