• Introducing XDA Computing: Discussion zones for Hardware, Software, and more!    Check it out!

Evaluating CVE-2015-1474 to escalate to system privileges

Search This thread

dadreamer

Member
Dec 5, 2015
25
2
Is your goal to gain root on FireOS v3/v4/5 or are you experimenting with this for other reasons?
As I said earlier I would like to get temp root for Docomo Fujitsu Arrows NX F-01F and this CVE is the one of several vulnerabilities which I could use to pull out boot block. I expect that boot image to be used in iovyroot later. No any other root methods work for my device. I tried almost everything (KingRoot, Towelroot, eRoot, vRoot, KingoRoot etc.).
 

DB126

Senior Member
Oct 15, 2013
15,268
10,044
As I said earlier I would like to get temp root for Docomo Fujitsu Arrows NX F-01F and this CVE is the one of several vulnerabilities which I could use to pull out boot block. I expect that boot image to be used in iovyroot later. No any other root methods work for my device. I tried almost everything (KingRoot, Towelroot, eRoot, vRoot, KingoRoot etc.).
Sorry - I skipped over the page with our prior engagement and thought that conversation was with a different member (in a different thread). Hope this works out for you.
 

Top Liked Posts

  • There are no posts matching your filters.
  • 7
    Take a look at the thread below, It looks like there is already some research begin done but I can't quite get my head around whether they are on the right track. This might help us get going in the right direction though.

    http://forum.xda-developers.com/not.../rd-rooting-n910a-n910v-models-t3042045/page6

    Good news ( @Phate123, @awinston )! I have managed to crash the surfaceflinger on 4.5.2 (should also work on 4.5.3).

    I'll upload the code on github, but first I want to briefly explain how I did it.
    In Android everything that is a graphical element is represented by an GraphicBuffer.
    GraphicBuffers are wrapped in BufferItems and managed by BufferQueues.
    Each Queue has two sites, a producer side (IGraphicBufferProducer) and a consumer side (IGraphicBufferConsumer). In the basic scenario an app is the producer and the surfaceflinger is the consumer. These are obviously two different processes, but both must use the same BufferQueue.
    BufferQueues are always created and owned by the consumers and consequently live in the same address space as the consumer. Producers must go through Binder to access their side of the queue.

    As with everything in Android, the BufferQueue provides the same interface for both native (in the same process) and remote usage. The remote interface is implemented by a proxy that communicates through Binder with the other side.
    In android KK BufferQueue implements the native side of the interface for both the producer (BnGraphicBufferProducer) and the consumer (BnGraphicBufferConsumer). These native implementations must provide a handler (onTransact) for requests that come from the remote proxies.

    You can read more at https://source.android.com/devices/graphics/architecture.html.

    Naturally, the first idea that comes into mind is to attack the native implementations of the BufferQueue that reside in the surfaceflinger. As the bug is in the unflatten routine of GraphicBuffer, we would like to craft a rogue parcel that represents a GraphicBuffer and then wait for the surfaceflinger to choke with it.
    Unfortunately, from my findings, the bugged unflatten method is not called from the onTransact handler in the native implementations.

    Only the proxy implementations seem to be a valid target, through BpGraphicBufferProducer::requestBuffer and BpGraphicBufferConsumer::aquireBuffer. Now we have a problem: as the BufferQueue resides in the surfaceflinger, there is no proxy implementation to attack.

    Our only hope is to somehow create the BufferQueue in our process, so that we are the consumers, and use the surfaceflinger as the producer. This way the surfaceflinger would be accessing the BufferQueue through the bugged proxy (BpGraphicBufferProducer::requestBuffer). One way to use the surfaceflinger as a producer is to make screen captures.

    I found the screencap command to be a very nice starting point to tinker with the idea as it does exactly what we wanted - it uses the surfaceflinger as a producer and pulls screen captures from it. Next I only had to hook the vtable entry of BpGraphicBufferProducer:: onTransact.

    Now we have to control the overflow in GraphicsBuffer::unflatten.
    6
    Would you mind sharing your code even though it doesn't look like you will be able to exploit this overflow? I am still trying to get my head around the basic attack through surface flinger and it would help me greatly to better understand how at least in theory this works. No worries if you don't want to.

    Here you go: https://github.com/p1gl3t/CVE-2015-1474_poc.
    5
    I hope that with this thread we are able to gain system privileges with the help of CVE-2015-1474.

    To begin with I try to write down what I have found. This is just a compilation of information so they might look mixed up.

    The class GraphicBuffer is utilized by the system service SurfaceFlinger. My current understanding is that the vulnerable method "unflatten" is used to create a GraphicBuffer object from raw data that is sent to the service by IPC using Binder. A forged message might be easiest supplied via adb shell using this commando
    Code:
    [email protected]:/ $ service call SurfaceFlinger ...
    I am not sure yet how the parcel get's eventually to the GraphicBuffer. It is a lot of code and I do not understand the low level graphics system of Android yet. The IGraphicBufferConsumer interface has a sub class BufferItem which has also an unflatten method which will call unflatten on GraphicBuffer. My gut tells me that the Parcel class is also involved in that process, but I'm not sure how yet.

    One important piece of information that I'm still missing is how the unflattened data is used in the further processing of SurfaceFlinger. I don't think it is possible to freely write in the memory of SurfaceFlinger with this bug. There are still a lot of sanity checks to come by.

    This could also effect on how we have to implement the communication with SurfaceFlinger. Maybe it's also possible with some forged objects and a SurfaceView.

    Maybe together we are able to bring some light into this. A little bump in the right direction might help.
    4
    @jcase Says no on those camera group holes. http://forum.xda-developers.com/showpost.php?p=58945240&postcount=18

    It's good to see other's working on 2015-1474 also :good:

    @jcase is right, only mediaserver is executed under group camera so that it can access /dev/video*. You can see that in init.base.rc and ueventd.qcom.rc.

    Now returning to the original topic... I fiddled around with unflatten, giving some input that should have made it crash.
    What I did is I left numInts untouched and set numFds = -numInts. I was expecting surfaceflinger to crash every single time when it did the first memcpy. Somehow it didn't. I was baffled and had to gdb the process to see where my assumptions were wrong.
    I breaked just before the first memcpy and printed the params:
    Code:
    (gdb) p $r0
    $19 = 3074255348
    (gdb) p $r1
    $20 = 3074340312
    (gdb) p $r2
    $21 = 4294967248
    r0 is the destination, r1 the source and r2 the number of bytes to copy. r2 is the unsigned representation of 4 * (-12) = 4 * numFds = -4 * numInts.
    How did the program NOT crash???!! It even worked a second time, but crashed with SIGABRT in a free() because of heap corruption (I suppose). So even the second memcpy passed without segfault.
    Here you have the memory map of surfaceflinger.


    LE I have traced the memcpy. It looks like this on my Apollo 14.4.5.2
    Code:
    .text:0002218C __memcpy_base
    .text:0002218C                 CMP             R2, #4
    .text:0002218E                 BLT.W           loc_222DC
    .text:00022192                 CMP             R2, #0x10
    .text:00022194                 BLT.W           loc_222BE
    .text:00022198                 CMP             R2, #0x20
    .text:0002219A                 BLT.W           loc_222AE
    .text:0002219E                 CMP             R2, #0x40
    .text:000221A0                 BLT             loc_222A2

    It seems like R2 (number of bytes) is treated like a signed int and the first branch is taken and the following instructions are executed
    Code:
    .text:000222DC loc_222DC                               ; CODE XREF: __memcpy_base+2
    .text:000222DC                 LSLS            R2, R2, #0x1F
    .text:000222DE                 ITT CS
    .text:000222E0                 LDRCSH.W        R3, [R1],#2
    .text:000222E4                 STRCSH.W        R3, [R0],#2
    .text:000222E8                 ITT MI
    .text:000222EA                 LDRMIB          R3, [R1]
    .text:000222EC                 STRMIB          R3, [R0]
    This ends up copying only n & 3 bytes, which is < 4. Basically, only the 2 least significant bits from n matter).

    So... I guess we are able to write to h->data + numFds*4 as long as numFds*4 is negative. But having numFds as an offset may hurt us on the malloc side.
    Now we have to defeat aslr somehow.
    1
    Crashed unflatten as well

    Okay so I crashed unflatten as well. Trying to figure out where to go from here. I am a little confused though because I did it natively by calling unflatten directly from a cpp program I wrote with a few lines of code. When you crash it like this how do I know it was the buffer overflow? Sorry, still trying to learn as I go.

    03-05 17:06:47.380 2652-2652/? A/libc﹕ Fatal signal 11 (SIGSEGV) at 0x52464247 (code=1), thread 2652 (screenshot)
    03-05 17:06:47.490 258-258/? I/DEBUG﹕ *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
    03-05 17:06:47.490 258-258/? I/DEBUG﹕ AM write failure (32 / Broken pipe)
    03-05 17:06:47.490 258-258/? I/DEBUG﹕ Build fingerprint: 'Amazon/thor/thor:4.4.3/KTU84M/13.4.5.2_user_452004220:user/release-keys'
    03-05 17:06:47.490 258-258/? I/DEBUG﹕ Revision: '0'
    03-05 17:06:47.490 258-258/? I/DEBUG﹕ pid: 2652, tid: 2652, name: screenshot >>> ./screenshot <<<
    03-05 17:06:47.490 258-258/? I/DEBUG﹕ signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 52464247
    03-05 17:06:47.490 955-1055/? W/NativeCrashListener﹕ Couldn't find ProcessRecord for pid 2652
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ r0 b723dfb8 r1 47424652 r2 be94a600 r3 00000020
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ r4 b723dfb8 r5 be94a618 r6 52464247 r7 be94a604
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ r8 be94a600 r9 00000000 sl be94a618 fp be94a6ec
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ ip b6f08f44 sp be94a590 lr b6f04f4b pc b6e34b94 cpsr 200b0030
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ d0 0000000000000000 d1 0000000000000000
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ d2 0000000000000000 d3 0000000000000000
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ d4 0000000000000000 d5 0000000000000000
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ d6 0000000000000000 d7 55ab5f0000000000
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ d8 0000000000000000 d9 0000000000000000
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ d10 0000000000000000 d11 0000000000000000
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ d12 0000000000000000 d13 0000000000000000
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ d14 0000000000000000 d15 0000000000000000
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ d16 0000002000000001 d17 0000000000000020
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ d18 b723a630b723a618 d19 b723a658b723a648
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ d20 b723a678b723a668 d21 b723a698b723a688
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ d22 b723aaf8b723a6a8 d23 b723af58b723af48
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ d24 0000000000000000 d25 0000000000000000
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ d26 0000000000000000 d27 0000000000000000
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ d28 0000000000000000 d29 0000000000000000
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ d30 0000000000000000 d31 0000000000000000
    03-05 17:06:47.500 258-258/? I/DEBUG﹕ scr 00000010
    03-05 17:06:47.510 258-258/? I/DEBUG﹕ backtrace:
    03-05 17:06:47.510 258-258/? I/DEBUG﹕ #00 pc 00005b94 /system/lib/libui.so (android::GraphicBuffer::unflatten(void const*&, unsigned int&, int const*&, unsigned int&)+23)
    03-05 17:06:47.510 258-258/? I/DEBUG﹕ #01 pc 00002f47 /data/local/tmp/screenshot
    03-05 17:06:47.510 258-258/? I/DEBUG﹕ #02 pc 0000e4db /system/lib/libc.so (__libc_init+50)
    03-05 17:06:47.510 258-258/? I/DEBUG﹕ #03 pc 0000308c /data/local/tmp/screenshot
    03-05 17:06:47.510 258-258/? I/DEBUG﹕ stack:
    03-05 17:06:47.510 258-258/? I/DEBUG﹕ be94a550 00000000
    03-05 17:06:47.510 258-258/? I/DEBUG﹕ be94a554 b6010001
    03-05 17:06:47.510 258-258/? I/DEBUG﹕ be94a558 00000000
    03-05 17:06:47.510 258-258/? I/DEBUG﹕ be94a55c b6e0d44b /system/lib/libgui.so

    ---------- Post added at 12:26 AM ---------- Previous post was at 12:12 AM ----------

    Okay so I crashed unflatten as well.

    Is the trick to do it through the surfaceflinger process because it is running with escalated privileges?