cve-2014-7920&cve-2014-7921 Analysis of Android right-of-reference vulnerability

Source: Internet
Author: User
Tags cve

No feather @ Ali Mobile Security, more security technology dry, please visit the security blog Ali

This is the right to exploit Android MediaServer, using cve-2014-7920 and cve-2014-7921 to implement the right, from 0 permissions mentioned media permissions, which cve-2014-7921 affect Android 4.0.3 and later versions, Cve-2014-7920 affects Android 2.2 and later versions. Google didn't fix the 2 vulnerabilities until Android5.1. The vulnerability [1] discloses the following process:

January 24, 2016 vulnerability author issued a vulnerability analysis and exploit[2], to get exploit after a few Android versions have not been able to run successfully, then analyze the reason, learn the use of loopholes. Record the following, welcome everyone to exchange study.

Not familiar with the Android binder, please search online learning materials, the following direct analysis of vulnerabilities.

The cause of 0x1 vulnerability

The previous article mentions that these 2 vulnerabilities were implemented in Mediaserver,mediaserver in Main_mediaserver.cpp[3], and its main () function initialized 2 service:

One is audioflinger[4],service name "Media.audio_flinger" and the other is Audiopolicyservice[5],service name "Media.audio_policy ”。

1.1 Memory Write vulnerability

The memory write vulnerability is generated in "Media.audio_policy", the interface class is iaudiopolicyservice[6][7], where the startoutput () interface has an incremented memory write vulnerability, stopoutput () The interface has a decreasing memory write vulnerability.

The Startoutput () interface is defined as:

Startoutput (audio_io_handle_t output, audio_stream_type_t stream, int session = 0)

The Stopoutput () interface is defined as:

Stopoutput (audio_io_handle_t output, audio_stream_type_t stream, int session = 0)

1) Incremental write vulnerability of startoutput

Everyone familiar with the Android Binder knows that the native class for this interface is bnaudiopolicyservice[8], and when the client requests the "Start_output" code, the Startoutput () interface, Bnaudiopolicyservice::ontransact () receives the request, and then executes the following code:

Continue calling Audiopolicyservice:: Startoutput () [9] Method:

Mpaudiopolicy->start_output (mpaudiopolicy, output, stream, session);

Mpaudiopolicy is a audio_policy type, Audio_policy:: Start_output () is defined in Audio_policy_hal.cpp as Ap_start_output (), which is called by the method:

Lap->apm->startoutput () is implemented by the Audiopolicymanagerbase:: Startoutput () method, which calls:

Let's see Audiooutputdescriptor:: Changerefcount () [10] The Code of the method:

When 2 If statements are false, Mrefcount[stream] + = Delta; The statement will be executed.

At this point, if the index stream is controlled, the relative offset memory of the Mrefcount memory will be modified to add Delta. It happens that stream is one of the interface parameters, and there is no checksum, the delta in Audiopolicymanagerbase:: Startoutput () is 1, meaning there is a memory write vulnerability that is incremented by 1. The creation of this memory write vulnerability requires the following conditions:

    • Isduplicated () is false: Fortunately, most of the output is not duplicated by default.
    • (Delta + (int) Mrefcount[stream]) < 0: Because of this condition, the MREFCOUNT[STREAM]<0X7FFFFFFF will be false, which limits the memory write vulnerability, Only memory values that have less than 0x7fffffff memory content can be incremented.
2) Decreasing write vulnerability of stopoutput

The Stopoutput () interface is similar to the Startoutput () interface, and we look directly at the Audiopolicymanagerbase::stopoutput () method, which is called:

Outputdesc->changerefcount (Stream,-1);

Similar to the Startoutput () interface, there is also the same write limit, which is different from a memory write vulnerability that decrements by 1.

1.2 Memory Read Vulnerability

Memory Write vulnerability is also generated in "Media.audio_policy", the problem is in the isstreamactive () interface. The interface is defined as:

BOOL Isstreamactive (audio_stream_type_t stream, uint32_t Inpastms)

Similar to the Startoutput () interface, the interface calls the Audiopolicymanagerbase::isstreamactive () method, which is called by the method:

