A few days ago, the company Armis published a proof of concept (PoC) of a remote code execution vulnerability in Android via Bluetooth (CVE-2017-0781), known as BlueBorne. Although BlueBorne refers to a set of 8 vulnerabilities, this PoC uses only 2 of them to achieve its goal.
The exploitation process is divided into 2 phases, first the memory leak vulnerability (CVE-2017-0785) is used to know the memory addresses and bypass the ASLR protection, and thus make a call to the function libc library system and execute code on the phone, in this case a reverse shell.
The original source code of the Armis PoC is oriented to Android 7.1.2 on Pixel and Nexus 5X phones, and it is implied that to use it in another model it is only necessary to modify in the code the offsets of libc and bluetooth libraries.
Later we will see how in the version 6.0.1 analyzed, the changes in the code of the bluetooth library are significant, complicating the exploitation and forcing us to make more modifications in the code of the PoC.
To perform some of the following actions it is necessary to have root privileges on the phone.
The first step is to extract the libraries to analyze them on our computer with IDA or Radare.
libc system function
We open libc.so with Radare and look for the system function. As we can see it is in the address
0x3ea04, which we introduce in the variable
LIBC_TEXT_STSTEM_OFFSET = 0x3ea04 +1.
The memory leak allows us to discover in which direction the libraries libc.so and bluetooth.default.so have been loaded.
In the analyzed model, the necessary elements are not in the same position of the extracted memory, so we must look for the values that point inside the libraries and modify the following code according to this.
To perform this task we need to obtain a memory dump, and the section map of the com.android.bluetooth process. It’s important to obtain this data at the same time because these addresses changes each time the process is restarted.
We search in the memory leak a value between 0xb376f000 and 0xb38b5000, for convenience I use the script CVE-2017-0785.py
In my case I used 0xb38b3d80 (line 180), we calculated the offset and updated the variable
BLUETOOTH_BSS_SOME_VAR_OFFSET, without forgetting also to update the element of the result table from which we have obtained this value.
To calculate the base address of libc we follow the same process.
With any of these values we calculate the offset and enter it in the variable
From this moment we can forget the ASLR.
With this code we can show the memory leak of the result variable of the script.
In addition, if we take samples of several processes we can compare them to see which values do not change and take them as a reference.
This variable contains the name of the device that makes the connection and in the PoC version 7.1.2 it is used to enter the system address and the bash command. Later it is detailed so that we will use this variable.
The method I followed to find the memory address of this variable has been to use GDB with PEDA-ARM and searchmem memory search function. This offset is entered in the variable
As we see in the technical detail of the Armis PoC https://go.armis.com/hubfs/BlueBorne - Android Exploit.pdf, if we overwrite R0 with the address of REMOTE_NAME , the btu_hci_msg_process function jumps to the address contained in [REMOTE_NAME + 8], leaving the address of REMOTE_NAME on R0.
Therefore, in this case we enter the memory address of the system function in REMOTE_NAME+8.
The argument that the system function will execute is the content of REMOTE_NAME, so having the system address inside it would cause an error. The people of Armis solve this problem using the following structure, in which the 2 commands are separated with
;, leaving the system address in position 8.
Payload is: '"\x17AAAAAAsysm";\n<bash_commands>\n#'
In version 6.0.1 of Android it is not possible to perform the operation in the same way since this same function does not exist in the library. On the other hand, within the exploitable functions, I have used the
000f1e36 function that also allows us to control the jump direction and the value of
These are the instructions that allow us to control r0 and the jump direction.
ldr r0, [r0 + 4] ... ldr r3, [r0 + 8] ldr r0, [r0] ldr r2, [r3 + 28] blx r2
Simplifying, we have the following equation, where x is the value of 4 bytes that we control.
jump = [[[x+4]+8]+28] r0 = [[x+4]]
To achieve our goal we need to use three pointers to control the jump, and one to control the r0; when originally only one was needed that pointed to system.
The payload used as REMOTE_NAME follows the following structure.
0 4 8 12 16 X +------------------+------+-----------+--------+---------------+ | shellscript_addr | name | name - 16 | system | bash_commands | +------------------+------+-----------+--------+---------------+ Jump address: 1 : [name+4] = name 2 : [name+8] = name-16 3 : [name-16+28] = [name+12] = system r0: 1 : [name+4] = name 2 : [name] = shellscript_addr
Once the code is finished, we test it and observe how, like the original PoC, it is necessary to launch it several times to obtain a satisfactory exploitation.