known as KeenTeam) • Marco (@marcograss): • My main focus is iOS/Android/macOS and sandboxes. But recently shifted to hypervisors, basebands, firmwares etc. • pwn2own 2016 Mac OS X Team • Mobile pwn2own 2016 iOS team • pwn2own 2017 VMWare escape team • Mobile pwn2own 2017 iOS Wifi + baseband team • Liang (@chenliang0817): • Lead Pwn2Own team in KeenLab (Co-founder of KeenTeam/KeenLab) • Browser exploiting, iOS/MacOS sandbox bypassing and privilege escalation • Winner of Mobile Pwn2Own 2013 iOS category • Winner of Pwn2Own 2014 OSX category
• White Hat Security Researchers • Several times pwn2own winners • We are based in Shanghai, China • Our blog is https://keenlab.tencent.com/en/ • Twitter @keen_lab
to strengthen PAC • Isolate different types of pointers used with the same key • Avoid pointer replacement attack (If all pointers use 0 context) • Key • 4 keys (combination of instruction/data and A/B keys), plus a G key (general key) for data hash purpose • Stored in system registry, inaccessible at userland • Keys are per process and per exception level (or weakness is introduced) • Algorithm • QARMA
Examples Comment PAC* PACIAZ, PACDB, etc… Generate PAC using specific key + context AUT* AUTIAZ, AUTDB, etc… Authenticate PAC using specific key + context Combined RETAA, BRAA, LDRAA… Authenticate PAC first, and do the original instruction
if the authentication fails? • Place an error code on specific bits of the address, making address invalid (53rd and 54th bit for EL0 address) • Process crash? Or not? Raw pointer PAC* instruction PACed pointer PACed pointer AUT* instruction Crash/Exit Continue exec Pass Fail
pointers? • Of course not! Too expensive • Most important and sensitive content should be protected • Function pointers: using instruction keys • Important data pointers: using data keys • Important contents: using G key • Can be used to implement CFI
Keys are inaccessible in userland • Keys can not obtained by kernel R/W in EL1 • Algorithms might be public and know • So with arbitrary R/W, cannot compute PAC • To obtain arbitrary code execution you must compute PAC of function pointer first • To compute PAC of function pointer you must obtain arbitrary code execution • Chicken-egg problem!
key in any situation • B key is per-process initialized at process creation time, IB is enabled by default • In task_create_internal • Switched during context switch
key are enabled by default for platform binary • Such as Webcontent • But disabled for our own App, why? • According to ARMv8.3 document, system register SCTLR_EL1 responsible for key status control • EnIA, EnIB, EnDA, EnDB
• B key is per-process • A key is the same for all processes • Non-arm64e apps have A key and DB key disabled, IB key and G key enabled • Questions? • A key and G key are constant value, same pointer same PAC upon each reboot? • That will cause big issue for sure • A key and G key are same for both EL0 and EL1, can use userland App to compute kernel pointer PAC? • Seems crazy idea
a cookie value between return address and local variable data • Cookie value is unique in the same process • Attackers can obtain the value via arbitrary memory read, defeating the stack protection • With PAC, the return address is authenticated(Using B key) with SP as context • The value is unique per pointer + stack frame • And, B key is per-process
more • Indirect function pointers are authenticated • C++ vptr is authenticated via data A key • Functions in vtable are authenticated via instruction A key plus specific context (entry location + a static value) • GOT function pointers are authenticated via A key plus their address(ASLR) as context
PAC • But the method function pointer is IB key protected • B key is per-process • But before reaching object-c selector cache, there is chance to reach A key call • E.g __xpc_file_transfer_dispose, pointed out by Ian Beer
register change • Previous state needs to be stored and restored frequently • Hackers can change those states to control the execution flow • LR PC and CPSR are the most critical registers • iOS uses G key to compute the hash of those critical registers, and ensure the values are not modified before restore • Validate the hash during restore, panic the system if validation failed
arbitrary memory read/write as prerequisite • With PAC, achieving arbitrary memory read/write becomes harder • Especially vptr object involved UAF • Heap-overflow, or non vptr UAF are still likely to achieve R/W • Final goal of exploitation is to achieve arbitrary code execution • Sadly • This is what PAC aims to prevent • R/W -> code execution becomes super hard
Even B key can be read via R/W, other keys are constant value • Any ways to compute PAC without calling CPU PAC instruction? • QARMA https://github.com/dkales/qarma64- python/blob/master/qarma.py • Result: fail • Apple might redesign/tweak the algorithm , and never publish
PAC same? • Constant key, on each reboot, same address same PAC? • Result: all different. Why? • Guess: some customization / randomization set to the CPU during iBoot phase • And, Apple’s design cannot be that weak.
user-friendly when crashing • Some function pointers use context as 0 • Can replace between each other • Neither of the above is very practical or enough to achieve code execution
processes • App can compute PAC for other processes • Case of userland privilege escalation or sandbox bypass • A great example was posted by Ian Beer recently: • https://googleprojectzero.blogspot.com/2019/04/splitting-atoms-in-xnu.html
x0, x1; ret”: • Without arbitrary code execution, just by calling API + R/W • And of course, obvious signing gadgets do not exist in iOS • But how about indirect signing gadgets?
in sysctl_unregister_oid, a converted 0-context pointer is stored and can be read out • X10 can be controlled • But AUTIA will fail as we cannot get PACed function pointer with specific context
AUT*, a fixed error bit will be appended to the pointer • So we can always get the correct PACIZAed value of any function pointer • Which means we can control the PC • But how about code execution, ROP? Or JOP? • ROP is hard to achieve, as return address is PACed by B key. JOP should also be hard, but thanks to Apple’s obfuscated kernel extension, quite some non-PAC indirect branching instruction
prevent R/W -> code execution • But, why we need code execution? • In previous jailbreaks, only rootfs rw remount needs code execution • With R/W, you can do almost everything. • So, Apple must make sure critical operations cannot be achieved by pure R/W • Then, APRR(possibly Apple Page Read-only Region) is introduced Post jailbreak steps(in the past) Can be achieved by data-only attack Disable Sandbox Yes Disable code signing(Critical) Yes Rootfs rw remount(since iOS 11.3) Practically no(In theory yes) Install system app(e.g Cydia) Yes but needs rootfs rw remount as prerequisite
is introduced • A memory range in kernel is marked as rx and the only rx memory in kernel • Everything else can be read-write • Some critical memory region should be modified frequently after iOS boot, which should have been protected also • APRR was introduced • Protect critical operations such as: AMFI trust cache management, pmap management
Function pointers in “__PPLTEXT:__text” segment • __PPLTEXT:__text is not executable by default • And special system register: “#4, c15, c2, #1” • “__PPLTEXT:__text” can be executed if the system register is set to 0x44554455646667 • Only ppl_enter will set the register • APRR protected memory is only modified in __PPLTEXT:__text code
as APRR protected pages • By setting flags in APRR attribute table • And specify some bits in page table TTE • Page table and APRR attribute table are APRR protected also • It means, to modify APRR protected memory, only three ways: • By modifying APRR attribute table and change page table TTE (both protected by APRR) • By setting system register “#4, c15, c2, #1” to 0x44554455646667, but you need to get code execution first, and also no good gadget to set this register, because of PAC • By executing code in __PPLTEXT:__text , but need to set system register first…
exploitation harder • Makes kernel RW -> code execution super hard • But in previous jailbreak, code execution is useless, data-only attack is enough • APRR provides better memory protection • KTRR can only protect kernel text and const area, cannot change after iommu is initialized • APRR can protect memory on demand after iommu initialization, at hardware level • Apple moves critical memory into APRR protected area • E.g AMFI trust cache, pmap, cs_valid feature etc. • And it is certain that Apple will move more stuff into APRR protect area • Future jailbreak needs code execution • PAC + APRR = effective mitigation!
is getting more and more mitigations and security scrutiny. • Recently, PAC, and more and more auditing. • There are several other paths of least resistance. • The Baseband is one of them • Can become a 0 clicks entry point •Complexity is an enemy of the vendor, but a friend of the attacker. • Basebands are VERY complex.
baseband basics for time constraints, you can find them in other talks, most notably: • Amat Cama, A walk With Shannon • Comsecuris, Breaking Band • Keen Lab, Exploitation of a Modern Smartphone Baseband • Charles Nitay Anna, The Baseband Basics • Guy – From Zero to Infinity • Comsecuris - There's Life in the Old Dog Yet (blogpost on iphone intel baseband) • The iPhone XR has the Intel (x-gold) XMM7560 model
station software stack to trigger the exploit OpenBSC OpenBTS srsLTE … Software defined Radio, or equivalent hardware USRP BladeRF CMU200 (Testing hardware) Over the air exploit RCE inside the phone baseband
choice, for example iPhone XR • Shameless plug, save time by grabbing https://github.com/marcograss/partialzip • You can download single files from inside the huge ipsw, saving time/bandwidth • Use “list” command to find the baseband firmware, for example “Firmware/ICE18-1.03.08.Release.bbfw” • Use the download command to get just that file (~40mb instead of 3- 4gb) • You are welcome.
• Extract and it’s composed of several ELFs • SYS_SW.elf is where the main os/stack is located • It says ELF for ARM… but it’s Intel.. (from iPhone XS and XR, before it was ARM) • Patch the elf header to make it Intel arch (010 Editor with the ELF template is a good choice), load into IDA Pro
version of the firmware because IDA Pro handles it better • It has several disadvantages compared to the x86 ones, • It’s the older baseband model • Lack of some network support such as CDMA • Baseband reversing is not straightforward… You can check the talk “Breaking Band” by Comsecuris, it’s basically a continuous wash and rinse, until you have a usable IDB • More challenging on Intel IMO since less strings than Samsung Shannon
to do is to find alloc / free variants, and Rtos APIs • Not too hard to find • You can then find init functions of the tasks. And the handler functions of the threads • Hint: UtaOsThreadCreate
threads that handle the juicy radio stuff where you want to find the RCEs. • Stuff like GMM, GRR, mobility management, EMM etc are there. • You need a good knowledge of the specs to choose what to go after..
for some messages, dequeue them and then handle them (including the radio messages) • Lot of messages are intra tasks, not all are relevant for over the air content
to https://developer.apple.com/bug-reporting/profiles-and-logs/ • Download and install the “Baseband.mobileconfig” profile for iOS • Reboot the device • You can trigger also a sysdiagnose by holding both volume and the top button • Get some (very) basics information on baseband crash. (task, address of abort, …)
Baseband where you have code exec PCI-E UserClient etc. You have several places where you can trigger a second bug on the Application Processor from the baseband Kernel CommCenter Others (Keep in mind that at this point you will still have to face PAC, since we will go on the Application Processor) Application Processor
Relevant IOKIT classes and components that we can gather from ioreg: • Connected over pci-e (baseband-pcie) is a IOPCIDevice • Has 2 IODeviceMemory, one of 0x1000 and one of 0x100 • AppleBasebandPCI • Baseband (IOPlatformDevice) • Has a interesting “function-coredump” • AppleBasebandD101 • AppleBasebandPCIICEControl • AppleBasebandPCIRTIDevice • AppleBasebandPCIRTIInterface • AppleBasebandPCIPDPADAMSkywalk • Others… Not enough space… But you can see there is a lot of «meat»
binary, 24mb plus libraries • Runs as “_wireless” user • It has a couple of “helpers” CommCenterMobileHelper, CommCenterRootHelper • “CommCenter is a 30 mb binary, even with PAC I bet you can find the right primitives” - qwerty
often requires a jailbreak on the latest version… • You can do some of the research on older models, or wait in 2019 for Intel to push some new Android models with the new XMM • Asus Zenfone 2 (Android,old as fuck) • Some Sierra Wireless Modules
mainstream basebands, making the bar for RCE higher, and this could be in theory implemented right now • Intel CET or ARM64 PAC in the future when new SoC come out? • True opt out option for unauthenticated networks for the paranoid users? They cannot just remove the unauthenticated networks since they are still widespread worldwide. But it will reduce the attack surface.