Upload
others
View
5
Download
0
Embed Size (px)
Citation preview
Fuzzing and Exploiting OSX Vulnerabilities for Fun and Profit
Complementary Active & Passive Fuzzing
What We Will Cover
• Who We Are
• Passive Fuzzing Framework
• Exploit to Root
Moony Li
- @Flyic - 7 years security - Sandcastle - Deep Discovery - Exploit Detection - Mac/Windows
Kernel - Android Vulnerability
Jack Tang
- @jacktang310 - 10+ years security - Browser - Document - Mac/Windows
Kernel - Virtualization
Vulnerability
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
CVE Credits
Github Access
h"ps://github.com/SilverMoonSecurity
What We Will Cover
• Comparing Approaches
• Our Approach/Consideration
• Implementation
• Best Practice
Methods Disadvantage Notes
Tradi1onalFuzzChoicetheIOKitservicenametheywanttotest.PourfuzzingdataintotheIOKitusermodeAPI(e.g.IOConnectCallMethod)
Callsequencedependency AppleCamIn(OpenDevice,PowerOnCamera…)
Inputdatadependency AppleHDAEngineInput(inputasusermodebufferpointer)
Timingdependency IOHDIXHDDriveOutKernel(mountdmg)
CodeReview
Un-scalable DependonHumanexperience�
CosteffortforReverseEngineering
somanyIOKitservicesanduserclient.�
Comparing Other Approaches
Our Approach|Consideration Interception & Poison
Are they similarJ
Comparison RiverDam PassiveFuzz
BasicFuncHon �
Streamintercept ExecuNonintercept
UpStream Usermodedata
DownStream Kernelmodedata
CreateChaos
Poisoningupstream Fuzzinguserdata
Downstreamfishdie Kernelcrash
Trackthepoison’sorigin Reproduce
…… ……
Just Like This …
Origianl function
Hooker
IOAcceleratorFamily2.kext
Targeted application from apple storeSuspicious module/function
manifest
IOThunderboltFamily.kext IOUSBFamily.kext
AppleGraphicsPowerManagement.kext AppleHDA.kext … …
I. is_io_connect_methodII. is_io_connect_async_methodIII. iokit_user_client_trapIV. IOMemoryDescriptor::createMappingInTaskV. ipc_kmsg_getVI. ipc_kmsg_sendVII. Copyio…...
Conditon Checker
Ring3
Ring0
Target drivers
XNU/IOKit
Tamper
StackFrame,Process,UserClient,MsgID,…...
Context Matcher
Implementation – Architecture Overview
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;
Implementation – Pseudo Code
• Hooker
• Directly accessible by user
• One hook for many processes
• Inline hook in kernel mode.
• Tamper
• Only fuzz buffer content accessible by user
• e.g. Inband_input, scalar_input, ool_input
• NOT size! (bypass getTargetAndMethodForIndex check)
Implementation – Hook & Tamper
…
0xffffff80c0c7b720 0xffffff7fa96ec9f2 AppleIntelHD3000Graphics`Gen6GLContext::bind_texture(VendorGLStreamInfo&, unsigned int, unsigned int, bool, Gen575TextureBuffer**) + 0x12e
0xffffff80c0c7b7c0 0xffffff7fa96f2bd5 AppleIntelHD3000Graphics`Gen6GLContext::process_token_BindTextures(VendorGLStreamInfo&) + 0x103
0xffffff80c0c7b7f0 0xffffff7fa96b6242 AppleIntelHD3000Graphics`IOIntelGLContext::processCommandBuffer(VendorCommandDescriptor*) + 0x12c
0xffffff80c0c7b820 0xffffff7fa96ec1eb AppleIntelHD3000Graphics`Gen6GLContext::processCommandBuffer(VendorCommandDescriptor*) + 0x7b
0xffffff80c0c7b900 0xffffff7fa96b540a AppleIntelHD3000Graphics`IOIntelGLContext::clientMemoryForType(unsigned int, unsigned int*, IOMemoryDescriptor**) + 0x5bc
0xffffff80c0c7b950 0xffffff7fa96b39c3 AppleIntelHD3000Graphics`IOIntelGLContext::submit_command_buffer(unsigned int, sIOGLGetCommandBuffer*) + 0x63
0xffffff80c0c7b980 0xffffff80276b9626 ::shim_io_connect_method_scalarI_structureO(IOExternalMethod *, IOService *, const io_user_scalar_t *, mach_msg_type_number_t, char *, IOByteCount *)((IOExternalMethod *) method = <>, , (IOService *) object = <>, , (const io_user_scalar_t *) input = <>, , (mach_msg_type_number_t) inputCount = <>, , (char *) output = <register r10 is not available>, , (IOByteCount *) outputCount = <register r11 is not available>, )
0xffffff80c0c7b9e0 0xffffff80276baef0 IOUserClient::externalMethod(unsigned int, IOExternalMethodArguments*, IOExternalMethodDispatch*, OSObject*, void*)((IOUserClient *) this = <>, , (uint32_t) selector = <>, , (IOExternalMethodArguments *) args = 0xffffff80c0c7ba00, (IOExternalMethodDispatch *) dispatch = <>, , (OSObject *) target = <>, , (void *) reference = <>, )
0xffffff80c0c7bb20 0xffffff80276b7f77 ::is_io_connect_method(io_connect_t, uint32_t, io_user_scalar_t *, mach_msg_type_number_t, char *, mach_msg_type_number_t, mach_vm_address_t, mach_vm_size_t, char *, mach_msg_type_number_t *, io_user_scalar_t *, mach_msg_type_number_t *, mach_vm_address_t, mach_vm_size_t *)((io_connect_t) connection = 0xffffff80c0c7ba60, (uint32_t) selector = 16, (io_user_scalar_t *) scalar_input = <>, , (mach_msg_type_number_t) scalar_inputCnt = <>, , (char *) inband_input = <>, , (mach_msg_type_number_t) inband_inputCnt = 0, (mach_vm_address_t) ool_input = <>, , (mach_vm_size_t) ool_input_size = <no location, value may have been optimized out>, , (char *) inband_output = <no location, value may have been optimized out>, , (mach_msg_type_number_t *) inband_outputCnt = <no location, value may have been optimized out>, , (io_user_scalar_t *) scalar_output = <>, , (mach_msg_type_number_t *) scalar_outputCnt = <no location, value may have been optimized out>, , (mach_vm_address_t) ool_output = <>, , (mach_vm_size_t *) ool_output_size = <>, )
0xffffff80c0c7bcd0 0xffffff7fa9cd34ab trampline_is_io_connect_method((io_connect_t) connection = 0xffffff8035637000, (uint32_t) selector = 16, (io_user_scalar_t *) scalar_input = 0xffffff80331a4dcc, (mach_msg_type_number_t) scalar_inputCnt = 1, (char *) inband_input = 0xffffff80331a4dd8 "", (mach_msg_type_number_t) inband_inputCnt = 0, (mach_vm_address_t) ool_input = 0, (mach_vm_size_t) ool_input_size = 0, (char *) inband_output = 0xffffff8035805600 "", (mach_msg_type_number_t *) inband_outputCnt = 0xffffff80358055fc, (io_user_scalar_t *) scalar_output = 0xffffff80c0c7bd30, (mach_msg_type_number_t *) scalar_outputCnt = 0xffffff80c0c7bd2c, (mach_vm_address_t) ool_output = 0, (mach_vm_size_t *) ool_output_size = 0xffffff80331a4df8)
0xffffff80c0c7bde0 0xffffff8027158750 _Xio_connect_method((mach_msg_header_t *) InHeadP = <>, , (mach_msg_header_t *) OutHeadP = 0xffffff80358055d0)
0xffffff80c0c7be10 0xffffff8027083443 ipc_kobject_server((ipc_kmsg_t) request = 0xffffff80331a4d40)
0xffffff80c0c7be50 0xffffff802705ef03 ipc_kmsg_send((ipc_kmsg_t) kmsg = <>, , (mach_msg_option_t) option = <>, , (mach_msg_timeout_t)
Implementation – Hook & Tamper (Snippet – Unreported Crash)
• (Driver interface)is_io_connect_method• (Driver
interface)is_io_connect_async_method• (Kernel)iokit_user_client_trap• (Kernel)IOMemoryDescriptor::createMappingInTas
k
• (Mach Msg)ipc_kmsg_get• (Mach Msg)ipc_kmsg_send• (General IO)Copyio • …
Implementation – Hook Summary
Implementation – Hook Summary Sinnpet
Keep fuzzing stable • Get rid of noise
o busy call, black screen call, hung call,
o reproduced crashes
Hunt according to vulnerability context • Kernel heap address leak
• Map user data into kernel and read as buffer size
• …
Implementation – Why Condition Checker?
• &&, ||, *(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
Implementation – Dimension of Condition 1/3
//Config for mac prodetail_control_entry_t g_white_listing_detail_control[] ={ // procName,uid,driverBundleName, driverClassName, selFunctionNO //"*",0,"*","*",ANY_MATCH_INTEGER,#if 0 //Reported or collected yet: //{"*",PROCESS_UID_ANY_INTEGER,"*","AGPMClient",7312}, //{"*",PROCESS_UID_ANY_INTEGER,"*", "nvDeviceTesla", 5}, //{"*",PROCESS_UID_ANY_INTEGER,"*", "NV2DContextTesla", 17}, //{"*",PROCESS_UID_ANY_INTEGER,"*","IONVSurfaceTesla",10}, //{"*",PROCESS_UID_ANY_INTEGER,"*","IOHDIXHDDriveOutKernelUserClient",2}, {"*",PROCESS_UID_ANY_INTEGER,"*","IGAccelSharedUserClient",1},//crash-24 {"*",PROCESS_UID_ANY_INTEGER,"*","AccelSurface",16},//crash-23 {"*",PROCESS_UID_ANY_INTEGER,"*",OBJECT_CLASS_NAME_NO_FOUND,16}, {"*",PROCESS_UID_ANY_INTEGER,"*","HD",2},//crash-21 //"*",PROCESS_UID_ANY_INTEGER,"*","Accel",2,//crash-28 //"*",PROCESS_UID_ANY_INTEGER,"*","IG",2,//crash-28 //"*",PROCESS_UID_ANY_INTEGER,"*","Con",2,//crash-28 "*",PROCESS_UID_ANY_INTEGER,"*","IGAccelSharedUserClient",0,//crash-29 "*",PROCESS_UID_ANY_INTEGER,"*","IOThunderboltFamilyUserClient",22,//crash-30 //"*",PROCESS_UID_ANY_INTEGER,"*","IG",ANY_MATCH_INTEGER, //"*",PROCESS_UID_ANY_INTEGER,"*","Accel",ANY_MATCH_INTEGER, //"vm",PROCESS_UID_ANY_INTEGER,"*","*",ANY_MATCH_INTEGER, //"*",PROCESS_UID_ANY_INTEGER,"*","vm",ANY_MATCH_INTEGER, "sandbox",PROCESS_UID_ANY_INTEGER,"*","*",ANY_MATCH_INTEGER, "dog",PROCESS_UID_ANY_INTEGER,"*","*",ANY_MATCH_INTEGER, //{"WindowServer",PROCESS_UID_ANY_INTEGER,"*","AccelSurface",16},//crash-23 //"*",PROCESS_UID_ANY_INTEGER,"*","SMC",ANY_MATCH_INTEGER, //"windowserver",PROCESS_UID_ANY_INTEGER,"*","*",ANY_MATCH_INTEGER,};
Implementation – White Listing Sample
• 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[,]
Implementation – Dimension of Condition 2/3
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},
}
Implementation – Stack Frame Sample
Dimension of condition 3/3
• Misc • Mach_msg
• msg subsystem id…
• Userclient • serviceName,ClassName,selector…
detail_control_entry_t g_white_listing_detail_control[] ={
// procName,uid,driverBundleName, driverClassName, selFunctionNO
//{"*",PROCESS_UID_ANY_INTEGER,"*","AGPMClient",7312},,
{"*",PROCESS_UID_ANY_INTEGER,"*","IGAccelSharedUserClient",1},//crash-24
{"*",PROCESS_UID_ANY_INTEGER,"*","AccelSurface",16},//crash-23
{"*",PROCESS_UID_ANY_INTEGER,"*",OBJECT_CLASS_NAME_NO_FOUND,16},
{"*",PROCESS_UID_ANY_INTEGER,"*","HD",2},//crash-21
{"*",PROCESS_UID_ANY_INTEGER,"*","IX",2},//crash-21
"*",PROCESS_UID_ANY_INTEGER,"*","AGPM",7312,//crash-11
"*",PROCESS_UID_ANY_INTEGER,"*","IGAccelGLContext",2,//crash-28
Implementation – UserClient Sample
#define KMSG_IOKIT_SUBSYSTEM_RANGE 0xAF0, 0x0B47
detail_control_entry_for_ipc_kmsg_send_t g_black_listing_detail_control_foripc_kmsg_send[]
={
//procName,uid,msg_id_from, msg_id_to, routineName, addr, addr_offset_from, addr_offset_to
"chrome",PROCESS_UID_ANY_INTEGER,
KMSG_IOKIT_SUBSYSTEM_RANGE,"__Xio_connect_method",KMSG_ADDR_OFFSET_ANY_RANGE,
KMSG_LEAVING,};
• #define KMSG_IOKIT_SUBSYSTEM_RANGE 0xAF0, 0x0B47
• #define KMSG_MACH_VM_SUBSYSTEM_RANGE 0x12C0, 0x12D4
• #define KMSG_MACH_PORT_SUBSYSTEM_RANGE 0xC80, 0x0CA4
• #define KMSG_MACH_HOST_SUBSYSTEM_RANGE 0xC8, 0xE4
• #define KMSG_HOST_PRIV_SUBSYSTEM_RANGE 0x190, 0x1AA
• ……
Implementation – Mach-msg Sample
• 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
Implementation – What Is Context?
• Some IOKit related memory corruption vulnerabilities may 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 may happen in the following context:• The output buffer’s content has 0xFFFFFF prefix.
Implementation – Context Sample
• Fuzzing Source:
• Multiple applications
• 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…)
Best Practice – For Passive 1/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?
Best Practice – For Passive 2/3
Miscellaneous Tips
• Occasional fuzz activities recommended
• Normal program running – sudden fuzz
• Keep OS version updated with latest KDK
Best Practice – For Passive 3/3
Best Practice – How to complementary passive fuzzing?
Best Practice – For Active Fuzz 1/4
Active Fuzz Passive Fuzz
Researcher
[1]Provide more IOKit call
[2]Suspicious moudle/function manifest
[3]Context Pattern
[2]Suspicious moudle/function manifest
Code Reviewer
• Statistical data from passive fuzz
• Accessible user client, non-root, non-sandbox,
crash frequencies, crash types(UAF, OOB)…
• Contact API in lower level to bypass
unnecessary checks (if possible)
• Resolve Mac-O format, find symbol, hard-code offset
• e.g. IOServiceGetMatchingServices(mach_port_t, CFDictionaryRef, io_iterator_t
*)
->io_service_get_matching_services_bin(mach_port_t, char*,int, void*)
Best Practice – For Active 1/4
• Reproduce:
• No need to record your random call/random
parameter - just record your pseudorandom
number seed (E.g. Mt19937-64/Mt19937-32)
• The kernel crash is easily reproduced, no matter
how randomly you call API and fuzz parameters
Best Practice – For Active 2/4
seed = CrahsedCases[i]
for(randomSelect every kernel module)
for(randomSelect every interface)
APICall( randomByte() )
Best Practice – For Active 2/4 Pseudo code for reproduce
for (every fuzz session)
seed = generate()
sendSeedOutside()
for(randomSelect every kernel module)
for(randomSelect every interface)
APICall( randomByte() )
Best Practice – For Active 3/4 Pseudo code for active fuzzing
• Reproduce:
• Web seed server for multiple connections
• One pseudorandom seed for a relatively short
fuzz cycle
Best Practice – For Active 4/4
What We Will Cover
• Security Mitigation
§ Exploit Methods
• Exploit Practice
• SIP (System Integrity Protection)
• KALSR(e.g. PEGASUS CVE-2016-4655)
• SMAP
• SMEP
https://speakerdeck.com/marcograss/dont-trust-your-eye-apple-
graphics-is-compromised
Security Mitigation
• Bypass KASLR – Using vulnerability to leak kernel code segment
address in run time – Build up payload with leaked API (e.g. thread_exception_return)
• Bypass SMAP – Using vulnerability to leak kernel heap address – Build up ROP chain in kernel heap – Kernel heap address would be needed
• Bypass SMEP – Using vulnerability to execute RIP in kernel – Execute ROP chain to disable SMEP/SMAP – Payload execution
Exploit Methods
• The OSX/iOS hacking guru Stefan Esser (@i0n1c) propose OSUnserializeXML is a good way in SyScan 2012
h"ps://reverse.put.as/wp-content/uploads/2011/06/SyScan2012_StefanEsser_iOS_Kernel_Heap_Armageddon.pdf
Tips of Heap FengShui OSUnerializeXML()
• In most cases, the OSDictionary allocated by OSUnserializeXML will be freed by OSObject::release in one system call
。。。
However…
• 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…
• In IOKIT service IOMProotDomain , slector 7 (kPMSleepSystemOptions)
RootDomainUserClient::secureSleepSystemOptions
。。。
Always an exceptionJ
We Exploit apple to root by bugs found and Heap Fengshui tips
• CVE-2016-xxx : This is typical UAF vulnerability in AppleHDAEngineInput kernel module. • CVE-2016-xxxx:
Another bug in the Disk image module can leak an object address. The address exists in kernel heap.
Bugs
payload
Ring3
Ring0
kernelSMAPSMEP
KASLR
kslide
Driver
Memory address – Disk Address
Call current_procCall proc_ucredCall posix_cred_getCall thread_exception_return
IOCommand
Exploit App
ROP Gadgets
mov cr4 rax; ret
Call payload
StackPivot0x68
Object0x108
AppleHDAEngineInput
IOHDIXHDDriveOutKernel
vtable_addr +0+8
call [vtable+0]
[1]Leak kernel buffer IOCommand address
[3]Spray freed IOCommand with OSData(StackPivot) [2]Free IOCommand
[4]Free Object[5]Spray freed Object with OSData(leaked IOCommand and
ROP)
[0]Leak kslide to build up payload
[6]Trigger execution by use Object
Exploit Process 1/2
IOCommandStackPivot
Object
Exploit Apppayload
+0+8
Exploit Process 2/2
Demo
Thanks very much
Special thanks :
Herry Li, @zenhumany
Juwei Lin, @fuzzerDOTcn