OS X NVRAM Restriction Bypassed

Begin with OS X 10.11 El Capitan, a set of security mechanism, System Integrity Protection(SIP), has been enforced and it can only be configured or turned off in the recovery environment like “Recovery HD”. In the “normal environment”, SIP configuration will not be permitted even with root privilege. If so, the SIP would be useless since it can be easily turned off.

As many people may already noticed, the configuration of SIP status is stored in the NVRAM with a property called “csr-active-config”. Of course users wouldn’t be allowed to modify or delete value of this certain property since the only official way to config SIP shall be the “csrutil” tool.

However, such restriction on certain NVRAM properties can be easily bypassed by patching the AppleEFINVRAM.kext.

The NVRAM restriction was in place since OS X 10.10 actually, the AppleEFINVRAM from 10.9.x doesn’t have such protection so that “csr-active-config” can be modified under these earlier OS X versions. On 10.10, restrictions can be bypassed by applying the following patches:
Tested on 10.10.5.
-> To bypass NVRAM property set restriction:

-> To bypass NVRAM property delete restriction:

For the 10.11, even SIP is configured to disabled using “csrutil” tool(csr-active-config=0x77), the restriction on csr-* properties would be still there. However, patches can also be done on 10.11:
Tested on 10.11 and 10.11.1 Beta.
-> To bypass NVRAM property set restriction:
This one also can be confirmed working in Pike’s post, just added some extra bytes to avoid incorrect patching on other kexts when using Clover KextPatch.

-> To bypass NVRAM property delete restriction:

These patches can also be applied using Clover KextPatch if on a Hack.
After patching AppleEFINVRAM, “csr-active-config” and other protected properties like “csr-data” can be modified and deleted directly using the “nvram” tool without the GUID: 7C436110-AB2A-4BBB-A880-FE41995C9F82. Besides, “csrutil” tool in 10.11 won’t complain about that operation must be in the Recovery environment when change the SIP configs since the NVRAM set restriction had been taken cared.

One last thing, these experiments are all for test purpose ONLY, do not use it on your working machine to avoid potential security issues. Just keep the SIP in place, as it should be.

Update 1:
The “nvram” tool should never allow to set these restricted properties like “csr-data” & “csr-active-config”, even with GUID(7C436110-AB2A-4BBB-A880-FE41995C9F82) present, at least such operation shall only be allowed in the Recovery environment, which with CSRBoot & CSRConfigMode flag set. ->This defect has been fixed in current 10.11 release.

Update 2:
Patch for 10.12:
-> To bypass NVRAM property set restriction:

-> To bypass NVRAM property delete restriction:

