OSX security vulnerability study is gaining more and more popular recently because Mac devices become more and more popular. OSX IOKit exposes large attacking surface for hackers compromising kernel extension and kernel itself from user mode. Many researcher do research on this domain (see Reference section). We will share some research results about this domain.
1. One passive fuzzing framework with context enlightenment to hunt kernel vulnerability.
2. Exploit tricks for how to occupy kernel memory from user mode program to bypass SMAP&SMEP.
3. Utilizing the vulnerabilities which found by our fuzzing method and the new exploit trick to root OSX successfully 2 times.
We introduce a new method 。ーPassive Fuzzing And Context Enlightenment for OSX IOKit。ア which names PFACE.PFACE has following highlight points. Firstly it can meet the condition dependency and permit code execution deeper and wider to hit more codes and get more system crash. And secondly it can output the modules which contains 。ーContexts。ア which is indicator for suspicious vulnerability. These indicators will lead reviewer to review these modules firstly.
If you have a bunch of kernel vulnerabilities, the big problem is how to transfer your ROP gadgets to the kernel space from user mode program because recent OSX already enable SMAP and SMEP. The famous security researcher Stefan Esser proposed that OSData be a good structure to occupy kernel memory [Refenece section 5]. Yes, OSData is a good data structure. But in practice, there are some problems causing OSData not to work. We find a new method that let OSData does work for occupy kernel memory from user mode program. We use the method to exploit the vulnerabilities we found and root OSX (10.11.3) successfully.
In practice, we find tens of vulnerabilities with CVE number, and many kernel crashes which fuzzing effect has been approved. And also we construct two different Local Privilege Escalation exploit to root by using some vulnerabilities of them on Mac OSX (10.11.3 ).
Here below is the CVE and ZDI list until now(NOT including submitted but pending):CVE-2015-3787, CVE-2015-5867, CVE-2015-7021,CVE-2015-7020, CVE-2016-1716,ZDI-CAN-3536,ZDI-CAN-3558, ZDI-CAN-3598,ZDI-CAN-3596,ZDI-CAN-3603,CVE-2015-7067, CVE-2015-7076,CVE-2015-7106,CVE-2015-7109,CVE-2016-1718,CVE-2016-1747,CVE-2016-1749,CVE-2016-1753, ZDI-CAN-3693, ZDI-CAN-3694, CVE-2016-1795, CVE-2016-1808, CVE-2016-1810, CVE-2016-1817, CVE-2016-1820, CVE-2016-1798, CVE-2016-1799, CVE-2016-1812, CVE-2016-1814, CVE-2016-1818, CVE-2016-1816
--- Moony Li & Jack Tang
http://codeblue.jp/2016/en/contents/speakers.html#speaker-li
[CB16] (P)FACE into the Apple core and exploit to root by Moony Li & Jack Tang
1. How we fuzz and exploit the
Apple core
(P)FACE into the Apple core
and exploit to root
2. Agenda
• Who we are
– CVE list
• Passive fuzzing framework
– Approach & consideration
– Implementation
– Context enlightenment
– Best Practice
• Exploit to root
– Security mitigation
– Root
3. Moony Li
- @Flyic
- 7 years security
- Sandcastle
- Deep Discovery
- Exploit Detection
- Mac/Windows
Kernel
- Android
Vulnerability
4. Jack Tang
- @jacktang310
- 10+ years security
- Browser
- Document
- Mac/Windows
Kernel
- Virtualization
Vulnerability
5. So what?
• Here below is the CVE and ZDI list until now(NOT including submitted but pending) since
2015:
CVE-2015-3787, CVE-2015-5867, CVE-2015-7021,CVE-2015-7020, CVE-
2016-1716,ZDI-CAN-3536,ZDI-CAN-3558, ZDI-CAN-3598,ZDI-CAN-
3596,ZDI-CAN-3603,CVE-2015-7067, CVE-2015-7076,CVE-2015-7106,CVE-
2015-7109,CVE-2016-1718,CVE-2016-1747,CVE-2016-1749,CVE-2016-1753,
ZDI-CAN-3693, ZDI-CAN-3694, CVE-2016-1795, CVE-2016-1808, CVE-
2016-1810, CVE-2016-1817, CVE-2016-1820, CVE-2016-1798, CVE-2016-
1799, CVE-2016-1812, CVE-2016-1814, CVE-2016-1818, CVE-2016-1816,
CVE-2016-4648,CVE-2016-4699,CVE-2016-4700,CVE-2016-4750
• Root 10.11.3(then) twice with found bug
6. Agenda
• Who we are
– CVE list
• Passive fuzzing framework
– Approach & consideration
– Implementation
– Context enlightenment
– Best Practice
• Exploit to root
– Security mitigation
– Root
7. So… How Others Fuzz Bugs?
• Traditional fuzzing by IOKit interface
Usually open the IOKit service name which they want to test, and pour fuzzing data into by the IOKit usermode API (e.g.
IOConnectCallMethod)
– Call sequence dependency
• AppleCamIn (OpenDevice, PowerOnCamera…)
– Input data dependency
• AppleHDAEngineInput(input as user mode buffer pointer)
– Timing dependency
• IOHDIXHDDriveOutKernel( mount dmg)
8. Then What About Review?
•Code review of target kernel extension
This costs much effort to reverse engineering binary code and
in the face of so many IOKit services and userclient.
-Un-scalable
-Cost effort RE (upgrade)
9. Our approach:
Why not play (e.g. games) for
bugs
• Both code traditional fuzz and code review are tiring
• What about play (e.g. online games) to hunt kernel
bug?
• The MORE you play games, the MORE bug bounty you
get
• Just like this
10. Why Do You Think So?
Poison Here?
Dam poison Passive fuzzing
River Stream Data flow of code execution
(Open driver, IOCtl
driver……)
Up stream User mode data
Down stream Kernel mode data
Poison at Dam Fuzz at hook of system call
Fish die in
downstream
Kernel crash
Trace the poison
origin
Reproduction
…
11. Agenda
• Who we are
– CVE list
• Passive fuzzing framework
– Approach & consideration
– Implementation
– Context enlightenment
– Best Practice(tasted Zen)
• Exploit to root
– Security mitigation
– Root
13. Architecture Overview
Origianl function
Hooker
IOAcceleratorFamily2.kext
Targeted application from apple store
Suspicious
module/function
manifest
IOThunderboltFamily.kext IOUSBFamily.kext
AppleGraphicsPowerManagement.kext AppleHDA.kext … …
I. is_io_connect_method
II. is_io_connect_async_method
III. iokit_user_client_trap
IV. IOMemoryDescriptor::createMappingInTask
V. ipc_kmsg_get
VI. ipc_kmsg_send
VII. Copyio
…...
Conditon Checker
Ring3
Ring0
Target
drivers
XNU/
IOKit
Tamper
StackFrame,
Process,
UserClient,
MsgID,
…...
Context Matcher
14. Pseudo Code
TargetAPI(params):
//Call Original_TargetAPI(params)
if (matchWhitelistParameter(params)) goto _exit();
if !(matchStackFrame() && matchBlacklistParameter(params))
goto _exit;
if (random()) {record(params); fuzz(params);}
Call Original_TargetAPI(params);
if (matchContext(params)) alert;
15. More Detail? Hooker & Tamper
• Hooker
– Directly accessible from user
– One hook for many processes
• Inline hook in kernel mode.
• Tamper
– Only fuzzing buffer content accessible by user
• Inband_input, scalar_input, ool_input
• NOT size!(bypass getTargetAndMethodForIndex check)
19. Why Condition Checker
•Keep fuzzing stable
– Get rid of noise
• busy call, black screen call, hung call,
• reproduced crashes
•Hunt according to vulnerability context
– Kernel heap leak
– Map user data into kernel and read as buffer size
– …
20. How Checker Works Dimension of condition
1/3
• &&, ||, *(wild match), white(black)
• Process
– User id (root/Non-root)
– Process Name (e.g. Safari, RCE, sandbox-evasion)
• Module
– Module Name
• Function
– Symbol Name/Address
– Offset range
22. How Checker Works Dimension of condition
2/3
•Data
– is_address_RWX
– Copy direction(in/out)
– Kernel or User space (SMAP noise)
•Call-Stack
– Function ret
– Stack Level (from bottom to top)
– Level range[,]
23. Stack Frame Sample
stack_match_item_t stack_matcher_for_copyio[]={
//If any item in list match, then match
//{routineName, cache}, routineAddress, offSetFrom, offsetTo, levelLow, levelHigh
{{"_shim_io_connect_method_scalarI_scalarO",STACK_ANY_INTEGER},STACK_ANY_INTEGER,0, 0xC120-
0xB8B0, STACK_ALL_LEVEL_RANGE},
{{"_shim_io_connect_method_scalarI_structureO",STACK_ANY_INTEGER},STACK_ANY_INTEGER,0,
0xDB94-0xD5C0, STACK_ALL_LEVEL_RANGE},
{{"_shim_io_connect_method_scalarI_structureI",STACK_ANY_INTEGER},STACK_ANY_INTEGER,0, 0xEA97-
0xE490, STACK_ALL_LEVEL_RANGE},
{{"_shim_io_connect_method_structureI_structureO",STACK_ANY_INTEGER},STACK_ANY_INTEGER,0,
0xF588-0xF270, STACK_ALL_LEVEL_RANGE},
{{"_is_io_connect_method",STACK_ANY_INTEGER},STACK_ANY_INTEGER,0, 0xb2a9-
0xaf10,STACK_ALL_LEVEL_RANGE},
}
24. How Checker Works Dimension of condition
3/3
•Misc
– Mach_msg
• msg subsystem id…
– Userclient
• serviceName,ClassName,selector…
27. Why Use Context & What is it?
•Enlightenment for code review
– Buggy module, interface for RE……
•The Pattern accumulated in bug hunting
activities
•No vulnerability but indicates suspicious
vulnerability
•Implemented through condition checker
28. Context Sample
• Some IOKit related memory corruption
vulnerabilities would happen in the following
context:
– Call IOMemoryDescriptor :: createMappingInTask to mapping user mode
buffer space to kernel mode.
– Read a value from the buffer and use it as a size to read or write a buffer.
•Some kernel information leak vulnerability
would happen in the following context:
– The output buffer’s content has 0xFFFFFF prefix.
30. Best Practice/Tips 1/3
• Fuzzing Source:
– Multiple application
• AppStore (MMORPG games, FaceTime,USB hardisk,BlueTooth, Wifi, VM,DirectX…)
• Virus Total, Apple OpenSource UT, github sample code
– Combination of rich kind of fuzzing source
• Active fuzzing, Python watchdog, browsing WebGL
• Fuzzing Stability:
– Bypass active hang, black screen, reproduced cases using condition checker(nvTestlaSurfaceTesla,
IGAccelGLContext, IGAccelSurface…)
31. Best Practice/Tips 2/3
• Reproduction:
– Log through network
– Log to NVRAM? Log to memory and kdp_panic_dump callback?
– Core dump server
• sh-3.2# nvram boot-args=”pmuflags=1 debug=0xd44 kext-dev-mode=1 kcsuffix=development –v _panicd_ip=10.64.80.106”
– Thunderbolt+fwkdp+lldb
• Automation
– kdp_panic_dump callback+dump+reboot?
– VM(Vmware fusion, Qemu…) revert?
32. Best Practice/Tips 3/3
•Misc tricks:
– Occasional fuzz activities recommended
– Normal program running – sudden fuzz
– Keep OS version updated with latest KDK
33. Agenda
• Who we are
– CVE list
• Passive fuzzing framework
– Approach & consideration
– Implementation
– Context enlightenment
– Best Practice(tasted Zen)
• Exploit to root
– Security mitigation
– Root
35. Bugs vs Mitigation
Mitigation Bugs/Exploit Notes
KASLR KSlide leak e.g. CVE-2016-4655 kernel info leak
SMAP Kernel Heap address leak CVE-2016-xxxx: In disk image module, it will
leak a object address, which exists in kernel
heap.
SMEP a. Control RIP
b. ROP Chain
c. Disable CR4 bits
d. Execute any
CVE-2016-1820 : In disk image module, it will
take an object address and use a QWORD
value in the object as function pointer to call.
36. • The OSX/iOS hacking guru Stefan Esser (@i0n1c)
propose OSUnserializeXML is a good way in SyScan
2012
https://reverse.put.as/wp-
content/uploads/2011/06/SyScan2012_StefanEsser_iOS_Kernel_Heap_Armageddon.p
df
Tips of Heap FengShui -
OSUnserialize
37. • In most cases, the OSDictionary allocated by OSUnserializeXML will
be freed by OSObject::release in one system call
。。。
However
38. •If the allocated object is referenced by
another component, it will not be released
even if call object::release to it.
•IORegistry is a good choice for Heap
Fengshui
• So we find OSUnserializeXML invoking
nearby IORegistry method calling …
However
39. •In IOKIT service IOMProotDomain ,
slector 7 (kPMSleepSystemOptions)
RootDomainUserClient::secureSleepSystemOptions
。。。
Always an exception
40. Exploit Process 1/2
payload
Ring3
Ring0
kernel
SMAP
SMEP
KASLR
kslide
Driver
Memory address – Disk Address
Call current_proc
Call proc_ucred
Call posix_cred_get
Call thread_exception_return
IOCommand
Exploit App
ROP Gadgets
mov cr4 rax; ret
Call payload
StackPivot
0x68
IOHDIXHDDriveOutKernel
xxx +0
+0x50
call [leak_addr+0x50]
[1]Leak kernel buffer IOCommand address
[3]Spray freed IOCommand
with OSData [2]Free IOCommand
[0]Leak kslide to
build up payload
[4]Trigger execution
xxx
1. Use KEEN team’s method to calculate
KSLIDE.
2. Call user client
IOHIDIXControllerUserClient ‘s selector
1. From the output , we can get a kernel
heap address of object
IOHDIXCommand. Then call
IOHIDIXControllerUserClient ‘s selector
2. It will release the object.
3. Call RootDomainUserClient user
client ‘s selector 7 with a carefully
prepared XML as parameter , which
include ROP gadget in <data> part.
4. Call IOHIDIXControllerUserClient
Selector 2 to get RIP execution
1. Use KEEN team’s method to calculate
KSLIDE.
2. Call user client
IOHIDIXControllerUserClient ‘s selector
1. From the output , we can get a kernel
heap address of object
IOHDIXCommand. Then call
IOHIDIXControllerUserClient ‘s selector
2. It will release the object.
3. Call RootDomainUserClient user
client ‘s selector 7 with a carefully
prepared XML as parameter , which
include ROP gadget in <data> part.
4. Call IOHIDIXControllerUserClient
Selector 2 to get RIP execution
Welcome everyone
I’m very happy to be presenting here today at the CodeBlue conference.
My name is Moony and I will be presenting today on the topic of How we fuzz and exploit the Apple core.
Today I will cover several key areas
1. First I’ll tell you a little about me and my partner, and what we have done
I will then introduce you to passive fuzzing framework that we use to hunt vulnerabilities.
And finally I will show you exploit tips using the vulnerabilities we have found and how we root OSX machines.
My name is Moony
I’ve worked for 7 years in security.
My role has been to develop sandbox systems.
Focusing on Mac - Windows and Android Kernel vulnerabilities.
Moony Li: Twitter: @Flyic
7 years of security production development
RD Leader of Sandcastle core engine of DD(Deep Discovery) production for Gateway 0day exploit detection.
Current focusing on research about Mac/Windows kernel ,Android vulnerability and exploit
Jack Tang: Twitter: @jacktang310
10 years of anti-malware solution development
Familiar with Windows/Mac kernel technology, browser and document exploit.
Current focusing on research about Mac, virtualization vulnerability and exploit
My partners name is Jack
Jack has worked in security for 10 years
His focus has been on browser and document vulnerabilities as well as Mac – Windows and virtualization vulnerabilities.
Jack cannot be with us today he has broken his leg and is not able to travel.
Moony Li: Twitter: @Flyic
7 years of security production development
RD Leader of Sandcastle core engine of DD(Deep Discovery) production for Gateway 0day exploit detection.
Current focusing on research about Mac/Windows kernel ,Android vulnerability and exploit
Jack Tang: Twitter: @jacktang310
10 years of anti-malware solution development
Familiar with Windows/Mac kernel technology, browser and document exploit.
Current focusing on research about Mac, virtualization vulnerability and exploit
We are proud to have found many vulnerabilities, exploiting them to root OSX machines
Because of our work we have been awarded many CVE credits as shown here
In this section I will first compare different approaches usually used to hunt vulnerabilities
I will then provide you details of
- how we designed our approach and
- how we implemented our solution
Finally I will outline best practice tips during fuzzing activities.
1. Traditional fuzzing by IOKit interface.
These researchers open the IOKit service name which they want to test, and pour fuzzing data into kernel by the IOKit usermode API (e.g. IOConnectCallMethod, IOConnectCallAsyncMethod …)
Optimized Fuzzing IOKit in iOS, Blackhat 2015
https://www.blackhat.com/docs/us-15/materials/us-15-Lei-Optimized-Fuzzing-IOKit-In-iOS-wp.pdf
But it has a critical limitation. It is hard to hunt the bugs which are triggered with condition dependency. We summarize the condition decency as following:
*Call sequence dependency
For example: for the IOKit service “AppleCamIn”, which controls camera device, only correct IOConnectCallMethod call sequence would it work up: OpenDevice -> PowerOnCamera -> … If the fuzzer doesn’t invoke OpenDevice and PowerOnCamera IOKit call, following IOKit call will be returned with failure in earlier stage.
*Input data dependency
For example: the IOKit service “AppleHDAEngineInput” ‘s user client “IOAudioEngineUserClient” requires the input data to include a user mode buffer pointer. If the fuzzer doesn’t prepared the user mode buffer before , error will be returned in earlier stage.
*Timing dependency
For example: for the IOKit service “IOHDIXHDDriveOutKernel”, the service only appears after user or application opens a DMG file. If the fuzzer open it directly , it will fails directly.
2. Code review of target kernel extension
This costs much effort to reverse binary code and in the face of so many IOKit services and userclient. So the target selecting will impact researcher’s efficiency. What target should be reviewed firstly for more possible vulnerabilities is a headache problem.
a. Use KEEN team’s published method (Reference section [7]) to calculate KSLIDE.
b. Open any DMG file in order to let IOHDIXHDDriveOutKernel service can be opened.
c. Open IOHDIXHDDriveOutKernel service ‘s user client IOHIDIXControllerUserClient. Open IOPMrootDomain service ‘s user client RootDomainUserClient.
d. Call user client IOHIDIXControllerUserClient ‘s selector 1 (getRequest64) . From the output , we can get a kernel heap address of object IOHDIXCommand whose size is 0x68. This is vulnerability #1.
e. Call IOHDIXHDDriveOutKernel service ‘s selector 2 (processReply64). It will release the object.
f. Call RootDomainUserClient user client ‘s selector 7 (kPMSleepSystemOptions) with a carefully prepared XML as parameter , which include ROP gadget in <data> part. The <data> part occurs multiply times in order to occupy the target space successfully. We tune the XML ‘s <data> ‘s size in order to create size 0x68 buffer which OSData field point to. After the call, our controlled buffer occupy the freed IOHDIXCommand object location. And the kernel address is known by user mode program.
g. Call IOHIDIXControllerUserClient user client selector 2 (processReply64) with argument which include the address (leaked by step d). The call will take the address as a IOHDIXCommand object, and call the address located at 0x50 offset. So we control the RIP and let it execute ROP gadget.
h. In the ROP gadget, we disable the SMAP and SMEP bits in CR4. Then executes the shell code to modify current process’ uid to root and fork a shell.