The Audiooutputdescriptor::isstreamactive () method, the method code is:

If you determine whether Mrefcount[stream] is 0 based on the isstreamactive () return value, you need to meet 2 conditions:

    • Mrefcount[stream]! = 0;
    • Ns2ms (Systime-mstoptime[stream]) > INPASTMS:

Systime-mstoptime[stream] is the time difference value, is positive, when inpastms>=0x80000000, the inequality is established.

Therefore, you can determine whether the value of the relative offset of the Mrefcount memory is 0 by controlling the value of stream and Inpastms.

0x2 using the previous 2.1 tips 1) using memory to read, fuzzy matching Audio_hw_device object

Audio_hw_device This structure contains audio hardware device function pointers, which are called in the interfaces provided by the "Media.audio_policy" and "Media.audio_flinger" service, which facilitates writing exploit. The audio_hw_device structure is defined as follows:

[Photo from original]

The analysis found that the reserved and function_ptrs-> get_supported_devices in the Audio_hw_device object were 0 and the other fields were not 0. The structure can be expressed in the form of 0 and non 0 as:

It is mentioned that the isstreamactive () interface can be used to determine if the memory value is not 0, so combined with the characteristics of the audio_hw_device structure in memory search, it happens to mrefcount in the upper and lower memory area can be searched Audio_hw_device object.

2) Use memory to write, leak memory address

"Media.audio_flinger" provides the getinputbuffersize () interface [11], and the interface is defined as:

Its service-side code is:

When the client calls the Getinputbuffersize () interface, the server ends up calling get_input_buffer_size (), the audio_hw.cpp::adev_get_input_buffer_size () function, Finally, the size is returned. The arm instruction feature shows that, in the disassembly of the get_input_buffer_size (Dev, &config) function, the return value is passed back through R0 by R0 the dev pointer, the Audio_hw_device object, after the function is executed. If you modify the Get_input_buffer_size function pointer so that it points to "BX LR", that can get the memory address of the Audio_hw_device object.

It happens that the get_input_buffer_size () function pointer is also stored in the Audio_hw_device object, using a memory write vulnerability to allow Audio_hw_device. Get_input_buffer_size points to an "BX LR" address to get the Audio_hw_device object address.

2.2 Step into the pit

The author in debugging exploit occurs several times crash, the update after the exploit placed in Https://, the compilation environment: Android 4.3_r2.1, operating environment: AVD 4.3 (4.3_r2.1).

1) MediaServer crash when searching for Audio_hw_device objects

When you run exploit, you can search for Audio_hw_device objects, but MediaServer crash, possibly due to the large memory range of the search, which leads to illegal memory access. Try to narrow your search, such as setting Max_offset to-3000.

2) Always get no adev_open_output_stream () address

The author uses the original gadget read_r0_offset_108 on AvD 4.3 and always gets a pointer to the Adev_open_output_stream function. Then a gadget (thumb) was found in the

3) Android 4.4.2 on crash

At the beginning of the author in AvD 4.4.2 execution exploit is always unsuccessful, debug found Audio_hw_device. The value of the get_input_buffer_size is set to 0, such as:

Because the base load in MediaServer is greater than 0x7fffffff, which is mrefcount[offset_get_input_buffer_size] > 0x7FFFFFFF, which is negative, is used in increments of 1/decrement 1 o'clock, Changerefcount () method, if (delta + (int) Mrefcount[stream]) < 0, then Mrefcount[stream] is set to 0. It's hard to take advantage of success on 4.4.2.

0x3 Exploit Analysis 3.1 Search Audio_hw_device object relative offset

2.1-1 refers to the use of the features of the Audio_hw_device structure to search for matching objects in the MediaServer process. The memory Read vulnerability of isstreamactive () is used to read the Mrefcount attachment memory area to produce 0/non 0 memory mappings, and then match the Audio_hw_device structure features to calculate audio_hw_ The relative offset of the device object relative to the Mrefcount.

3.2 Bypass ASLR

2.1-2 mentions using memory write exploits to get memory addresses, let's analyze how exploit uses memory writes to bypass ASLR.

