Popular Post vit9696 Posted January 7, 2018 Popular Post Share Posted January 7, 2018 I thought it was worth making a separate thread for our AptioFix discussions.Some links to relevant posts (suggest us gather stuff here):1. Information about APTIO V nvram bugs2. Z97 NvramSmi code & boot.efi memory move code3. KASLR slide calculation & usage 4. Slide calculation formula 5. Debug printing mess in boot.efi 21 Link to comment Share on other sites More sharing options...
vit9696 Posted January 8, 2018 Author Share Posted January 8, 2018 Here comes an explanation of when KASLR is used, and how it is determined by the recent boot.efi. First of all, here are the key combinations, most of which everybody knows about, but some are probably less well-known: Cmd + V — verbose (-v) Cmd + S — single mode (-s) Cmd + S + Minus — kaslr off (if CSR_ALLOW_UNRESTRICTED_NVRAM, otherwise single mode) Cmd + X — boot mode x (I guess even authors of macosxbootloader are unaware of it) Cmd + R — recovery boot Cmd + C + Minus — disable board compatibility check (-no_compat_check) Cmd + K — use prelinkedkernel.development instead of prelinkedkernel (kcsuffix=development) Shift — safe mode & kaslr off (-x) In addition to a dedicated key combination, that is responsible for disabling KASLR, there are three more places to disable KASLR.1. Cmd + S + Minus (only if CSR_ALLOW_UNRESTRICTED_NVRAM is set) 2. Shift (key combination for safe mode) 3. -x (boot argument for safe mode) 4. If prelinkedkernel header has 'comp' magic and its version is 0 (this thing) Additionally to that I have to admit that slide=X boot argument takes no effect when CSR_ALLOW_UNRESTRICTED_NVRAM is no set. For how KASLR address calculation works itself it is better to show the reverse-engineered code, because the exact offset calculation depends on CPU family and model. void ParseBootArgs(…) { ... if ( (BootMode & 0x4001) == 0x4001 ) // BOOT_MODE_SAFE | BOOT_MODE_ASLR (-x) { DisableKaslr = 1; GlobalVariableState = BootMode & ~0x4000ui64;// & ~BOOT_MODE_ASLR goto KASLR_DONE; } if ( !DisableKaslr && !ReadBootArgument(*kernelCommandLine, "slide", &value, &valueLength)// == EFI_SUCCESS && CsrAllowUnrestrictedNvram() ) { if ( !valueLength ) // slide= { GenerateRandomSlideNumber(); // Also called very early at boot.efi start SLIDE_SET: BYTE1(GlobalVariableState) |= 0x40u; // |= BOOT_MODE_ASLR goto KASLR_DONE; } SuppliedSlide = StringToInteger(value); if ( SuppliedSlide ) { if ( SuppliedSlide - 1 > 0xFE ) // SuppliedSlide >= 0x00 && SuppliedSlide <= 0xFF goto KASLR_DONE; gKernelSlide = (unsigned int)CalculateSlideAddress(SuppliedSlide); goto SLIDE_SET; } BYTE1(GlobalVariableState) &= 0xBFu; // &= ~BOOT_MODE_ASLR } KASLR_DONE: ... } UINT32 __cdecl CsrAllowUnrestrictedNvram() { UINTN Size; // [rsp+28h] [rbp-8h] Size = 0i64; if ( !(HasCsrActiveConfig & 1) ) { Size = 4i64; if ( (gRT->GetVariable((CHAR16 *)L"csr-active-config", &gAppleNvramVariableGuid, 0i64, &Size, &CsrActiveConfig) & 0x8000000000000000ui64) == 0i64 ) HasCsrActiveConfig = 1; } return CsrActiveConfig & 0x40; } void __cdecl GenerateRandomSlideNumber() { int RDRANDSupported; // esi UINT64 Slide; // rax UINT16 RDTSC; // ax _RAX = 1i64; __asm { cpuid } RDRANDSupported = _RCX & 0x40000000; do { if ( RDRANDSupported ) { Slide = RDRandRandomValue(0); if ( Slide ) break; } RDTSC = RDTSCCurrentValue(); Slide = (unsigned __int8)(RDTSC ^ HIBYTE(RDTSC)); } while ( !Slide ); gKernelSlide = (unsigned int)CalculateSlideAddress(Slide); } UINT64 __fastcall CalculateSlideAddress(UINT8 Slide) { UINT32 SlideInt; // er8 UINT64 RealSlideAddress; // rax unsigned int CpuFamily; // edx int CpuModel; // er9 UINT32 SlideAddress; // er8 SlideInt = Slide; if ( (Slide & 0x80u) == 0 ) return (unsigned int)Slide << 21; _RAX = 1i64; __asm { cpuid } CpuFamily = ((unsigned int)_RAX >> 8) & 0xF; if ( CpuFamily == 0xF ) CpuFamily = (unsigned __int8)((unsigned int)_RAX >> 20) + 15;// Use ExtendedFamily CpuModel = (unsigned __int8)_RAX >> 4; if ( CpuFamily == 15 || CpuFamily == 6 ) CpuModel |= ((unsigned int)_RAX >> 12) & 0xF0;// Use ExtendedModel SlideAddress = SlideInt << 21; RealSlideAddress = SlideAddress + 0x10200000; if ( (CpuModel | 0x10) != 0x3A ) // For CPUs which model is not 0x3A RealSlideAddress = SlideAddress; if ( CpuFamily != 6 ) // For CPUs which family is not 6 RealSlideAddress = SlideAddress; return RealSlideAddress; } The above makes me rather worried what should the approach be regarding slide=X usage for 2 cases: 1. Safe mode compatibility 2. System Integrity Protection compatibility (nvram restriction) To fix issue #2 it is enough to override gBS->GetVariable function that will report csr-active-config to exist and have CSR_ALLOW_UNRESTRICTED_NVRAM bit set. This makes good sense to me, because the kernel will still have protected nvram and this SIP restrictions, but boot.efi allows us to set custom KASLR. To fix #1 I would suggest to use a boot.efi patch, that will enable ASLR back. 01 40 00 00 is a reasonably rarely used constant (only 4 entries in the current boot.efi, two of which we need), and it has not changed since macosxbootloader. For this reason I consider a lookup of two 01 40 00 00 byte sequences being near each other (since the registers may change) to be quite a future-proof solution (although not pretty of course). Just patch them with FF FF FF FF and you will have KASLR in -x mode. 12 Link to comment Share on other sites More sharing options...
apianti Posted January 8, 2018 Share Posted January 8, 2018 I have some questions about that code..... I know............... But still... if ( (Slide & 0x80u) == 0 ) return (unsigned int)Slide << 21; This tests Slide <= 128, if it is then it just multiplies by 0x200000. Which ranges from 0x10000000 to 0x1FE00000. SlideAddress = SlideInt << 21; RealSlideAddress = SlideAddress + 0x10200000; For > 128, there are two parts. First, it gets multiplied by 0x200000 and added to 0x10200000. Which ranges from 0x10200000 to 0x20000000. But the next part does not make sense..... if ( (CpuModel | 0x10) != 0x3A ) // For CPUs which model is not 0x3A RealSlideAddress = SlideAddress; So for some reason anything that is not SB or IB the range becomes 0x200000 to 0xFE00000..... Ummmmmmmmmmmmm....... There's no way that slide=0 is putting the kernel at adresss 0. EDIT: Slide=0 is not a valid slide so it will never be used to calculate the address. if ( CpuFamily != 6 ) // For CPUs which family is not 6 RealSlideAddress = SlideAddress; This is not ever happening. What CPU is not family 6 that can run macOS? SuppliedSlide = StringToInteger(value); if ( SuppliedSlide ) { if ( SuppliedSlide - 1 > 0xFE ) // SuppliedSlide >= 0x00 && SuppliedSlide <= 0xFF goto KASLR_DONE; gKernelSlide = (unsigned int)CalculateSlideAddress(SuppliedSlide); goto SLIDE_SET; } What is this? This says slide=0 has no effect but it clearly does. Since if SuppliedSlide is zero it will be skipped for being false in the first if. The second if is the weirdest (and possibly dumbest) check that SuppliedSlide is <= 0xFF I've ever seen. EDIT: Oh I see, slide=0 actually disables KASLR and it will go back to 0x100000. BYTE1(GlobalVariableState) &= 0xBFu; // &= ~BOOT_MODE_ASLR EDIT2: This is a disaster actually. I wonder if this has changed since the original KASLR because I remember dmazar explaining it to me exactly like I've been telling everyone to calculate it.... But that is not correct for SB and IB. EDIT3: So the addresses available to be loaded at are 0x100000 for no KASLR. 0x200000 to 0x1FE00000 for non SB or IB. For SB and IB, 0x10200000 to 0x20000000. All aligned on 0x200000 boundaries. EDIT4: In case anyone is wondering that's only 383 possible places the kernel could be located, if you don't know the CPU model. If you do then it's only 256 places, obviously. And one of those places (with KASLR disabled) you should attempt to attack first anyway, so it's actually one less. I don't see how this couldn't easily be attacked, it's not really randomized at all. In fact, I actually am not going to continue my thought................... EDIT5: I'm dumb and did it backwards, vit9696 fixed the slide table below. 5 Link to comment Share on other sites More sharing options...
vit9696 Posted January 8, 2018 Author Share Posted January 8, 2018 apianti, I suppose it is much easier to read this by comparing to the relevant macosxbootloader code: link. It indeed is the case that CPUs newer than Ivy Bridge get a different slide offset, and I have no idea of the reasons behind. By the way, you got it a little wrong regarding zero, because slide setup is not called with any value but 1~255. So the minimum value is 0x100000. And with zero it falls through and BOOT_MODE_ASLR bit is unset. I should porbably mention the relevant XNU code describing the use of kaslr, here it confirms to us that kaslr slide has to be 0x100000 due to the subtraction: vm_offset_t ml_static_ptovirt( vm_offset_t paddr) { return (vm_offset_t)(((unsigned long) paddr) | VM_MIN_KERNEL_ADDRESS); // VM_MIN_KERNEL_ADDRESS = 0xFFFFFF8000000000 } static_base_address = ml_static_ptovirt(KERNEL_BASE_OFFSET); // KERNEL_BASE_OFFSET = 0x100000 base_address = ml_static_ptovirt(args->kaddr); vm_kernel_slide = base_address - static_base_address;There is nothing interesting/relevant after DONE, there are other boot arguments handling and stuff. Regarding CPU family comparison I suppose it is legacy, since in old times Intel did have 0xF used in some of Xeons and Pentiums: https://software.intel.com/en-us/articles/intel-architecture-and-processor-identification-with-cpuid-model-and-family-numbers From the top of my head I could say that Xserve1,1 had a Xeon Woodcrest processor, which had 0xF family. 4 Link to comment Share on other sites More sharing options...
apianti Posted January 8, 2018 Share Posted January 8, 2018 apianti, I suppose it is much easier to read this by comparing to the relevant macosxbootloader code: link. It indeed is the case that CPUs newer than Ivy Bridge get a different slide offset, and I have no idea of the reasons behind. By the way, you got it a little wrong regarding zero, because slide setup is not called with any value but 1~255. So the minimum value is 0x100000. And with zero it falls through and BOOT_MODE_ASLR bit is unset. Yeah, I realized that and edited it because apparently slide=0 means disable KASLR before your response. I should porbably mention the relevant XNU code describing the use of kaslr, here it confirms to us that kaslr slide has to be 0x100000 due to the subtraction: vm_offset_t ml_static_ptovirt( vm_offset_t paddr) { return (vm_offset_t)(((unsigned long) paddr) | VM_MIN_KERNEL_ADDRESS); // VM_MIN_KERNEL_ADDRESS = 0xFFFFFF8000000000 } static_base_address = ml_static_ptovirt(KERNEL_BASE_OFFSET); // KERNEL_BASE_OFFSET = 0x100000 base_address = ml_static_ptovirt(args->kaddr); vm_kernel_slide = base_address - static_base_address; Oh, so it does need that 0x100000 added? Or subtracted? I think that confused me more.... The base_address is some different value though unless slide=0 or KASLR is disabled? Because vm_kernel_slide will be zero if it's disabled? There is nothing interesting/relevant after DONE, there are other boot arguments handling and stuff. Didn't think so but just making sure. Regarding CPU family comparison I suppose it is legacy, since in old times Intel did have 0xF used in some of Xeons and Pentiums: https://software.intel.com/en-us/articles/intel-architecture-and-processor-identification-with-cpuid-model-and-family-numbersFrom the top of my head I could say that Xserve1,1 had a Xeon Woodcrest processor, which had 0xF family. Yeah but KASLR wasn't introduced until ML and Xserve1,1 can't run ML, it's not a supported model. So not sure who is writing that code but....... I think they may need some time off. Jobs ghost still making them pull 56 hour shifts? 3 Link to comment Share on other sites More sharing options...
vit9696 Posted January 8, 2018 Author Share Posted January 8, 2018 Oh, so it does need that 0x100000 added? Or subtracted? I think that confused me more.... The base_address is some different value though unless slide=0 or KASLR is disabled? Because vm_kernel_slide will be zero if it's disabled? I hope I understand it right, and it means the following. The kernel is normally allocated at base 0x100000 + slide address. Slide address consists of slide value (either passed by slide=X or implicitly generated), which always adds as X * 0x200000 and possibly a platform-specific & value-specific constant. Here is the table with the relevant values. For slide=0 (or when implicitly off) this is just 0x100000 (and thus people cannot boot if the address is used in -x). For slide=0x1~0x7F (passed or randomly generated) the kernel is allocated from 0x100000 + 0x200000 till 0x100000 + 0xFE00000. For slide=0x80~0xFF (passed or randomly generated) on Sandy Bridge or Ivy Bridge CPUs from 0x100000 + 0x20200000 till 0x100000 + 0x30000000. For slide=0x80~0xFF (passed or randomly generated) on Other CPUs from 0x100000 + 0x10000000 till 0x100000 + 0x1FE00000. 16 Link to comment Share on other sites More sharing options...
apianti Posted January 8, 2018 Share Posted January 8, 2018 Yeah, I just realized I did it backwards... Nice catch. I crossed mine out. And that made it way more understandable. I guess the original calculation was correct if the value < 128. For >= 128, it is not for SB or IB but the others it is, yes? Link to comment Share on other sites More sharing options...
vit9696 Posted January 8, 2018 Author Share Posted January 8, 2018 Yeah, I just realized I did it backwards... Nice catch. I crossed mine out. And that made it way more understandable. I guess the original calculation was correct if the value < 128. For >= 128, it is not for SB or IB but the others it is, yes? Not impossible indeed. Added to the first post just in case. Link to comment Share on other sites More sharing options...
WinstonAce Posted January 9, 2018 Share Posted January 9, 2018 Hi can you explain the formula for calculating slide value? can't understand what slide value to use with this memory map Thanks in advance Type Start End # Pages Attributes available 0000000000000000-0000000000057FFF 0000000000000058 000000000000000F reserved 0000000000058000-0000000000058FFF 0000000000000001 000000000000000F available 0000000000059000-000000000009DFFF 0000000000000045 000000000000000F reserved 000000000009E000-000000000009FFFF 0000000000000002 000000000000000F available 0000000000100000-00000000A9845FFF 00000000000A9746 000000000000000F LoaderData 00000000A9846000-00000000A9945FFF 0000000000000100 000000000000000F available 00000000A9946000-00000000ABF1FFFF 00000000000025DA 000000000000000F LoaderData 00000000ABF20000-00000000ABF33FFF 0000000000000014 000000000000000F LoaderCode 00000000ABF34000-00000000AC000FFF 00000000000000CD 000000000000000F ACPI_NVS 00000000AC001000-00000000AC007FFF 0000000000000007 000000000000000F BS_data 00000000AC008000-00000000AC198FFF 0000000000000191 000000000000000F BS_code 00000000AC199000-00000000ACF0AFFF 0000000000000D72 000000000000000F BS_data 00000000ACF0B000-00000000ACF1BFFF 0000000000000011 000000000000000F BS_code 00000000ACF1C000-00000000ACF2DFFF 0000000000000012 000000000000000F BS_data 00000000ACF2E000-00000000ACF38FFF 000000000000000B 000000000000000F BS_code 00000000ACF39000-00000000ACF3AFFF 0000000000000002 000000000000000F RT_data 00000000ACF3B000-00000000AD7F6FFF 00000000000008BC 800000000000000F BS_data 00000000AD7F7000-00000000AD835FFF 000000000000003F 000000000000000F LoaderData 00000000AD836000-00000000AD844FFF 000000000000000F 000000000000000F available 00000000AD845000-00000000C0F8DFFF 0000000000013749 000000000000000F BS_data 00000000C0F8E000-00000000C128EFFF 0000000000000301 000000000000000F available 00000000C128F000-00000000C158FFFF 0000000000000301 000000000000000F BS_data 00000000C1590000-00000000C16BCFFF 000000000000012D 000000000000000F available 00000000C16BD000-00000000C174AFFF 000000000000008E 000000000000000F BS_data 00000000C174B000-00000000C58FAFFF 00000000000041B0 000000000000000F available 00000000C58FB000-00000000C6C28FFF 000000000000132E 000000000000000F BS_code 00000000C6C29000-00000000C6FF2FFF 00000000000003CA 000000000000000F reserved 00000000C6FF3000-00000000C7023FFF 0000000000000031 000000000000000F reserved 00000000C7024000-00000000C7084FFF 0000000000000061 000000000000000F available 00000000C7085000-00000000C70ECFFF 0000000000000068 000000000000000F ACPI_NVS 00000000C70ED000-00000000C7215FFF 0000000000000129 000000000000000F ACPI_NVS 00000000C7216000-00000000C7219FFF 0000000000000004 000000000000000F ACPI_NVS 00000000C721A000-00000000C7231FFF 0000000000000018 000000000000000F RT_data 00000000C7232000-00000000C9C3CFFF 0000000000002A0B 800000000000000F RT_data 00000000C9C3D000-00000000C9E95FFF 0000000000000259 800000000000000F RT_data 00000000C9E96000-00000000C9E97FFF 0000000000000002 800000000000000F RT_data 00000000C9E98000-00000000C9F16FFF 000000000000007F 800000000000000F RT_code 00000000C9F17000-00000000C9F60FFF 000000000000004A 800000000000000F RT_code 00000000C9F61000-00000000C9FFEFFF 000000000000009E 800000000000000F BS_data 00000000C9FFF000-00000000C9FFFFFF 0000000000000001 000000000000000F available 0000000100000000-000000042FDFFFFF 000000000032FE00 000000000000000F reserved 00000000CB000000-00000000CF1FFFFF 0000000000004200 8000000000000000 MemMapIO 00000000F8000000-00000000FBFFFFFF 0000000000004000 8000000000000001 MemMapIO 00000000FEC00000-00000000FEC00FFF 0000000000000001 8000000000000001 MemMapIO 00000000FED00000-00000000FED03FFF 0000000000000004 8000000000000001 MemMapIO 00000000FED1C000-00000000FED1FFFF 0000000000000004 8000000000000001 MemMapIO 00000000FEE00000-00000000FEE00FFF 0000000000000001 8000000000000001 MemMapIO 00000000FF000000-00000000FFFFFFFF 0000000000001000 8000000000000001 Link to comment Share on other sites More sharing options...
apianti Posted January 9, 2018 Share Posted January 9, 2018 Hi can you explain the formula for calculating slide value? can't understand what slide value to use with this memory map Thanks in advance available 0000000000100000-00000000A9845FFF 00000000000A9746 000000000000000F Any slide will be fine, so don't set one and let it choose one randomly. 1 Link to comment Share on other sites More sharing options...
Slice Posted January 9, 2018 Share Posted January 9, 2018 I got a strange result OsxAptioFix2 error: Doing hibernate wake, but did not find hibernate image address.... waiting 5 secs ... Meanwhile NVRAM works. Thanks! PS. wake-failure %013%08f Link to comment Share on other sites More sharing options...
vit9696 Posted January 10, 2018 Author Share Posted January 10, 2018 Published the source code of my changes here: https://github.com/vit9696/AptioFix Enjoy =) 17 Link to comment Share on other sites More sharing options...
Funky frank Posted January 10, 2018 Share Posted January 10, 2018 Wow, nice. Any changes since 2 todays? Is there a binary? Link to comment Share on other sites More sharing options...
gujiangjiang Posted January 11, 2018 Share Posted January 11, 2018 Published the source code of my changes here: https://github.com/vit9696/AptioFix Enjoy =) Hello vit Can we add apfsjumpstart protocols to AptioInputFix to avoid debug log when using apfs.efi. Thanks. 从我的 iPhone 发送,使用 Tapatalk Link to comment Share on other sites More sharing options...
cecekpawon Posted January 11, 2018 Share Posted January 11, 2018 Wow, nice. Any changes since 2 todays? Is there a binary? Just compile and had not test my self AptioFixPlatform.zip 5 Link to comment Share on other sites More sharing options...
Slice Posted January 11, 2018 Share Posted January 11, 2018 Published the source code of my changes here: https://github.com/vit9696/AptioFix Enjoy =) May we somehow include this driver into Clover release package as option? 6 Link to comment Share on other sites More sharing options...
gujiangjiang Posted January 11, 2018 Share Posted January 11, 2018 Report: AptioInputFix may cause CloverGUI can’t move through the keyboard. It may cause CloverGUI Freeze. 从我的 iPhone 发送,使用 Tapatalk My another laptop using aptiomemfix and show this. 从我的 iPhone 发送,使用 Tapatalk Link to comment Share on other sites More sharing options...
Guest Posted January 11, 2018 Share Posted January 11, 2018 Thank you It is working well for my rig I have deleted latest optiofix2 and slide=128 (mandatory for me to pass memory error in some conditions) and system starts fine I have some debug message from two new efi you posted, maybe it is a scan of memory position to automatic decide which slide is useful for me... Just compile and had not test my self Link to comment Share on other sites More sharing options...
SV0911 Posted January 11, 2018 Share Posted January 11, 2018 @fabiosun could you maybe tell me which one of the releases (GCC5, GCC49, VS2015x86, XCODE5) i have to choose for my rig (see my sig..) to test it? Big thanks in advance!!!! Link to comment Share on other sites More sharing options...
Guest Posted January 11, 2018 Share Posted January 11, 2018 I have used Xcode5 Link to comment Share on other sites More sharing options...
vit9696 Posted January 11, 2018 Author Share Posted January 11, 2018 May we somehow include this driver into Clover release package as option?Why not? But I would suggest you wait a little, perhaps some ideas arise from other devs and they could improve things first. 2all, AptioInputFix aka AsAmiShim is the source code of my FV2 input driver, you may not need it. 5 Link to comment Share on other sites More sharing options...
SV0911 Posted January 11, 2018 Share Posted January 11, 2018 I have used Xcode5 Big thanks again fabiosun, and i like to confirm that it´s working on my rig (with the above choosen one..) Also Big thanks to @vit9696 !!! Link to comment Share on other sites More sharing options...
apianti Posted January 11, 2018 Share Posted January 11, 2018 May we somehow include this driver into Clover release package as option? I'm reviewing the code and will probably replace what's in clover if it looks good. But I want a new name, I hate referring to it as "Aptio" fix, it is for more than just that though... Philip will need to change the package, I hate that thing, won't touch it.... 1 Link to comment Share on other sites More sharing options...
vit9696 Posted January 11, 2018 Author Share Posted January 11, 2018 apianti, it is literally for aptio, and there is one more driver, which is also for aptio. So the naming if anything should stay. In my opinion, it is better to maintain it externally from clover and just clone as edk and friends, because there is no reason only clover should use these drivers. I am fine to give any of you commit access if necessary. 2 Link to comment Share on other sites More sharing options...
Guest Posted January 11, 2018 Share Posted January 11, 2018 @vit9696 Is it correct this output? system boots fine Link to comment Share on other sites More sharing options...
Recommended Posts