From 07b697d28d7b599e3c72133a61944d9a9ca76d23 Mon Sep 17 00:00:00 2001 From: Download-Fritz Date: Sat, 4 Jul 2020 15:28:22 +0200 Subject: [PATCH] OcMachoLib: Support KC Mach-Os --- Include/Acidanthera/Library/OcMachoLib.h | 12 +- Library/OcAppleKernelLib/KernelCollection.c | 3 +- Library/OcAppleKernelLib/KextPatcher.c | 2 +- Library/OcAppleKernelLib/Link.c | 2 +- Library/OcAppleKernelLib/PrelinkedContext.c | 11 +- Library/OcAppleKernelLib/PrelinkedKext.c | 8 +- Library/OcMachoLib/Header.c | 110 ++++++++++++------ Library/OcMachoLib/Symbols.c | 2 +- .../TestKernelCollection2/KernelCollection2.c | 2 +- Utilities/TestMacho/Macho.c | 2 +- 10 files changed, 104 insertions(+), 50 deletions(-) diff --git a/Include/Acidanthera/Library/OcMachoLib.h b/Include/Acidanthera/Library/OcMachoLib.h index c40ed7c5..67764f1a 100644 --- a/Include/Acidanthera/Library/OcMachoLib.h +++ b/Include/Acidanthera/Library/OcMachoLib.h @@ -34,6 +34,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. typedef struct { MACH_HEADER_64 *MachHeader; UINT32 FileSize; + UINT32 ContainerOffset; MACH_SYMTAB_COMMAND *Symtab; MACH_NLIST_64 *SymbolTable; CHAR8 *StringTable; @@ -46,9 +47,11 @@ typedef struct { /** Initializes a Mach-O Context. - @param[out] Context Mach-O Context to initialize. - @param[in] FileData Pointer to the file's data. - @param[in] FileSize File size of FileData. + @param[out] Context Mach-O Context to initialize. + @param[in] FileData Pointer to the file's expected Mach-O header. + @param[in] FileSize File size of FileData. + @param[in] ContainerOffset The amount of Bytes the Mach-O header is offset + from the base (container, e.g. KC) of the file. @return Whether Context has been initialized successfully. @@ -57,7 +60,8 @@ BOOLEAN MachoInitializeContext ( OUT OC_MACHO_CONTEXT *Context, IN VOID *FileData, - IN UINT32 FileSize + IN UINT32 FileSize, + IN UINT32 ContainerOffset ); /** diff --git a/Library/OcAppleKernelLib/KernelCollection.c b/Library/OcAppleKernelLib/KernelCollection.c index c01a4ee6..71d06a43 100644 --- a/Library/OcAppleKernelLib/KernelCollection.c +++ b/Library/OcAppleKernelLib/KernelCollection.c @@ -642,7 +642,8 @@ KcGetKextSize ( Result = MachoInitializeContext ( &KextContext, Context->Prelinked + KextOffset, - Context->PrelinkedSize - KextOffset + Context->PrelinkedSize - KextOffset, + KextOffset ); if (!Result) { return 0; diff --git a/Library/OcAppleKernelLib/KextPatcher.c b/Library/OcAppleKernelLib/KextPatcher.c index 0be08010..5c64eea1 100644 --- a/Library/OcAppleKernelLib/KextPatcher.c +++ b/Library/OcAppleKernelLib/KextPatcher.c @@ -64,7 +64,7 @@ PatcherInitContextFromBuffer ( // and request PRELINK_KERNEL_IDENTIFIER. // - if (!MachoInitializeContext (&Context->MachContext, Buffer, BufferSize)) { + if (!MachoInitializeContext (&Context->MachContext, Buffer, BufferSize, 0)) { return EFI_INVALID_PARAMETER; } diff --git a/Library/OcAppleKernelLib/Link.c b/Library/OcAppleKernelLib/Link.c index 01d1470c..0b4ed4be 100644 --- a/Library/OcAppleKernelLib/Link.c +++ b/Library/OcAppleKernelLib/Link.c @@ -1644,7 +1644,7 @@ InternalPrelinkKext64 ( // Reinitialize the Mach-O context to account for the changed __LINKEDIT // segment and file size. // - if (!MachoInitializeContext (MachoContext, MachHeader, (SegmentOffset + SegmentSize))) { + if (!MachoInitializeContext (MachoContext, MachHeader, (SegmentOffset + SegmentSize), MachoContext->ContainerOffset)) { // // This should never failed under normal and abnormal conditions. // diff --git a/Library/OcAppleKernelLib/PrelinkedContext.c b/Library/OcAppleKernelLib/PrelinkedContext.c index 9e808e46..d6ce9b21 100644 --- a/Library/OcAppleKernelLib/PrelinkedContext.c +++ b/Library/OcAppleKernelLib/PrelinkedContext.c @@ -224,7 +224,7 @@ PrelinkedContextInit ( // // Initialise primary context. // - if (!MachoInitializeContext (&Context->PrelinkedMachContext, Prelinked, PrelinkedSize)) { + if (!MachoInitializeContext (&Context->PrelinkedMachContext, Prelinked, PrelinkedSize, 0)) { return EFI_INVALID_PARAMETER; } @@ -249,7 +249,8 @@ PrelinkedContextInit ( if (!MachoInitializeContext ( &Context->InnerMachContext, &Context->Prelinked[Segment->FileOffset], - (UINT32) (Context->PrelinkedSize - Segment->FileOffset))) { + (UINT32) (Context->PrelinkedSize - Segment->FileOffset), + (UINT32) Segment->FileOffset)) { return EFI_INVALID_PARAMETER; } @@ -679,7 +680,7 @@ PrelinkedReserveKextSize ( if (Executable != NULL) { ASSERT (ExecutableSize > 0); - if (!MachoInitializeContext (&Context, Executable, ExecutableSize)) { + if (!MachoInitializeContext (&Context, Executable, ExecutableSize, 0)) { return EFI_INVALID_PARAMETER; } @@ -747,7 +748,7 @@ PrelinkedInjectKext ( // if (Executable != NULL) { ASSERT (ExecutableSize > 0); - if (!MachoInitializeContext (&ExecutableContext, (UINT8 *)Executable, ExecutableSize)) { + if (!MachoInitializeContext (&ExecutableContext, (UINT8 *)Executable, ExecutableSize, 0)) { DEBUG ((DEBUG_INFO, "OCAK: Injected kext %a/%a is not a supported executable\n", BundlePath, ExecutablePath)); return EFI_INVALID_PARAMETER; } @@ -776,7 +777,7 @@ PrelinkedInjectKext ( AlignedExecutableSize - ExecutableSize ); - if (!MachoInitializeContext (&ExecutableContext, &Context->Prelinked[KextOffset], ExecutableSize)) { + if (!MachoInitializeContext (&ExecutableContext, &Context->Prelinked[KextOffset], ExecutableSize, 0)) { return EFI_INVALID_PARAMETER; } diff --git a/Library/OcAppleKernelLib/PrelinkedKext.c b/Library/OcAppleKernelLib/PrelinkedKext.c index 09c694c5..3c3efc3b 100644 --- a/Library/OcAppleKernelLib/PrelinkedKext.c +++ b/Library/OcAppleKernelLib/PrelinkedKext.c @@ -56,6 +56,7 @@ InternalCreatePrelinkedKext ( UINT64 SourceSize; UINT64 SourceEnd; BOOLEAN Found; + UINT32 ContainerOffset; KextIdentifier = NULL; BundleLibraries = NULL; @@ -155,6 +156,11 @@ InternalCreatePrelinkedKext ( SourceEnd > Prelinked->PrelinkedSize) { return NULL; } + + ContainerOffset = 0; + if (Prelinked->IsKernelCollection) { + ContainerOffset = (UINT32) SourceBase; + } } // @@ -166,7 +172,7 @@ InternalCreatePrelinkedKext ( } if (Prelinked != NULL - && !MachoInitializeContext (&NewKext->Context.MachContext, &Prelinked->Prelinked[SourceBase], (UINT32)SourceSize)) { + && !MachoInitializeContext (&NewKext->Context.MachContext, &Prelinked->Prelinked[SourceBase], (UINT32)SourceSize, ContainerOffset)) { FreePool (NewKext); return NULL; } diff --git a/Library/OcMachoLib/Header.c b/Library/OcMachoLib/Header.c index 2d47da13..0ffdc760 100644 --- a/Library/OcMachoLib/Header.c +++ b/Library/OcMachoLib/Header.c @@ -187,7 +187,8 @@ BOOLEAN MachoInitializeContext ( OUT OC_MACHO_CONTEXT *Context, IN VOID *FileData, - IN UINT32 FileSize + IN UINT32 FileSize, + IN UINT32 ContainerOffset ) { MACH_HEADER_64 *MachHeader; @@ -272,8 +273,9 @@ MachoInitializeContext ( ZeroMem (Context, sizeof (*Context)); - Context->MachHeader = MachHeader; - Context->FileSize = FileSize; + Context->MachHeader = MachHeader; + Context->FileSize = FileSize; + Context->ContainerOffset = ContainerOffset; return TRUE; } @@ -485,10 +487,15 @@ InternalSectionIsSane ( } if (Section->NumRelocations != 0) { - Result = OcOverflowMulAddU32 ( + Result = OcOverflowSubU32 ( + Section->RelocationsOffset, + Context->ContainerOffset, + &TopOffset32 + ); + Result |= OcOverflowMulAddU32 ( Section->NumRelocations, sizeof (MACH_RELOCATION_INFO), - Section->RelocationsOffset, + TopOffset32, &TopOffset32 ); if (Result || (TopOffset32 > Context->FileSize)) { @@ -642,11 +649,16 @@ MachoGetNextSegment64 ( return NULL; } - Result = OcOverflowAddU64 ( + Result = OcOverflowSubU64 ( NextSegment->FileOffset, - NextSegment->FileSize, + Context->ContainerOffset, &TopOfSegment ); + Result |= OcOverflowAddU64 ( + TopOfSegment, + NextSegment->FileSize, + &TopOfSegment + ); if (Result || (TopOfSegment > Context->FileSize)) { return NULL; } @@ -821,9 +833,14 @@ InternalInitialiseSymtabs64 ( UINTN MachoAddress; CHAR8 *StringTable; UINT32 FileSize; + UINT32 SymbolsOffset; + UINT32 StringsOffset; UINT32 OffsetTop; BOOLEAN Result; + UINT32 IndirectSymbolsOffset; + UINT32 LocalRelocationsOffset; + UINT32 ExternalRelocationsOffset; MACH_NLIST_64 *SymbolTable; MACH_NLIST_64 *IndirectSymtab; MACH_RELOCATION_INFO *LocalRelocations; @@ -838,33 +855,43 @@ InternalInitialiseSymtabs64 ( FileSize = Context->FileSize; - Result = OcOverflowMulAddU32 ( - Symtab->NumSymbols, - sizeof (MACH_NLIST_64), + Result = OcOverflowSubU32 ( Symtab->SymbolsOffset, - &OffsetTop + Context->ContainerOffset, + &SymbolsOffset ); + Result |= OcOverflowMulAddU32 ( + Symtab->NumSymbols, + sizeof (MACH_NLIST_64), + SymbolsOffset, + &OffsetTop + ); if (Result || (OffsetTop > FileSize)) { return FALSE; } - Result = OcOverflowAddU32 ( + Result = OcOverflowSubU32 ( Symtab->StringsOffset, - Symtab->StringsSize, - &OffsetTop + Context->ContainerOffset, + &StringsOffset ); + Result |= OcOverflowAddU32 ( + StringsOffset, + Symtab->StringsSize, + &OffsetTop + ); if (Result || (OffsetTop > FileSize)) { return FALSE; } MachoAddress = (UINTN)Context->MachHeader; - StringTable = (CHAR8 *)(MachoAddress + Symtab->StringsOffset); + StringTable = (CHAR8 *)(MachoAddress + StringsOffset); if (Symtab->StringsSize == 0 || StringTable[Symtab->StringsSize - 1] != '\0') { return FALSE; } - Tmp = (VOID *)(MachoAddress + Symtab->SymbolsOffset); + Tmp = (VOID *)(MachoAddress + SymbolsOffset); if (!OC_TYPE_ALIGNED (MACH_NLIST_64, Tmp)) { return FALSE; } @@ -902,49 +929,64 @@ InternalInitialiseSymtabs64 ( return FALSE; } - Result = OcOverflowMulAddU32 ( - DySymtab->NumIndirectSymbols, - sizeof (MACH_NLIST_64), + Result = OcOverflowSubU32 ( DySymtab->IndirectSymbolsOffset, - &OffsetTop + Context->ContainerOffset, + &IndirectSymbolsOffset ); + Result |= OcOverflowMulAddU32 ( + DySymtab->NumIndirectSymbols, + sizeof (MACH_NLIST_64), + IndirectSymbolsOffset, + &OffsetTop + ); if (Result || (OffsetTop > FileSize)) { return FALSE; } - Result = OcOverflowMulAddU32 ( - DySymtab->NumOfLocalRelocations, - sizeof (MACH_RELOCATION_INFO), + Result = OcOverflowSubU32 ( DySymtab->LocalRelocationsOffset, - &OffsetTop + Context->ContainerOffset, + &LocalRelocationsOffset ); + Result |= OcOverflowMulAddU32 ( + DySymtab->NumOfLocalRelocations, + sizeof (MACH_RELOCATION_INFO), + LocalRelocationsOffset, + &OffsetTop + ); if (Result || (OffsetTop > FileSize)) { return FALSE; } - Result = OcOverflowMulAddU32 ( - DySymtab->NumExternalRelocations, - sizeof (MACH_RELOCATION_INFO), + Result = OcOverflowSubU32 ( DySymtab->ExternalRelocationsOffset, - &OffsetTop + Context->ContainerOffset, + &ExternalRelocationsOffset ); + Result |= OcOverflowMulAddU32 ( + DySymtab->NumExternalRelocations, + sizeof (MACH_RELOCATION_INFO), + ExternalRelocationsOffset, + &OffsetTop + ); if (Result || (OffsetTop > FileSize)) { return FALSE; } - Tmp = (VOID *)(MachoAddress + DySymtab->IndirectSymbolsOffset); + Tmp = (VOID *)(MachoAddress + IndirectSymbolsOffset); if (!OC_TYPE_ALIGNED (MACH_NLIST_64, Tmp)) { return FALSE; } IndirectSymtab = (MACH_NLIST_64 *)Tmp; - Tmp = (VOID *)(MachoAddress + DySymtab->LocalRelocationsOffset); + Tmp = (VOID *)(MachoAddress + LocalRelocationsOffset); if (!OC_TYPE_ALIGNED (MACH_RELOCATION_INFO, Tmp)) { return FALSE; } LocalRelocations = (MACH_RELOCATION_INFO *)Tmp; - Tmp = (VOID *)(MachoAddress + DySymtab->ExternalRelocationsOffset); + Tmp = (VOID *)(MachoAddress + ExternalRelocationsOffset); if (!OC_TYPE_ALIGNED (MACH_RELOCATION_INFO, Tmp)) { return FALSE; } @@ -1176,7 +1218,7 @@ MachoGetFilePointerByAddress64 ( *MaxSize = (UINT32)(Segment->Size - Offset); } - Offset += Segment->FileOffset; + Offset += Segment->FileOffset - Context->ContainerOffset; return (VOID *)((UINTN)Context->MachHeader + (UINTN)Offset); } } @@ -1322,7 +1364,7 @@ MachoExpandImage64 ( // // Do not overwrite header. // - CopyFileOffset = Segment->FileOffset; + CopyFileOffset = Segment->FileOffset - Context->ContainerOffset; CopyFileSize = Segment->FileSize; CopyVmSize = Segment->Size; if (CopyFileOffset <= HeaderSize) { @@ -1359,7 +1401,7 @@ MachoExpandImage64 ( DstSegment->FileOffset += CurrentDelta; DstSegment->FileSize = DstSegment->Size; - if (DstSegment->VirtualAddress - DstSegment->FileOffset != FirstSegment->VirtualAddress) { + if (DstSegment->VirtualAddress - (DstSegment->FileOffset - Context->ContainerOffset) != FirstSegment->VirtualAddress) { return 0; } diff --git a/Library/OcMachoLib/Symbols.c b/Library/OcMachoLib/Symbols.c index 3e99c232..51cce153 100644 --- a/Library/OcMachoLib/Symbols.c +++ b/Library/OcMachoLib/Symbols.c @@ -662,7 +662,7 @@ MachoSymbolGetFileOffset64 ( return FALSE; } - *FileOffset = (Section->Offset + (UINT32)Offset); + *FileOffset = (Section->Offset - Context->ContainerOffset + (UINT32)Offset); if (MaxSize != NULL) { *MaxSize = (UINT32)(Section->Size - Offset); diff --git a/Utilities/TestKernelCollection2/KernelCollection2.c b/Utilities/TestKernelCollection2/KernelCollection2.c index b4c07002..0560133a 100644 --- a/Utilities/TestKernelCollection2/KernelCollection2.c +++ b/Utilities/TestKernelCollection2/KernelCollection2.c @@ -49,7 +49,7 @@ extern UINT32 VsmcKextInfoPlistDataSize; static int FeedMacho(void *file, uint32_t size) { OC_MACHO_CONTEXT Context; - if (!MachoInitializeContext (&Context, file, size)) { + if (!MachoInitializeContext (&Context, file, size, 0)) { DEBUG ((DEBUG_WARN, "MachoInitializeContext failure\n")); return -1; } diff --git a/Utilities/TestMacho/Macho.c b/Utilities/TestMacho/Macho.c index 7715dde1..25c30ab6 100644 --- a/Utilities/TestMacho/Macho.c +++ b/Utilities/TestMacho/Macho.c @@ -39,7 +39,7 @@ MACH_UUID_COMMAND Uuid; static int FeedMacho(void *file, uint32_t size) { OC_MACHO_CONTEXT Context; - if (!MachoInitializeContext (&Context, file, size)) { + if (!MachoInitializeContext (&Context, file, size, 0)) { return -1; }