提交 70c55e03 编写于 作者: V vit9696

OcAppleKernelLib: Implement CPUID patching for 10.6 64-bit

上级 b5dcbd32
...@@ -42,6 +42,11 @@ prelinkedkernel.unpack ...@@ -42,6 +42,11 @@ prelinkedkernel.unpack
*.dmg *.dmg
*.chunklist *.chunklist
*.pyc *.pyc
*.id0
*.id1
*.id2
*.nam
*.til
Debug/QemuRun Debug/QemuRun
Doxy Doxy
Legacy/BinDrivers/X64 Legacy/BinDrivers/X64
......
...@@ -86,6 +86,11 @@ ...@@ -86,6 +86,11 @@
// //
#define PLIST_EXPANSION_SIZE 512 #define PLIST_EXPANSION_SIZE 512
//
// Make integral kernel version.
//
#define KERNEL_VERSION(A, B, C) ((A) * 10000 + (B) * 100 + (C))
// //
// Prelinked context used for kernel modification. // Prelinked context used for kernel modification.
// //
...@@ -420,6 +425,50 @@ ReadAppleKernel ( ...@@ -420,6 +425,50 @@ ReadAppleKernel (
OUT UINT8 *Digest OPTIONAL OUT UINT8 *Digest OPTIONAL
); );
/**
Create Apple kernel version in integer format.
See KERNEL_VERSION on how to build it from integers.
@param[in] String Apple kernel version.
@returns Kernel version or 0.
**/
UINT32
OcParseDarwinVersion (
IN CONST CHAR8 *String
);
/**
Read Apple kernel version in integer format.
@param[in] Kernel Apple kernel binary.
@param[in] KernelSize Apple kernel size.
@returns Kernel version or 0.
**/
UINT32
OcKernelReadDarwinVersion (
IN CONST UINT8 *Kernel,
IN UINT32 KernelSize
);
/**
Check whether min <= current <= max is true.
When current or max are 0 they are considered infinite.
@param[in] CurrentVersion Current kernel version.
@param[in] MinVersion Minimal kernel version.
@param[in] MaxVersion Maximum kernel version.
@returns TRUE on match.
**/
BOOLEAN
OcMatchDarwinVersion (
IN UINT32 CurrentVersion OPTIONAL,
IN UINT32 MinVersion OPTIONAL,
IN UINT32 MaxVersion OPTIONAL
);
/** /**
Construct prelinked context for later modification. Construct prelinked context for later modification.
Must be freed with PrelinkedContextFree on success. Must be freed with PrelinkedContextFree on success.
......
...@@ -983,13 +983,28 @@ PatchIncreasePciBarSize ( ...@@ -983,13 +983,28 @@ PatchIncreasePciBarSize (
STATIC STATIC
CONST UINT8 CONST UINT8
mKernelCpuIdFindRelNew[] = { mKernelCpuIdFindRelNew[] = {
0xB9, 0x8B, 0x00, 0x00, 0x00, 0x31, 0xC0, 0x31, 0xD2, 0x0F, 0x30, 0xB8, 0x01, 0x00, 0x00, 0x00, 0x31, 0xDB, 0x31, 0xC9, 0x31, 0xD2, 0x0F, 0xA2 0xB9, 0x8B, 0x00, 0x00, 0x00, ///< mov ecx, 8Bh
0x31, 0xC0, ///< xor eax, eax
0x31, 0xD2, ///< xor edx, edx
0x0F, 0x30, ///< wrmsr
0xB8, 0x01, 0x00, 0x00, 0x00, ///< mov eax, 1
0x31, 0xDB, ///< xor ebx, ebx
0x31, 0xC9, ///< xor ecx, ecx
0x31, 0xD2, ///< xor edx, edx
0x0F, 0xA2 ///< cpuid
}; };
STATIC STATIC
CONST UINT8 CONST UINT8
mKernelCpuIdFindRelOld[] = { mKernelCpuIdFindRelOld[] = {
0xB9, 0x8B, 0x00, 0x00, 0x00, 0x31, 0xD2, 0x0F, 0x30, 0xB8, 0x01, 0x00, 0x00, 0x00, 0x31, 0xDB, 0x31, 0xC9, 0x31, 0xD2, 0x0F, 0xA2 0xB9, 0x8B, 0x00, 0x00, 0x00, ///< mov ecx, 8Bh
0x31, 0xD2, ///< xor edx, edx
0x0F, 0x30, ///< wrmsr
0xB8, 0x01, 0x00, 0x00, 0x00, ///< mov eax, 1
0x31, 0xDB, ///< xor ebx, ebx
0x31, 0xC9, ///< xor ecx, ecx
0x31, 0xD2, ///< xor edx, edx
0x0F, 0xA2 ///< cpuid
}; };
STATIC STATIC
...@@ -1073,6 +1088,197 @@ typedef struct { ...@@ -1073,6 +1088,197 @@ typedef struct {
#pragma pack(pop) #pragma pack(pop)
STATIC
EFI_STATUS
PatchKernelCpuIdLegacy (
IN OUT PATCHER_CONTEXT *Patcher,
IN OC_CPU_INFO *CpuInfo,
IN UINT32 *Data,
IN UINT32 *DataMask,
IN UINT8 *Record
)
{
UINT8 *StartPointer;
UINT8 *EndPointer;
UINT8 *Location;
UINT32 Signature[3];
UINT32 Index;
UINT32 MaxExt;
INT32 Delta;
INTERNAL_CPUID_PATCH Patch;
STATIC CONST UINT8 mKernelCpuidFindLegacyStart[8] = {
0xBA, 0x04, 0x00, 0x00, 0x00, ///< mov edx, 4
0x48, 0x8D, 0x35 ///< lea rsi from lea rsi, byte_FFFFFF80006C5900
};
for (Index = 0; Index < EFI_PAGE_SIZE; ++Index, ++Record) {
if (Record[0] == mKernelCpuidFindLegacyStart[0]
&& Record[1] == mKernelCpuidFindLegacyStart[1]
&& Record[2] == mKernelCpuidFindLegacyStart[2]
&& Record[3] == mKernelCpuidFindLegacyStart[3]
&& Record[4] == mKernelCpuidFindLegacyStart[4]
&& Record[5] == mKernelCpuidFindLegacyStart[5]
&& Record[6] == mKernelCpuidFindLegacyStart[6]
&& Record[7] == mKernelCpuidFindLegacyStart[7]) {
break;
}
}
if (Index >= EFI_PAGE_SIZE) {
return EFI_NOT_FOUND;
}
StartPointer = Record + sizeof (mKernelCpuidFindLegacyStart) + sizeof (UINT32);
STATIC CONST UINT8 mKernelCpuidFindLegacyEnd[9] = {
0x00, ///< 0 from mov cs:byte_FFFFFF80006C590C, 0
0xB8, 0x00, 0x00, 0x00, 0x80, ///< mov eax, 80000000h
0x0F, 0xA2, ///< cpuid
0x89 ///< mov prefix from mov [rbp+var_40], eax
};
for (; Index < EFI_PAGE_SIZE; ++Index, ++Record) {
if (Record[0] == mKernelCpuidFindLegacyEnd[0]
&& Record[1] == mKernelCpuidFindLegacyEnd[1]
&& Record[2] == mKernelCpuidFindLegacyEnd[2]
&& Record[3] == mKernelCpuidFindLegacyEnd[3]
&& Record[4] == mKernelCpuidFindLegacyEnd[4]
&& Record[5] == mKernelCpuidFindLegacyEnd[5]
&& Record[6] == mKernelCpuidFindLegacyEnd[6]
&& Record[7] == mKernelCpuidFindLegacyEnd[7]
&& Record[8] == mKernelCpuidFindLegacyEnd[8]) {
break;
}
}
if (Index >= EFI_PAGE_SIZE) {
return EFI_NOT_FOUND;
}
EndPointer = Record + 1;
STATIC CONST UINT8 mKernelCpuidFindLegacyLoc[8] = {
0xB8, 0x01, 0x00, 0x00, 0x00, ///< mov eax, 1
0x0F, 0xA2, ///< cpuid
0x89 ///< mov prefix from mov [rbp+var_40], eax
};
for (; Index < EFI_PAGE_SIZE; ++Index, ++Record) {
if (Record[0] == mKernelCpuidFindLegacyLoc[0]
&& Record[1] == mKernelCpuidFindLegacyLoc[1]
&& Record[2] == mKernelCpuidFindLegacyLoc[2]
&& Record[3] == mKernelCpuidFindLegacyLoc[3]
&& Record[4] == mKernelCpuidFindLegacyLoc[4]
&& Record[5] == mKernelCpuidFindLegacyLoc[5]
&& Record[6] == mKernelCpuidFindLegacyLoc[6]
&& Record[7] == mKernelCpuidFindLegacyLoc[7]) {
break;
}
}
if (Index >= EFI_PAGE_SIZE) {
return EFI_NOT_FOUND;
}
Location = Record;
//
// Free 2 more bytes in the end by assigning EAX directly.
//
AsmCpuid (0x80000000, &MaxExt, NULL, NULL, NULL);
EndPointer += 2;
EndPointer[0] = 0xB8;
CopyMem (&EndPointer[1], &MaxExt, sizeof (MaxExt));
//
// Short-write CPU signature at RSI save space.
//
AsmCpuid (0, NULL, &Signature[0], &Signature[2], &Signature[1]);
for (Index = 0; Index < 3; ++Index) {
//
// mov eax, <signature>
//
*StartPointer++ = 0xB8;
CopyMem (StartPointer, &Signature[Index], sizeof (Signature[0]));
StartPointer += sizeof (Signature[0]);
//
// mov [rsi], eax
//
*StartPointer++ = 0x89;
*StartPointer++ = 0x06;
if (Index < 2) {
//
// add rsi, 4
//
*StartPointer++ = 0x48;
*StartPointer++ = 0x83;
*StartPointer++ = 0xC6;
*StartPointer++ = 0x04;
}
}
//
// Ensure that we still have room, which is within 2-byte jmp (127)
// and has at least 2-byte jmp and patch + 5-byte jmp area.
// Should have around 25 bytes here.
//
if (StartPointer >= EndPointer
|| EndPointer - StartPointer > 128
|| (UINTN) (EndPointer - StartPointer) < sizeof (INTERNAL_CPUID_PATCH) + 7) {
return EFI_OUT_OF_RESOURCES;
}
//
// Short jmp to EndPointer
//
StartPointer[0] = 0xEB;
StartPointer[1] = (UINT8) (EndPointer - StartPointer - 2);
StartPointer += 2;
//
// Workaround incorrect OSXSAVE handling, see below.
//
if (CpuInfo->CpuidVerEcx.Bits.XSAVE != 0
&& CpuInfo->CpuidVerEcx.Bits.OSXSAVE == 0
&& CpuInfo->CpuidVerEcx.Bits.AVX != 0) {
CpuInfo->CpuidVerEcx.Bits.OSXSAVE = 1;
}
//
// Jump from location to patch area.
//
Delta = (INT32) (StartPointer - (Location + 5));
*Location++ = 0xE9;
CopyMem (Location, &Delta, sizeof (Delta));
Location += sizeof (Delta);
*Location++ = 0x90;
*Location++ = 0x90;
//
// Write virtualised CPUID.
//
Patch.EaxCmd = 0xB8;
Patch.EaxVal = (Data[0] & DataMask[0]) | (CpuInfo->CpuidVerEax.Uint32 & ~DataMask[0]);
Patch.EbxCmd = 0xBB;
Patch.EbxVal = (Data[1] & DataMask[1]) | (CpuInfo->CpuidVerEbx.Uint32 & ~DataMask[1]);
Patch.EcxCmd = 0xB9;
Patch.EcxVal = (Data[2] & DataMask[2]) | (CpuInfo->CpuidVerEcx.Uint32 & ~DataMask[2]);
Patch.EdxCmd = 0xBA;
Patch.EdxVal = (Data[3] & DataMask[3]) | (CpuInfo->CpuidVerEdx.Uint32 & ~DataMask[3]);
CopyMem (StartPointer, &Patch, sizeof (Patch));
StartPointer += sizeof (Patch);
//
// Jump to the end of location (5-byte mov + 2-byte cpuid).
//
Delta = (INT32) (Location - (StartPointer + 5));
*StartPointer++ = 0xE9;
CopyMem (StartPointer, &Delta, sizeof (Delta));
return EFI_SUCCESS;
}
EFI_STATUS EFI_STATUS
PatchKernelCpuId ( PatchKernelCpuId (
IN OUT PATCHER_CONTEXT *Patcher, IN OUT PATCHER_CONTEXT *Patcher,
...@@ -1082,6 +1288,7 @@ PatchKernelCpuId ( ...@@ -1082,6 +1288,7 @@ PatchKernelCpuId (
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
UINT8 *CpuidSetInfo;
UINT8 *Record; UINT8 *Record;
UINT8 *Last; UINT8 *Last;
UINT32 Index; UINT32 Index;
...@@ -1109,12 +1316,13 @@ PatchKernelCpuId ( ...@@ -1109,12 +1316,13 @@ PatchKernelCpuId (
Last = ((UINT8 *) MachoGetMachHeader64 (&Patcher->MachContext) Last = ((UINT8 *) MachoGetMachHeader64 (&Patcher->MachContext)
+ MachoGetFileSize (&Patcher->MachContext) - EFI_PAGE_SIZE*2 - sizeof (mKernelCpuIdFindRelNew)); + MachoGetFileSize (&Patcher->MachContext) - EFI_PAGE_SIZE*2 - sizeof (mKernelCpuIdFindRelNew));
Status = PatcherGetSymbolAddress (Patcher, "_cpuid_set_info", (UINT8 **) &Record); Status = PatcherGetSymbolAddress (Patcher, "_cpuid_set_info", (UINT8 **) &CpuidSetInfo);
if (EFI_ERROR (Status) || Record >= Last) { if (EFI_ERROR (Status) || CpuidSetInfo >= Last) {
DEBUG ((DEBUG_WARN, "OCAK: Failed to locate _cpuid_set_info (%p) - %r\n", Record, Status)); DEBUG ((DEBUG_WARN, "OCAK: Failed to locate _cpuid_set_info (%p) - %r\n", CpuidSetInfo, Status));
return EFI_NOT_FOUND; return EFI_NOT_FOUND;
} }
Record = CpuidSetInfo;
FoundSize = 0; FoundSize = 0;
for (Index = 0; Index < EFI_PAGE_SIZE; ++Index, ++Record) { for (Index = 0; Index < EFI_PAGE_SIZE; ++Index, ++Record) {
...@@ -1135,6 +1343,13 @@ PatchKernelCpuId ( ...@@ -1135,6 +1343,13 @@ PatchKernelCpuId (
FoundReleaseKernel = FoundSize > 0; FoundReleaseKernel = FoundSize > 0;
if (!FoundReleaseKernel) {
Status = PatchKernelCpuIdLegacy (Patcher, CpuInfo, Data, DataMask, CpuidSetInfo);
if (!EFI_ERROR (Status)) {
return EFI_SUCCESS;
}
}
// //
// When patching the release kernel we do not allow reevaluating CPUID information, // When patching the release kernel we do not allow reevaluating CPUID information,
// which is used to report OSXSAVE availability. This causes issues with some programs, // which is used to report OSXSAVE availability. This causes issues with some programs,
......
/** @file
Copyright (C) 2019, vit9696. All rights reserved.
All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Base.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/OcAppleKernelLib.h>
#include <Library/OcMiscLib.h>
#include <Library/OcStringLib.h>
#include "PrelinkedInternal.h"
UINT32
OcParseDarwinVersion (
IN CONST CHAR8 *String
)
{
UINT32 Version;
UINT32 VersionPart;
UINT32 Index;
UINT32 Index2;
if (*String == '\0' || *String < '0' || *String > '9') {
return 0;
}
Version = 0;
for (Index = 0; Index < 3; ++Index) {
Version *= 100;
VersionPart = 0;
for (Index2 = 0; Index2 < 2; ++Index2) {
//
// Handle single digit parts, i.e. parse 1.2.3 as 010203.
//
if (*String != '.' && *String != '\0') {
VersionPart *= 10;
}
if (*String >= '0' && *String <= '9') {
VersionPart += *String++ - '0';
} else if (*String != '.' && *String != '\0') {
return 0;
}
}
Version += VersionPart;
if (*String == '.') {
++String;
}
}
return Version;
}
BOOLEAN
OcMatchDarwinVersion (
IN UINT32 CurrentVersion OPTIONAL,
IN UINT32 MinVersion OPTIONAL,
IN UINT32 MaxVersion OPTIONAL
)
{
//
// Check against min <= curr <= max.
// curr=0 -> curr=inf, max=0 -> max=inf
//
//
// Replace max inf with max known version.
//
if (MaxVersion == 0) {
MaxVersion = CurrentVersion;
}
//
// Handle curr=inf <= max=inf(?) case.
//
if (CurrentVersion == 0) {
return MaxVersion == 0;
}
//
// Handle curr=num > max=num case.
//
if (CurrentVersion > MaxVersion) {
return FALSE;
}
//
// Handle min=num > curr=num case.
//
if (CurrentVersion < MinVersion) {
return FALSE;
}
return TRUE;
}
UINT32
OcKernelReadDarwinVersion (
IN CONST UINT8 *Kernel,
IN UINT32 KernelSize
)
{
INT32 Offset;
UINT32 Index;
CHAR8 DarwinVersion[32];
UINT32 DarwinVersionInteger;
Offset = FindPattern (
(CONST UINT8 *) "Darwin Kernel Version ",
NULL,
L_STR_LEN ("Darwin Kernel Version "),
Kernel,
KernelSize,
0
);
if (Offset < 0) {
DEBUG ((DEBUG_WARN, "OCAK: Failed to determine kernel version\n"));
return 0;
}
Offset += L_STR_LEN ("Darwin Kernel Version ");
for (Index = 0; Index < ARRAY_SIZE (DarwinVersion) - 1; ++Index, ++Offset) {
if ((UINT32) Offset >= KernelSize || Kernel[Offset] == ':') {
break;
}
DarwinVersion[Index] = (CHAR8) Kernel[Offset];
}
DarwinVersion[Index] = '\0';
DarwinVersionInteger = OcParseDarwinVersion (DarwinVersion);
DEBUG ((
DEBUG_INFO,
"OCAK: Read kernel version %a (%u)\n",
DarwinVersion,
DarwinVersionInteger
));
return DarwinVersionInteger;
}
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
Link.c Link.c
CommonPatches.c CommonPatches.c
KernelCollection.c KernelCollection.c
KernelVersion.c
KxldState.c KxldState.c
PrelinkedContext.c PrelinkedContext.c
PrelinkedInternal.h PrelinkedInternal.h
......
...@@ -45,145 +45,6 @@ typedef enum KERNEL_CACHE_TYPE_ { ...@@ -45,145 +45,6 @@ typedef enum KERNEL_CACHE_TYPE_ {
CacheTypePrelinked CacheTypePrelinked
} KERNEL_CACHE_TYPE; } KERNEL_CACHE_TYPE;
STATIC
UINT32
OcParseDarwinVersion (
IN CONST CHAR8 *String
)
{
UINT32 Version;
UINT32 VersionPart;
UINT32 Index;
UINT32 Index2;
if (*String == '\0' || *String < '0' || *String > '9') {
return 0;
}
Version = 0;
for (Index = 0; Index < 3; ++Index) {
Version *= 100;
VersionPart = 0;
for (Index2 = 0; Index2 < 2; ++Index2) {
//
// Handle single digit parts, i.e. parse 1.2.3 as 010203.
//
if (*String != '.' && *String != '\0') {
VersionPart *= 10;
}
if (*String >= '0' && *String <= '9') {
VersionPart += *String++ - '0';
} else if (*String != '.' && *String != '\0') {
return 0;
}
}
Version += VersionPart;
if (*String == '.') {
++String;
}
}
return Version;
}
STATIC
BOOLEAN
OcMatchDarwinVersion (
IN UINT32 CurrentVersion,
IN UINT32 MinVersion,
IN UINT32 MaxVersion
)
{
//
// Check against min <= curr <= max.
// curr=0 -> curr=inf, max=0 -> max=inf
//
//
// Replace max inf with max known version.
//
if (MaxVersion == 0) {
MaxVersion = CurrentVersion;
}
//
// Handle curr=inf <= max=inf(?) case.
//
if (CurrentVersion == 0) {
return MaxVersion == 0;
}
//
// Handle curr=num > max=num case.
//
if (CurrentVersion > MaxVersion) {
return FALSE;
}
//
// Handle min=num > curr=num case.
//
if (CurrentVersion < MinVersion) {
return FALSE;
}
return TRUE;
}
STATIC
UINT32
OcKernelReadDarwinVersion (
IN CONST UINT8 *Kernel,
IN UINT32 KernelSize
)
{
INT32 Offset;
UINT32 Index;
CHAR8 DarwinVersion[32];
UINT32 DarwinVersionInteger;
Offset = FindPattern (
(CONST UINT8 *) "Darwin Kernel Version ",
NULL,
L_STR_LEN ("Darwin Kernel Version "),
Kernel,
KernelSize,
0
);
if (Offset < 0) {
DEBUG ((DEBUG_WARN, "OC: Failed to determine kernel version\n"));
return 0;
}
Offset += L_STR_LEN ("Darwin Kernel Version ");
for (Index = 0; Index < ARRAY_SIZE (DarwinVersion) - 1; ++Index, ++Offset) {
if ((UINT32) Offset >= KernelSize || Kernel[Offset] == ':') {
break;
}
DarwinVersion[Index] = (CHAR8) Kernel[Offset];
}
DarwinVersion[Index] = '\0';
DarwinVersionInteger = OcParseDarwinVersion (DarwinVersion);
DEBUG ((
DEBUG_INFO,
"OC: Read kernel version %a (%u)\n",
DarwinVersion,
DarwinVersionInteger
));
return DarwinVersionInteger;
}
STATIC STATIC
EFI_STATUS EFI_STATUS
OcKernelLoadKextsAndReserve ( OcKernelLoadKextsAndReserve (
......
...@@ -38,6 +38,9 @@ ...@@ -38,6 +38,9 @@
/[^\n]+\nPassed.kext injected - 0x8[^\n]+ /[^\n]+\nPassed.kext injected - 0x8[^\n]+
*/ */
STATIC BOOLEAN FailedToProcess = FALSE;
STATIC UINT32 KernelVersion = 0;
STATIC CHAR8 KextInfoPlistData[] = { STATIC CHAR8 KextInfoPlistData[] = {
0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65,
0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31,
...@@ -190,15 +193,6 @@ STATIC CHAR8 KextInfoPlistData[] = { ...@@ -190,15 +193,6 @@ STATIC CHAR8 KextInfoPlistData[] = {
0x6C, 0x69, 0x73, 0x74, 0x3E 0x6C, 0x69, 0x73, 0x74, 0x3E
}; };
extern UINT8 LiluKextData[];
extern UINT32 LiluKextDataSize;
extern CHAR8 LiluKextInfoPlistData[];
extern UINT32 LiluKextInfoPlistDataSize;
extern UINT8 VsmcKextData[];
extern UINT32 VsmcKextDataSize;
extern CHAR8 VsmcKextInfoPlistData[];
extern UINT32 VsmcKextInfoPlistDataSize;
long long current_timestamp() { long long current_timestamp() {
struct timeval te; struct timeval te;
gettimeofday(&te, NULL); // get current time gettimeofday(&te, NULL); // get current time
...@@ -207,80 +201,24 @@ long long current_timestamp() { ...@@ -207,80 +201,24 @@ long long current_timestamp() {
return milliseconds; return milliseconds;
} }
#if 0
STATIC
UINT8
IOAHCIBlockStoragePatchFind[] = {
0x41, 0x50, 0x50, 0x4C, 0x45, 0x20, 0x53, 0x53, 0x44, 0x00
};
STATIC
UINT8
IOAHCIBlockStoragePatchReplace[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
STATIC
PATCHER_GENERIC_PATCH
IOAHCIBlockStoragePatch = {
.Base = NULL, // Symbolic patch
.Find = IOAHCIBlockStoragePatchFind,
.Mask = NULL,
.Replace = IOAHCIBlockStoragePatchReplace,
.ReplaceMask = NULL,
.Size = sizeof (IOAHCIBlockStoragePatchFind),
.Count = 1,
.Skip = 0
};
#endif
#if 0
STATIC
UINT8
IOAHCIPortPatchFind[] = {
0x45, 0x78, 0x74, 0x65, 0x72, 0x6E, 0x61, 0x6C
};
STATIC
UINT8
IOAHCIPortPatchReplace[] = {
0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x61, 0x6C
};
STATIC
PATCHER_GENERIC_PATCH
IOAHCIPortPatch = {
.Base = NULL, // For symbolic patch
.Find = IOAHCIPortPatchFind,
.Mask = NULL,
.Replace = IOAHCIPortPatchReplace,
.ReplaceMask = NULL,
.Size = sizeof (IOAHCIPortPatchFind),
.Count = 1,
.Skip = 0
};
#endif
#if 0
STATIC STATIC
UINT8 UINT8
DisableAppleHDAPatchReplace[] = { DisableIOAHCIPatchReplace[] = {
0x31, 0xC0, 0xC3 // xor eax, eax ; ret 0x31, 0xC0, 0xC3 // xor eax, eax ; ret
}; };
STATIC STATIC
PATCHER_GENERIC_PATCH PATCHER_GENERIC_PATCH
DisableAppleHDAPatch = { DisableIOAHCIPatch = {
.Base = "__ZN20AppleHDACodecGeneric5probeEP9IOServicePi", .Base = "__ZN10IOAHCIPort5startEP9IOService",
.Find = NULL, .Find = NULL,
.Mask = NULL, .Mask = NULL,
.Replace = DisableAppleHDAPatchReplace, .Replace = DisableIOAHCIPatchReplace,
.ReplaceMask = NULL, .ReplaceMask = NULL,
.Size = sizeof (DisableAppleHDAPatchReplace), .Size = sizeof (DisableIOAHCIPatchReplace),
.Count = 1, .Count = 1,
.Skip = 0 .Skip = 0
}; };
#endif
STATIC STATIC
UINT8 UINT8
...@@ -290,7 +228,7 @@ DisableKernelLog[] = { ...@@ -290,7 +228,7 @@ DisableKernelLog[] = {
STATIC STATIC
PATCHER_GENERIC_PATCH PATCHER_GENERIC_PATCH
KernelPatch = { DisableIoLogPatch = {
.Base = "_IOLog", .Base = "_IOLog",
.Find = NULL, .Find = NULL,
.Mask = NULL, .Mask = NULL,
...@@ -306,78 +244,46 @@ ApplyKextPatches ( ...@@ -306,78 +244,46 @@ ApplyKextPatches (
PRELINKED_CONTEXT *Context PRELINKED_CONTEXT *Context
) )
{ {
#if 0
EFI_STATUS Status; EFI_STATUS Status;
PATCHER_CONTEXT Patcher; PATCHER_CONTEXT Patcher;
Status = PatcherInitContextFromPrelinked ( Status = PatcherInitContextFromPrelinked (
&Patcher, &Patcher,
Context, Context,
"com.apple.iokit.IOAHCIBlockStorage" "com.apple.iokit.IOAHCIFamily"
);
if (!EFI_ERROR (Status)) {
Status = PatcherApplyGenericPatch (&Patcher, &IOAHCIBlockStoragePatch);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "Failed to apply patch com.apple.iokit.IOAHCIBlockStorage - %r\n", Status));
} else {
DEBUG ((DEBUG_WARN, "Patch success com.apple.iokit.IOAHCIBlockStorage\n"));
}
} else {
DEBUG ((DEBUG_WARN, "Failed to find com.apple.iokit.IOAHCIBlockStorage - %r\n", Status));
}
Status = PatcherInitContextFromPrelinked (
&Patcher,
Context,
"com.apple.driver.AppleAHCIPort"
);
if (!EFI_ERROR (Status)) {
Status = PatcherApplyGenericPatch (&Patcher, &IOAHCIPortPatch);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "Failed to apply patch com.apple.driver.AppleAHCIPort - %r\n", Status));
} else {
DEBUG ((DEBUG_WARN, "Patch success com.apple.driver.AppleAHCIPort\n"));
}
} else {
DEBUG ((DEBUG_WARN, "Failed to find com.apple.driver.AppleAHCIPort - %r\n", Status));
}
Status = PatcherInitContextFromPrelinked (
&Patcher,
Context,
"com.apple.driver.AppleHDA"
); );
if (!EFI_ERROR (Status)) { if (!EFI_ERROR (Status)) {
Status = PatcherApplyGenericPatch (&Patcher, &DisableAppleHDAPatch); Status = PatcherApplyGenericPatch (&Patcher, &DisableIOAHCIPatch);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "Failed to apply patch com.apple.driver.AppleHDA - %r\n", Status)); DEBUG ((DEBUG_WARN, "[FAIL] Failed to apply patch com.apple.iokit.IOAHCIFamily - %r\n", Status));
FailedToProcess = TRUE;
} else { } else {
DEBUG ((DEBUG_WARN, "Patch success com.apple.driver.AppleHDA\n")); DEBUG ((DEBUG_WARN, "[OK] Patch success com.apple.iokit.IOAHCIFamily\n"));
} }
} else { } else {
DEBUG ((DEBUG_WARN, "Failed to find com.apple.driver.AppleHDA - %r\n", Status)); DEBUG ((DEBUG_WARN, "[FAIL] Failed to find com.apple.iokit.IOAHCIFamily - %r\n", Status));
FailedToProcess = TRUE;
} }
Status = PatcherInitContextFromPrelinked ( Status = PatcherInitContextFromPrelinked (
&Patcher, &Patcher,
Context, Context,
"com.apple.driver.AppleHDAController" "com.apple.iokit.IOHIDFamily"
); );
if (!EFI_ERROR (Status)) { if (!EFI_ERROR (Status)) {
Status = PatcherBlockKext (&Patcher); Status = PatcherBlockKext (&Patcher);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "Failed to block com.apple.driver.AppleHDAController - %r\n", Status)); DEBUG ((DEBUG_WARN, "[FAIL] Failed to block com.apple.iokit.IOHIDFamily - %r\n", Status));
FailedToProcess = TRUE;
} else { } else {
DEBUG ((DEBUG_WARN, "Block success com.apple.driver.AppleHDAController\n")); DEBUG ((DEBUG_WARN, "[OK] Block success com.apple.iokit.IOHIDFamily\n"));
} }
} else { } else {
DEBUG ((DEBUG_WARN, "Failed to find com.apple.driver.AppleHDAController - %r\n", Status)); DEBUG ((DEBUG_WARN, "[FAIL] Failed to find com.apple.iokit.IOHIDFamily - %r\n", Status));
FailedToProcess = TRUE;
} }
#endif
} }
VOID VOID
...@@ -396,14 +302,34 @@ ApplyKernelPatches ( ...@@ -396,14 +302,34 @@ ApplyKernelPatches (
); );
if (!EFI_ERROR (Status)) { if (!EFI_ERROR (Status)) {
Status = PatcherApplyGenericPatch (&Patcher, &KernelPatch); Status = PatcherApplyGenericPatch (&Patcher, &DisableIoLogPatch);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "[FAIL] DisableIoLogPatch kernel patch - %r\n", Status));
FailedToProcess = TRUE;
} else {
DEBUG ((DEBUG_WARN, "[OK] DisableIoLogPatch kernel patch\n"));
}
UINT32 VirtualCpuid[4] = {0, 0, 0, 0};
UINT32 VirtualCpuidMask[4] = {0xFFFFFFFF, 0, 0, 0};
OC_CPU_INFO CpuInfo;
memset(&CpuInfo, 0, sizeof(CpuInfo));
Status = PatchKernelCpuId (
&Patcher,
&CpuInfo,
VirtualCpuid,
VirtualCpuidMask
);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "Failed to apply patch kernel - %r\n", Status)); DEBUG ((DEBUG_WARN, "[FAIL] CPUID kernel patch - %r\n", Status));
FailedToProcess = TRUE;
} else { } else {
DEBUG ((DEBUG_WARN, "Patch success kernel\n")); DEBUG ((DEBUG_WARN, "[OK] CPUID kernel patch\n"));
} }
} else { } else {
DEBUG ((DEBUG_WARN, "Failed to find kernel - %r\n", Status)); DEBUG ((DEBUG_WARN, "Failed to find kernel - %r\n", Status));
FailedToProcess = TRUE;
} }
} }
...@@ -449,7 +375,6 @@ int wrap_main(int argc, char** argv) { ...@@ -449,7 +375,6 @@ int wrap_main(int argc, char** argv) {
PcdGet32 (PcdFixedDebugPrintErrorLevel) |= DEBUG_INFO; PcdGet32 (PcdFixedDebugPrintErrorLevel) |= DEBUG_INFO;
PcdGet32 (PcdDebugPrintErrorLevel) |= DEBUG_INFO; PcdGet32 (PcdDebugPrintErrorLevel) |= DEBUG_INFO;
UINT32 AllocSize; UINT32 AllocSize;
PRELINKED_CONTEXT Context; PRELINKED_CONTEXT Context;
const char *name = argc > 1 ? argv[1] : "/System/Library/PrelinkedKernels/prelinkedkernel"; const char *name = argc > 1 ? argv[1] : "/System/Library/PrelinkedKernels/prelinkedkernel";
...@@ -462,10 +387,10 @@ int wrap_main(int argc, char** argv) { ...@@ -462,10 +387,10 @@ int wrap_main(int argc, char** argv) {
UINT32 ReservedExeSize = 0; UINT32 ReservedExeSize = 0;
for (int argi = 0; argc - argi > 2; argi += 2) { for (int argi = 0; argc - argi > 2; argi += 2) {
UINT8 *TestData = LiluKextData; UINT8 *TestData = NULL;
UINT32 TestDataSize = LiluKextDataSize; UINT32 TestDataSize = 0;
CHAR8 *TestPlist = LiluKextInfoPlistData; CHAR8 *TestPlist = NULL;
UINT32 TestPlistSize = LiluKextInfoPlistDataSize; UINT32 TestPlistSize = 0;
if (argc - argi > 2) { if (argc - argi > 2) {
if (argv[argi + 2][0] == 'n' && argv[argi + 2][1] == 0) { if (argv[argi + 2][0] == 'n' && argv[argi + 2][1] == 0) {
...@@ -508,11 +433,13 @@ int wrap_main(int argc, char** argv) { ...@@ -508,11 +433,13 @@ int wrap_main(int argc, char** argv) {
"OC: Failed to fit kext %s\n", "OC: Failed to fit kext %s\n",
argv[argi + 2] argv[argi + 2]
); );
FailedToProcess = TRUE;
} }
} }
UINT32 LinkedExpansion = KcGetSegmentFixupChainsSize (ReservedExeSize); UINT32 LinkedExpansion = KcGetSegmentFixupChainsSize (ReservedExeSize);
if (LinkedExpansion == 0) { if (LinkedExpansion == 0) {
FailedToProcess = TRUE;
return -1; return -1;
} }
...@@ -532,15 +459,23 @@ int wrap_main(int argc, char** argv) { ...@@ -532,15 +459,23 @@ int wrap_main(int argc, char** argv) {
free(Prelinked); free(Prelinked);
Prelinked = NewPrelinked; Prelinked = NewPrelinked;
PrelinkedSize = NewPrelinkedSize; PrelinkedSize = NewPrelinkedSize;
printf("Sha384 is %02X%02X%02X%02X\n", Sha384[0], Sha384[1], Sha384[2], Sha384[3]); DEBUG ((DEBUG_WARN, "[OK] Sha384 is %02X%02X%02X%02X\n", Sha384[0], Sha384[1], Sha384[2], Sha384[3]));
} else { } else {
printf("Unpack fail\n"); DEBUG ((DEBUG_WARN, "[FAIL] Kernel unpack failure - %r\n", Status));
FailedToProcess = TRUE;
return -1; return -1;
} }
#if 0 KernelVersion = OcKernelReadDarwinVersion (Prelinked, PrelinkedSize);
if (KernelVersion != 0) {
DEBUG ((DEBUG_WARN, "[OK] Got version %u\n", KernelVersion));
} else {
DEBUG ((DEBUG_WARN, "[FAIL] Failed to detect version\n"));
FailedToProcess = TRUE;
}
ApplyKernelPatches (Prelinked, PrelinkedSize); ApplyKernelPatches (Prelinked, PrelinkedSize);
#endif
PATCHER_CONTEXT Patcher; PATCHER_CONTEXT Patcher;
Status = PatcherInitContextFromBuffer ( Status = PatcherInitContextFromBuffer (
...@@ -548,7 +483,12 @@ int wrap_main(int argc, char** argv) { ...@@ -548,7 +483,12 @@ int wrap_main(int argc, char** argv) {
Prelinked, Prelinked,
PrelinkedSize PrelinkedSize
); );
DEBUG ((DEBUG_ERROR, "Patcher init status %r\n", Status)); if (!EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "[OK] Patcher init success\n"));
} else {
DEBUG ((DEBUG_WARN, "[FAIL] Patcher init failure - %r\n", Status));
FailedToProcess = TRUE;
}
Status = PrelinkedContextInit (&Context, Prelinked, PrelinkedSize, AllocSize); Status = PrelinkedContextInit (&Context, Prelinked, PrelinkedSize, AllocSize);
...@@ -557,14 +497,14 @@ int wrap_main(int argc, char** argv) { ...@@ -557,14 +497,14 @@ int wrap_main(int argc, char** argv) {
Status = PrelinkedInjectPrepare (&Context, LinkedExpansion, ReservedExeSize); Status = PrelinkedInjectPrepare (&Context, LinkedExpansion, ReservedExeSize);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "Prelink inject prepare error %r\n", Status)); DEBUG ((DEBUG_WARN, "[FAIL] Prelink inject prepare error %r\n", Status));
FailedToProcess = TRUE;
return -1; return -1;
} }
#ifndef TEST_SLE
Status = PrelinkedInjectKext ( Status = PrelinkedInjectKext (
&Context, &Context,
"/Library/Extensions/TestDriver.kext", "/Library/Extensions/PlistKext.kext",
KextInfoPlistData, KextInfoPlistData,
sizeof (KextInfoPlistData), sizeof (KextInfoPlistData),
NULL, NULL,
...@@ -572,16 +512,20 @@ int wrap_main(int argc, char** argv) { ...@@ -572,16 +512,20 @@ int wrap_main(int argc, char** argv) {
0 0
); );
DEBUG ((DEBUG_WARN, "TestDriver.kext injected - %r\n", Status)); if (!EFI_ERROR (Status)) {
#endif DEBUG ((DEBUG_WARN, "[OK] PlistKext.kext injected - %r\n", Status));
} else {
DEBUG ((DEBUG_WARN, "[FAIL] PlistKext.kext injected - %r\n", Status));
FailedToProcess = TRUE;
}
int c = 0; int c = 0;
while (argc > 2) { while (argc > 2) {
UINT8 *TestData = LiluKextData; UINT8 *TestData = NULL;
UINT32 TestDataSize = LiluKextDataSize; UINT32 TestDataSize = 0;
CHAR8 *TestPlist = LiluKextInfoPlistData; CHAR8 *TestPlist = NULL;
UINT32 TestPlistSize = LiluKextInfoPlistDataSize; UINT32 TestPlistSize = 0;
if (argc > 2) { if (argc > 2) {
if (argv[2][0] == 'n' && argv[2][1] == 0) { if (argv[2][0] == 'n' && argv[2][1] == 0) {
...@@ -619,7 +563,12 @@ int wrap_main(int argc, char** argv) { ...@@ -619,7 +563,12 @@ int wrap_main(int argc, char** argv) {
TestDataSize TestDataSize
); );
DEBUG ((DEBUG_WARN, "%a injected - %r\n", argc > 2 ? "Passed.kext" : "Lilu.kext", Status)); if (!EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "[OK] %a injected - %r\n", argv[2], Status));
} else {
DEBUG ((DEBUG_WARN, "[FAIL] %a injected - %r\n", argv[2], Status));
FailedToProcess = TRUE;
}
if (argc > 2) free(TestData); if (argc > 2) free(TestData);
if (argc > 3) free(TestPlist); if (argc > 3) free(TestPlist);
...@@ -630,37 +579,22 @@ int wrap_main(int argc, char** argv) { ...@@ -630,37 +579,22 @@ int wrap_main(int argc, char** argv) {
} }
ASSERT (Context.PrelinkedSize - Context.KextsFileOffset <= ReservedExeSize); ASSERT (Context.PrelinkedSize - Context.KextsFileOffset <= ReservedExeSize);
#ifndef TEST_SLE
if (argc <= 2) {
Status = PrelinkedInjectKext (
&Context,
"/Library/Extensions/VirtualSMC.kext",
VsmcKextInfoPlistData,
VsmcKextInfoPlistDataSize,
"Contents/MacOS/VirtualSMC",
VsmcKextData,
VsmcKextDataSize
);
DEBUG ((DEBUG_WARN, "VirtualSMC.kext injected - %r\n", Status));
}
Status = PrelinkedInjectComplete (&Context); Status = PrelinkedInjectComplete (&Context);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "Prelink inject complete error %r\n", Status));
}
writeFile("out.bin", Prelinked, Context.PrelinkedSize); writeFile("out.bin", Prelinked, Context.PrelinkedSize);
if (!EFI_ERROR (Status)) { if (!EFI_ERROR (Status)) {
printf("All good\n"); DEBUG ((DEBUG_WARN, "[OK] Prelink inject complete success\n"));
} else { } else {
printf("Inject error\n"); DEBUG ((DEBUG_WARN, "[FAIL] Prelink inject complete error %r\n", Status));
FailedToProcess = TRUE;
} }
#endif
PrelinkedContextFree (&Context); PrelinkedContextFree (&Context);
} else { } else {
DEBUG ((DEBUG_WARN, "Context creation error %r\n", Status)); DEBUG ((DEBUG_WARN, "[FAIL] Context creation error %r\n", Status));
FailedToProcess = TRUE;
} }
free(Prelinked); free(Prelinked);
...@@ -708,8 +642,8 @@ INT32 LLVMFuzzerTestOneInput(CONST UINT8 *Data, UINTN Size) { ...@@ -708,8 +642,8 @@ INT32 LLVMFuzzerTestOneInput(CONST UINT8 *Data, UINTN Size) {
Status = PrelinkedInjectKext ( Status = PrelinkedInjectKext (
&Context, &Context,
"/Library/Extensions/Lilu.kext", "/Library/Extensions/Lilu.kext",
LiluKextInfoPlistData, KextInfoPlistData, ///< FIXME: has no executable
LiluKextInfoPlistDataSize, sizeof (KextInfoPlistData),
"Contents/MacOS/Lilu", "Contents/MacOS/Lilu",
Data, Data,
Size Size
...@@ -723,8 +657,9 @@ INT32 LLVMFuzzerTestOneInput(CONST UINT8 *Data, UINTN Size) { ...@@ -723,8 +657,9 @@ INT32 LLVMFuzzerTestOneInput(CONST UINT8 *Data, UINTN Size) {
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
for (size_t i = 0; i < 1; i++) { int code = wrap_main(argc, argv);
wrap_main(argc, argv); if (FailedToProcess) {
code = -1;
} }
return 0; return code;
} }
此差异已折叠。
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
PROJECT = KextInject PROJECT = KextInject
PRODUCT = $(PROJECT)$(SUFFIX) PRODUCT = $(PROJECT)$(SUFFIX)
OBJS = $(PROJECT).o \ OBJS = $(PROJECT).o \
Lilu.o \ CommonPatches.o \
Vsmc.o \ KernelVersion.o \
KextPatcher.o \ KextPatcher.o \
KxldState.o \ KxldState.o \
PrelinkedKext.o \ PrelinkedKext.o \
......
此差异已折叠。
#!/bin/bash
abort() {
echo "$1"
exit 1
}
if [ ! -x "KextInject" ]; then
abort "Please compile KextInject"
fi
if [ ! -d "$1" ]; then
abort "Please pass a directory with caches!"
fi
ARCH=x86_64
DIR="$1"
CODE=0
shift
for dir in "${DIR}"/*/ ; do
for file in kernelcache prelinkedkernel immutablekernel BootKernelExtensions.kc; do
for resulting in ${file} ${file}_unpack ${file}_${ARCH} ${file}_${ARCH}_unpack; do
if [ ! -f "${dir}${resulting}" ]; then
continue
fi
printf "%s%s - " "${dir}" "${resulting}"
ok=true
echo "./KextInject ${dir}${resulting} ${*}" > "${dir}${resulting}.log"
./KextInject "${dir}${resulting}" "${@}" >> "${dir}${resulting}.log" || ok=false
if $ok; then
echo "OK"
else
echo "FAIL"
CODE=-1
fi
done
done
done
exit $CODE
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册