16 thoughts on “OS X NVRAM Restriction Bypassed

  1. Google Chrome 52.0.2743.116 Mac OS X  10.11.6

    For 10.11, I don’t think just nop 0000000000002979 -> jne?
    My idea:
    Search for 85c0 0f8540010000 and repiace it with 85c0 90e940010000 (Change to jmp )?
    FYI.

    1. Google Chrome 53.0.2785.113 Windows 10 x64 Edition

      Yeah sounds good. However we don’t really needs to patch AppleEFINVRAM anymore since Clover already supports CSR flag management before the OS boot up.

      1. Safari 10.0 iPhone iOS 10.0.1

        All right. But I don’t know what will happen after patching AppleEFINVRAM? I guessed that CSR flags can be set in any environment of OS X? Normal OS is included?
        Of course assuming Clover do nothing (i.e. Set CSRActiveConfig = 0xffff?)

        1. Safari 10.0 Mac OS X  10.12

          Yes it just bypass the check for modifying and deleting certain nvram variables, so the csr-active-config can be set even in normal environment. But since the reboot is still required, it would be much easier to just set it using updated Clover.

          1. Safari 10.0 iPhone iOS 10.0.1

            Yup. I think so. But previously I tried to patch AppleEFINVRAM binary file via Clover’s KextToPatch and of course successfully. But I ran csrutil disable and it still printed that need to be set under Recovery/Installer OS. Did it just print this and actually it was set correctly? However, at that time I was using Clover to set CSRActiveConfig = 0x13. So I don’t know if it worked…

        2. Google Chrome 53.0.2785.116 Windows 10 x64 Edition

          If the patch works then csrutil should not complain that, it would be same as use it in Recovery. May consider turn on debug mode in KextToPatch to see if it got patched correctly.

          1. Safari 10.0 iPhone iOS 10.0.1

            Maybe my brain got messed… Oops. Cannot remember that. Will be confirmed later on. (Maybe National Day of China)
            And I remembered that I tried this patch under Sierra in summer holiday, so I supposed this data may be changed.
            Will confirm later. Anyway.

          1. Google Chrome 53.0.2785.116 Mac OS X  10.12.0

            perl -pi -e ‘s|\x85\xC0\x0F\x85\x49\x01\x00\x00|\x85\xC0\xEB\x04\x90\x90\x90\x90|’ AppleEFINVRAM

            Nope. Your patch for bypassing NVRAM property set restriction is wrong. Here is the diff:

            — /Users/Vanilla/Desktop/org.txt 2016-09-24 17:55:00.000000000 +0800
            +++ /Users/Vanilla/Desktop/patched_v1.txt 2016-09-24 17:55:47.000000000 +0800
            @@ -1,4 +1,4 @@
            -org:
            +patched_v1:
            (__TEXT,__text) section
            __ZN20AppleEFINVRAMGlobalsC1Ev:
            0000000000001260 55 pushq %rbp
            @@ -2764,7 +2764,11 @@
            00000000000036ba 4c89e2 movq %r12, %rdx
            00000000000036bd e800000000 callq _mac_iokit_check_nvram_set
            00000000000036c2 85c0 testl %eax, %eax
            -00000000000036c4 0f8549010000 jne 0x3813
            +00000000000036c4 eb04 jmp 0x36ca
            +00000000000036c6 90 nop
            +00000000000036c7 90 nop
            +00000000000036c8 90 nop
            +00000000000036c9 90 nop
            00000000000036ca 4c89ef movq %r13, %rdi
            00000000000036cd 4c89e6 movq %r12, %rsi
            00000000000036d0 e889f7ffff callq __ZL19ConvertObjectToDataPK8OSSymbolP8OSObject ## ConvertObjectToData(OSSymbol const*, OSObject*)

            Try this one:
            perl -pi -e ‘s|\x85\xC0\x0F\x85\x49\x01\x00\x00|\x85\xC0\x90\xE9\x49\x01\x00\x00|’ AppleEFINVRAM

            And here is diff:
            — org.txt 2016-09-24 17:55:00.000000000 +0800
            +++ patched_v2.txt 2016-09-24 17:58:45.000000000 +0800
            @@ -1,4 +1,4 @@
            -org:
            +patched_v2:
            (__TEXT,__text) section
            __ZN20AppleEFINVRAMGlobalsC1Ev:
            0000000000001260 55 pushq %rbp
            @@ -2764,7 +2764,8 @@
            00000000000036ba 4c89e2 movq %r12, %rdx
            00000000000036bd e800000000 callq _mac_iokit_check_nvram_set
            00000000000036c2 85c0 testl %eax, %eax
            -00000000000036c4 0f8549010000 jne 0x3813
            +00000000000036c4 90 nop
            +00000000000036c5 e949010000 jmp 0x3813
            00000000000036ca 4c89ef movq %r13, %rdi
            00000000000036cd 4c89e6 movq %r12, %rsi
            00000000000036d0 e889f7ffff callq __ZL19ConvertObjectToDataPK8OSSymbolP8OSObject ## ConvertObjectToData(OSSymbol const*, OSObject*)

        3. Safari 10.0 Mac OS X  10.12

          0x3813 is close the function exit, jmp to it wouldn’t do the nvram-set. Actually jmp 0x36ca even isn’t necessary, just nop that jne would be fine.

          1. Chrome 53.0.2785.109 iPod iOS 9.3.3

            Oops. Sorry I see… But I’d like to know what is 0x3813 it’s a function to set nvram or just a restriction? If just a restriction and try to NOP it can be a easier way.

          2. Google Chrome 53.0.2785.116 Mac OS X  10.12.0

            — org.txt 2016-09-25 08:06:07.000000000 +0800
            +++ patched_nop.txt 2016-09-25 08:13:23.000000000 +0800
            @@ -2766,7 +2766,12 @@
            00000000000036ba 4c 89 e2 movq %r12, %rdx
            00000000000036bd e8 00 00 00 00 callq 0x36c2
            00000000000036c2 85 c0 testl %eax, %eax
            -00000000000036c4 0f 85 49 01 00 00 jne 0x3813
            +00000000000036c4 90 nop
            +00000000000036c5 90 nop
            +00000000000036c6 90 nop
            +00000000000036c7 90 nop
            +00000000000036c8 90 nop
            +00000000000036c9 90 nop
            00000000000036ca 4c 89 ef movq %r13, %rdi
            00000000000036cd 4c 89 e6 movq %r12, %rsi
            00000000000036d0 e8 89 f7 ff ff callq __ZL19ConvertObjectToDataPK8OSSymbolP8OSObject ## ConvertObjectToData(OSSymbol const*, OSObject*)
            @@ -3379,7 +3384,7 @@
            0000000000003fad 48 89 c6 movq %rax, %rsi
            0000000000003fb0 e8 00 00 00 00 callq 0x3fb5
            0000000000003fb5 85 c0 testl %eax, %eax
            -0000000000003fb7 74 0b je 0x3fc4
            +0000000000003fb7 65 90 nop
            0000000000003fb9 48 83 c4 08 addq $0x8, %rsp
            0000000000003fbd 5b popq %rbx
            0000000000003fbe 41 5e popq %r14

            OK. Tested. Above is ok as well. I also changed the second je to nop.

        4. Safari 10.0 Mac OS X  10.12

          I just noticed that you nop the je for the nvram-delete, that would go to the function exit and still block the delete operation. Try (# nvram -d csr-active-config || # csrutil clear) and see if it works.
          je -> jmp shall always force it do the delete operation in this case.

          1. Safari 10.0 iPhone iOS 10.0.1

            Yeah it works. I tried # csrutil clear and OK. I guessed the jne for setting and the je for deleting is just a check. Nothing more it does. So both of them can be nop or jmp. BTW, only search for 0f8549010000 and replace it with 90e949010000 is OK too. So just change the je/jne into jmp, or just replace them with nops. Both are OK. Anyway .

  2. Google Chrome 56.0.2924.76 Mac OS X  10.12.4

    Hi. Linus. Long time no see and happy Chinese New Year!
    I found the patch has been changed since 10.12.4 DP1 build 16E144f. And here are the details:

    — 10124_efinvram_org.txt 2017-01-28 18:38:17.000000000 +0800
    +++ 10124_efinvram_patched.txt 2017-01-28 18:36:58.000000000 +0800
    @@ -1,4 +1,4 @@
    -AppleEFINVRAM:
    +HackrEFINVRAM:
    (__TEXT,__text) section
    __ZN20AppleEFINVRAMGlobalsC1Ev:
    00000000000011d0 55 pushq %rbp
    @@ -2762,7 +2762,12 @@
    0000000000003633 4c 89 e2 movq %r12, %rdx
    0000000000003636 e8 00 00 00 00 callq 0x363b
    000000000000363b 85 c0 testl %eax, %eax
    -000000000000363d 0f 85 38 01 00 00 jne 0x377b // This jne entry has been changed.
    +000000000000363d 90 nop
    +000000000000363e 90 nop
    +000000000000363f 90 nop
    +0000000000003640 90 nop
    +0000000000003641 90 nop
    +0000000000003642 90 nop
    0000000000003643 4c 89 f7 movq %r14, %rdi
    0000000000003646 4c 89 e6 movq %r12, %rsi
    0000000000003649 e8 80 f7 ff ff callq __ZL19ConvertObjectToDataPK8OSSymbolP8OSObject ## ConvertObjectToData(OSSymbol const*, OSObject*)
    @@ -3414,7 +3419,7 @@
    0000000000003fab 48 89 c6 movq %rax, %rsi
    0000000000003fae e8 00 00 00 00 callq 0x3fb3
    0000000000003fb3 85 c0 testl %eax, %eax
    -0000000000003fb5 74 0b je 0x3fc2 // This will still work.
    +0000000000003fb5 eb 0b jmp 0x3fc2
    0000000000003fb7 48 83 c4 08 addq $0x8, %rsp
    0000000000003fbb 5b popq %rbx
    0000000000003fbc 41 5e popq %r14

    And thus the new patch is:
    perl -pi -e ‘s|\x85\xC0\x0F\x85\x38\x01\x00\x00|\x85\xC0\xEB\x04\x90\x90\x90\x90|’ AppleEFINVRAM
    # For deleting, not changed.
    Or just NOP out that jne if you like.

Leave a Reply

Your email address will not be published. Required fields are marked *