1) Get base Address

First modify the Audio_hw_device. Get_input_buffer_size the value of the pointer, get_input_buffer_size the original point to adev_get_input_buffer_size, and modify it to point to the X1e290+1, as Gadget1, the code is as follows:

Where Library_offset is the offset between the Lib base address used and the base address of the library, Gadget_offset is the offset from the base address of the Lib library; relative_address_of_ Get_input_buffer_size is the offset of the Adev_get_input_buffer_size function address in; the Modify_value () function is memory increment 1/ Decrements the encapsulation of the 1 operation. Gadget1 is:

Then call Audioflinger::getinputbuffersize () to jump to Gadget1.

uint32_t read_function_pointer_address = af->getinputbuffersize (0, (audio_format_t) 0, (audio_channel_mask_t) 0);

Gadget1 executes R0 as Dev is Audio_hw_device object, reference audio_hw_device structure, r0+0x64 is Open_output_stream, Adev_open_output_stream value, Returned by R0.

Minus the offset of adev_open_output_stream in read_function_pointer_offset_from_base_address, You can get the base address of

2) Get Audio_hw_device object address

Modify the Audio_hw_device. The get_input_buffer_size pointer makes it point to, which is Gadget2:

The Gadget2 runtime returns the value of Dev (R0) directly, which is the address of the Audio_hw_device object.

3) Set Write gadget

Modify the Audio_hw_device. Get_input_buffer_size is, recorded as Gadget3, using the code as follows:

Let's take a look at the Audioflinger::getinputbuffersize () method, where:

See GADGET3, write Data call interface Getinputbuffersize (address, 0, value) (this interface is defined as Getinputbuffersize (Uint32_tsamplerate, audio_format_t Format, audio_channel_mask_t channelmask)), when you go to get_input_buffer_size (Dev, config), R0 is Dev, R1 is &config, Gadget3 is executed as follows:

At this point we will audio_hw_device. Get_input_buffer_size points to Gadget3, and then calls Getinputbuffersize (address, 0, value) to write value to address-0xc memory.

3.3 Layout Gadget Buffer

Write the system () function address and parameters to audio_hw_device.reserved, and then modify Audio_hw_device.get_input_buffer_size to point to a call gadget when calling get_ again. Input_buffer_size () When call gadget is triggered.

1) write to the system () function parameter

See Using code:

The WRITE32 () function writes data into 2 steps:

A) Set the data offset

Call Modify_value (APS, G_primary_device_offset + 1, offset-g_current_write_offset); Modifies the contents of the Dev.version, which is the array offset for subsequent data writes, and dev.version decrements from 0x200 until 0xC for the first time:

b) Write Data

Call Af->getinputbuffersize (g_primary_device_address + sizeof (uint32_t) +, (audio_format_t) 0, (audio_channel_mask _t) value) triggers Gadget3 execution, which is broken on Gadget3 when debugging:

At this point R0 points to dev,r1 for &config:

View [R1] memory, r1[0] is config. Samplerate is the address, which addresses are to be written, &dev[0]+4+12, r1[1] as CONFIG. Channelmask is value, which is "/dat":

The pseudo-code for GADGET3 is roughly as follows:

After the gadget (one time) has run, the data has been written to the Audio_hw_device object:

2) write to the system () function address

The address of the system () function is computed from the base address of the, and the call Gadget3 writes to dev+36:

3) write to call gadget

Call Gadget3 to modify Audio_hw_device. Get_input_buffer_size the value of the pointer, using point,, as Gadget4.


3.4 Triggering Code execution

Use the code to:

Af->getinputbuffersize (0, (audio_format_t) 0, (audio_channel_mask_t) 0);

When Getinputbuffersize () is called, gadget4 execution is triggered:

Register Value:

Call the system () function to load the outer command/data/local/tmp/a. The author wrote a remote shell named A, is successful after the execution of the shell, for "Media" permissions:

0x4 Reference Links













No feather @ Ali Mobile Security, more security technology dry, please visit the security blog Ali

cve-2014-7920&cve-2014-7921 Analysis of Android right-of-reference vulnerability

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.