 Hello everyone, thank you for attending this talk. I am Slava, I am a security researcher at Checkpoint. Security research is my daily work. Today I am going to show how an Android application can attack the digital signal processor of a mobile device and thereby gain privileges and denial of service capabilities. Let's begin with a question. Do you know how many processors are on your mobile phone? The answer is many. As a single Snapdragon system on a chip, embedded in Pixel, Samsung, Xiaomi, LG, OnePlus, Sony and other devices, may include multiple CPU cores, an Android or graphic processor unit, a Snapdragon VIRUS modem, a hexagon digital signal processor and Spectra image signal processor. Snapdragon product tiers are differentiated by scalable computing resources for the CPU, GPU and DSP. The lowest tiers might contain only a single hexagon DSP, whereas the premium tier contains up to four hexagon DSP processors dedicated for specific use cases. These are modem DSP, known as baseband audio DSP, computer DSP and sensor DSP. In this research, I turned my attention to ADSP and CDSP subsystems. ADSP and CDSP processors are intended for such cool tasks as processing of audio and voice data, computer vision, machine learning calculations, camera streaming, artificial intelligence, etc. On some devices, such as the Sony Xperia XZ, only the ADSP processor is responsible for all these tasks. But on other devices, such as the Pixel 4, these tasks are shared between ADSP and CDSP. Let's take a look at the communication scheme between an Android application and an ADSP running library. First RPC is the Qualcomm proprietary RPC mechanism used to enable remote function calls between application processors where Android is run and DSP. On Android's side, user-mode process initiates the remote invocation. In our case, an Android application calls one of the STAP functions in its native code. STAP is auto-generated code that converts the function call to an RPC message. Generally, the STAP code is compiled as a separate native library. The STAP code loads libADSPRPCSO and libCDSPRPCSO built-in libraries to invoke Android drivers. DSP RPC drivers send the queued message to the DSP side through the shared memory driver channel and then wait for the response. On DSP side, a framework presented by the fast RPC shell binary dequeues the messages and dispatches them for processing by a skeleton code. And again, skeleton is an auto-generated library that un-martials parameters and calls the target method in the object library. The object library is some logic provided by Qualcomm or OEMs and designed to run on a DSP. Who can run the oven code on DSP? Any third-party developer can implement its oven DSP library because the hexagon SDK, which is responsible for compiling CC++ code in the hexagon bytecode, is publicly available. But it's impossible to run a third-party library on DSP. For security reasons, DSP is licensed for programming by OEMs and code running on the DSP is signed by Qualcomm. Who manages the DSP? It's CURED, a Qualcomm proprietary multi-threaded real-time operating system. Integrity of the CURED is trusted by the TRAS zone. CURED executable binary, different for ADSP and CDSP, is signed and split into several files, in the same way as any other trusted application on Qualcomm devices. For each Android process initiating the remote invocation, CURED creates a separate fast-RPC shell process on the DSP. The DSP architecture provides different protection domains, PD. Kernel PD has access to all memory of all domains. GuestOS PD has access to the memory of its oven PD, the memory of the user PD and some system registers. User PD has access only to its oven memory. Skeleton and object libraries, as well as the fast-RPC shell, are running in the user protection domain. The stop codes provided by Qualcomm or OEMs can be skipped from the fast-RPC chain. As was mentioned, live-ADSP-RPC and live-CDSP-RPC libraries are responsible for communication with DSP-RPC drivers. Each library exports two major functions. RemoteHandleOpen function opens a remote session between the client-on-application processor and a new fast-RPC shell process on the DSP. The Skeleton library name is provided as the first argument. RemoteHandleInVoc function is able to invoke methods exported by the Skeleton library. Using these two functions, an Android application can request to execute any Skeleton method without using a stop code. Now we have enough information to state the downgrade vulnerability. DSP libraries are assigned and cannot be pitched. However, any Android application can bring a sign by Qualcomm Skeleton library in its assets and then open a remote session. The library will be successfully loaded on the DSP because its signature is correct. The fact that there is no version check of loading Skeleton libraries opens the possibility to run a very old Skeleton lib with no one-day vulnerabilities on the DSP. Even if the pitched Skeleton library already exists on the device, it's possible to load the old version of this library. Any DSP code fix can simply be bypassed by an attacker. Due to the lack of list of Skeleton libraries permitted for the device, it's possible to run a library intended for one device, for example, Chinese Xiaomi, on any other device, for example, Samsung. This means that a vulnerability discovered in one of OEM's libraries compromises all Snapdragon-based Android devices. Okay, the major goal of the research was to find a way to execute custom code on a DSP by passing Qualcomm's signature. To do this, we had to discover and exploit a vulnerability in a DSP-running library. DSP libraries are proprietary hexagon apps. The easiest way to instrument a hexagon executable is to use the open source quick emulator, QMU. Hexagon instruction set support was added in the QMU only at the end of 2019, and we fixed a lot of bugs to be able to run a real DSP libraries in the user mode of the emulator. To fast-lips on Ubuntu PC, we used American Fizer loop, AFL, in combination with QMU. A skeleton library is primarily a library, and we had to prepare a simple program, ScaleLoader, that loads and invokes the one. Moreover, most skeleton libraries widely use DSP framework and system calls. Our simple program cannot handle such requests, and therefore we had to load, like, huge OS on the emulator before execution of the rest code. The easiest way to do so is not to use the real QTOS, but its light version, runALFPBN, adopted by Qualcomm for its execution on a hexagon simulator and included in the hexagon SDK. That's it. The AFL permutates the content of the data file and triggers the execution of runALFPBN on the emulator. QMU returns a code coverage matrix to the AFL after execution of the test case. On this slide, you can see the data format that we used to fast-skill it on libraries. The first world is the second argument of the remote handle and walk function. The index of the invoked method, number of input and number of output arguments are encoded there. Next, several words we take as the size of arguments and then we expect to see a value of input coverage. We were surprised by the fuzzing result. Crushes were found in all DSP libraries that we choose to fast. Besides, most issues were discovered exactly in skeleton libraries, and this means that hexagon SDK produces the vulnerable code. Hexagon SDK automatically generates stop and scale code for marshalling and un-marshalling of function arguments. Let's take a look at an example of such code. Stop and scale code based on interface definition modules, IDL modules, prepared by the developer. Here you can see an example of the IDL declaration of two functions in the neural network library, hexagon NN, a vulnerable code will be generated for both of them. Hexagon NN SNP print function passes an input output buffer argument to the DSP. In the stop code, this buffer will be split into two separate buffers, the input and the output. The value of the input buffer length will also be duplicated for serialized bytes. The scale function copies the input buffer to the output buffer before calling an object function. The size of data to be copied is one of the transmitted buffer lengths. An attacker controls this value. All verification checks can simply be bypassed by using a negative input buffer length. Type casting to the signed int type on checking a buffer boundaries is a buff leading to heap overflow. To summarize, the automatically generated code injects vulnerabilities into the libraries of Qualcomm, OEMs and all other third party developers who use the hexagon SDK. Dozens of SDK skeleton libraries installed on Android smartphones are vulnerable due to serious bugs in the SDK. So, we discovered many vulnerabilities. Let's explore one of them. LeapFast CD-ADSP Scale SOW library can be found on most Android devices. In this example, I used Leap Extracted from the Sony Xperia XZ Premium device. A malicious Android application can cause this Leap to crash by providing crafted arguments to the remote handle invoke function. The 3F method allows us to read and write everything that we want within the other space of the DSP process. It's enough to implement an exploit and execute an unsigned payload in the user protection domain. Okay, we got code execution. What can we do with it? We can crash the DSP. We can hide malicious code. We can try to access camera sensors and more. Besides, now we can communicate with cured drivers. The next step of the research is to attack the cured privileged domains from the user protection domain. And cured drivers are the entry points for this. Cured OS implements its own device driver model named Cured Driver Invocation. Linux, POSIX and CUDE device drivers operate these high privileges than user port. Dozens of CUDE drivers can be found in the cured binary. Leap cured A library which is part of Hexagon SDK contains the cured infrastructure. Faster PC shell is linked statically with this library. CUDE provides a simple driver invocation API where the ability to access a device driver based only on the driver name. Actually, only cured CUDE handle and walk macro is the necessary user-visible API. It's responsible for all generic driver operations. The cured CUDE Open is just a special case of this macro. To fast CUDE drivers on Ubuntu PC we used the same combination of Hexagon QNU and AFL as for fuzzing both user-mode DSP libraries. CUDE drivers were not included by Qualcomm in the run ELF-PB version of CUDE. Therefore, we had to patch the run ELF file. What did we do? We appended program segments of CUDE ELF from a real device and redirected malloc and mem copy kernel functions used by CUDE drivers to their user-mode implementation. Our simple CUDE exact program is responsible for calling a driver invocation function by its address. First of all, any failure in CUDE drivers can be used to reboot the mobile device. For example, each of the lines of this code will cause a DSP panic and can be used for a denial-service attack on a device. For research purposes, we exploited one of discovered vulnerabilities in G-Link CUDE driver. Along with the user PD exploit it allows us to run a custom code in the context of the guest OS protection domain. Now I'll show a simple demo to prove the full stack attack chain. The payload will return a DSP internal data inaccessible from application processor. The device is a pixel. I'm using the ADB shell to run a tool that performs the attack. An Android application can run this tool as well. The first stage of the attack is to execute a code in the context of user PD. Then the user payload triggers the guest OS code execution vulnerability and then I dump sensitive data such as the acute data segment and then controls the form. For example, I reviewed it. Instead of a conclusion, I just want to know that Hexagon ADSP and CDSP subsystems are very promising areas for security research. The DSP is accessible from Android applications, has access to interesting data for an attacker and has many security issues. Thank you for your attention.