implemented patch with mask for kext, kernel and booter

This commit is contained in:
Sergey Isakov 2019-10-08 23:57:18 +03:00
parent 98cf33977d
commit be7ab87dca
6 changed files with 178 additions and 78 deletions

View File

@ -420,10 +420,14 @@
<true/>
<key>Find</key>
<data>igKEwHRC</data>
<key>MaskFind</key>
<data>////////</data>
<key>MatchOS</key>
<string>10.14</string>
<key>Replace</key>
<data>igKEwOtC</data>
<key>MaskReplace</key>
<data>AAAAAP8A</data>
</dict>
<dict>
<key>Comment</key>
@ -460,6 +464,8 @@
<string>VoodooHDA</string>
<key>Replace</key>
<data>VGVsZXBob25lcwA=</data>
<key>MaskReplace</key>
<data>/////wAAAAAAAAA=</data>
</dict>
<dict>
<key>Find</key>

View File

@ -836,6 +836,16 @@ CopyKernelAndKextPatches (IN OUT KERNEL_AND_KEXT_PATCHES *Dst,
Dst->KernelPatches[Dst->NrKernels].Count = Src->KernelPatches[i].Count;
Dst->KernelPatches[Dst->NrKernels].MatchOS = AllocateCopyPool (AsciiStrSize(Src->KernelPatches[i].MatchOS), Src->KernelPatches[i].MatchOS);
Dst->KernelPatches[Dst->NrKernels].MatchBuild = AllocateCopyPool (AsciiStrSize(Src->KernelPatches[i].MatchBuild), Src->KernelPatches[i].MatchBuild);
if (Src->KernelPatches[i].MaskFind != NULL) {
Dst->KernelPatches[Dst->NrKernels].MaskFind = AllocateCopyPool (Src->KernelPatches[i].DataLen, Src->KernelPatches[i].MaskFind);
} else {
Dst->KernelPatches[Dst->NrKernels].MaskFind = NULL;
}
if (Src->KernelPatches[i].MaskReplace != NULL) {
Dst->KernelPatches[Dst->NrKernels].MaskReplace = AllocateCopyPool (Src->KernelPatches[i].DataLen, Src->KernelPatches[i].MaskReplace);
} else {
Dst->KernelPatches[Dst->NrKernels].MaskReplace = NULL;
}
++(Dst->NrKernels);
}
}
@ -1069,22 +1079,17 @@ FillinKextPatches (IN OUT KERNEL_AND_KEXT_PATCHES *Patches,
if (Patches->KextPatches) {
Patches->NrKexts = 0;
FreePool (Patches->KextPatches);
Patches->KextPatches = NULL;
}
if (Count > 0) {
TagPtr Prop2 = NULL, Dict = NULL;
KEXT_PATCH *newPatches = AllocateZeroPool (Count * sizeof(KEXT_PATCH));
// Patches->NrKexts = 0;
/* if (Patches->KextPatches != NULL) {
CopyMem (newPatches, Patches->KextPatches, (Patches->NrKexts * sizeof(KEXT_PATCH)));
FreePool (Patches->KextPatches);
} */
Patches->KextPatches = newPatches;
DBG ("KextsToPatch: %d requested\n", Count);
for (i = 0; i < Count; i++) {
CHAR8 *KextPatchesName, *KextPatchesLabel;
UINTN FindLen = 0, ReplaceLen = 0;
UINTN FindLen = 0, ReplaceLen = 0, MaskLen = 0;
UINT8 *TmpData, *TmpPatch;
EFI_STATUS Status = GetElement (Prop, i, &Prop2);
if (EFI_ERROR (Status)) {
@ -1095,7 +1100,6 @@ FillinKextPatches (IN OUT KERNEL_AND_KEXT_PATCHES *Patches,
if (Prop2 == NULL) {
break;
}
DBG (" - [%02d]:", i);
Dict = GetProperty (Prop2, "Name");
@ -1119,14 +1123,11 @@ FillinKextPatches (IN OUT KERNEL_AND_KEXT_PATCHES *Patches,
} else {
AsciiStrCatS(KextPatchesLabel, 255, " (NoLabel)");
}
DBG (" %a", KextPatchesLabel);
Patches->KextPatches[Patches->NrKexts].MenuItem.BValue = TRUE;
Dict = GetProperty (Prop2, "Disabled");
if ((Dict != NULL) && IsPropertyTrue (Dict)) {
Patches->KextPatches[Patches->NrKexts].MenuItem.BValue = FALSE;
}
@ -1140,15 +1141,35 @@ FillinKextPatches (IN OUT KERNEL_AND_KEXT_PATCHES *Patches,
Patches->KextPatches[Patches->NrKexts].Data = AllocateCopyPool (FindLen, TmpData);
Patches->KextPatches[Patches->NrKexts].DataLen = FindLen;
FreePool(TmpData);
TmpData = GetDataSetting (Prop2, "MaskFind", &MaskLen);
MaskLen = (MaskLen > FindLen)? FindLen : MaskLen;
if (TmpData == NULL || MaskLen == 0) {
Patches->KextPatches[Patches->NrKexts].MaskFind = NULL;
} else {
Patches->KextPatches[Patches->NrKexts].MaskFind = AllocateZeroPool (FindLen);
CopyMem(Patches->KextPatches[Patches->NrKexts].MaskFind, TmpData, MaskLen);
}
FreePool(TmpData);
Patches->KextPatches[Patches->NrKexts].Patch = AllocateCopyPool (FindLen, TmpPatch);
FreePool(TmpPatch);
MaskLen = 0;
TmpData = GetDataSetting (Prop2, "MaskReplace", &MaskLen);
MaskLen = (MaskLen > FindLen)? FindLen : MaskLen;
if (TmpData == NULL || MaskLen == 0) {
Patches->KextPatches[Patches->NrKexts].MaskReplace = NULL;
} else {
Patches->KextPatches[Patches->NrKexts].MaskReplace = AllocateZeroPool (FindLen);
CopyMem(Patches->KextPatches[Patches->NrKexts].MaskReplace, TmpData, MaskLen);
}
FreePool(TmpData);
Patches->KextPatches[Patches->NrKexts].MatchOS = NULL;
Patches->KextPatches[Patches->NrKexts].MatchBuild = NULL;
Patches->KextPatches[Patches->NrKexts].Name = AllocateCopyPool (AsciiStrSize(KextPatchesName), KextPatchesName);
Patches->KextPatches[Patches->NrKexts].Label = AllocateCopyPool (AsciiStrSize(KextPatchesLabel), KextPatchesLabel);
FreePool(TmpData);
FreePool(TmpPatch);
FreePool(KextPatchesName);
Patches->KextPatches[Patches->NrKexts].Label = AllocateCopyPool (AsciiStrSize(KextPatchesLabel), KextPatchesLabel);
FreePool(KextPatchesLabel);
// check enable/disabled patch (OS based) by Micky1979
@ -1203,7 +1224,7 @@ FillinKextPatches (IN OUT KERNEL_AND_KEXT_PATCHES *Patches,
DBG ("KernelToPatch: %d requested\n", Count);
for (i = 0; i < Count; i++) {
CHAR8 *KernelPatchesLabel;
UINTN FindLen = 0, ReplaceLen = 0;
UINTN FindLen = 0, ReplaceLen = 0, MaskLen = 0;
UINT8 *TmpData, *TmpPatch;
EFI_STATUS Status = GetElement (Prop, i, &Prop2);
if (EFI_ERROR (Status)) {
@ -1214,7 +1235,6 @@ FillinKextPatches (IN OUT KERNEL_AND_KEXT_PATCHES *Patches,
if (Prop2 == NULL) {
break;
}
DBG (" - [%02d]:", i);
Dict = GetProperty (Prop2, "Comment");
@ -1223,15 +1243,9 @@ FillinKextPatches (IN OUT KERNEL_AND_KEXT_PATCHES *Patches,
} else {
KernelPatchesLabel = AllocateCopyPool (8, "NoLabel");
}
DBG (" %a", KernelPatchesLabel);
//Patches->KernelPatches[Patches->NrKernels].MenuItem.BValue = TRUE;
Dict = GetProperty (Prop2, "Disabled");
/* if ((Dict != NULL) && IsPropertyTrue (Dict)) {
DBG(" :: patch disabled\n");
Patches->KernelPatches[Patches->NrKernels].MenuItem.BValue = FALSE;
} */
Patches->KernelPatches[Patches->NrKernels].MenuItem.BValue = !IsPropertyTrue (Dict);
TmpData = GetDataSetting (Prop2, "Find", &FindLen);
@ -1244,7 +1258,27 @@ FillinKextPatches (IN OUT KERNEL_AND_KEXT_PATCHES *Patches,
Patches->KernelPatches[Patches->NrKernels].Data = AllocateCopyPool (FindLen, TmpData);
Patches->KernelPatches[Patches->NrKernels].DataLen = FindLen;
FreePool(TmpData);
TmpData = GetDataSetting (Prop2, "MaskFind", &MaskLen);
MaskLen = (MaskLen > FindLen)? FindLen : MaskLen;
if (TmpData == NULL || MaskLen == 0) {
Patches->KernelPatches[Patches->NrKexts].MaskFind = NULL;
} else {
Patches->KernelPatches[Patches->NrKexts].MaskFind = AllocateZeroPool (FindLen);
CopyMem(Patches->KernelPatches[Patches->NrKexts].MaskFind, TmpData, MaskLen);
}
FreePool(TmpData);
Patches->KernelPatches[Patches->NrKernels].Patch = AllocateCopyPool (FindLen, TmpPatch);
FreePool(TmpPatch);
TmpData = GetDataSetting (Prop2, "MaskReplace", &MaskLen);
MaskLen = (MaskLen > FindLen)? FindLen : MaskLen;
if (TmpData == NULL || MaskLen == 0) {
Patches->KernelPatches[Patches->NrKexts].MaskReplace = NULL;
} else {
Patches->KernelPatches[Patches->NrKexts].MaskReplace = AllocateZeroPool (FindLen);
CopyMem(Patches->KernelPatches[Patches->NrKexts].MaskReplace, TmpData, MaskLen);
}
FreePool(TmpData);
Patches->KernelPatches[Patches->NrKernels].Count = 0;
Patches->KernelPatches[Patches->NrKernels].MatchOS = NULL;
Patches->KernelPatches[Patches->NrKernels].MatchBuild = NULL;
@ -1254,9 +1288,6 @@ FillinKextPatches (IN OUT KERNEL_AND_KEXT_PATCHES *Patches,
if (Dict != NULL) {
Patches->KernelPatches[Patches->NrKernels].Count = GetPropertyInteger (Dict, 0);
}
FreePool(TmpData);
FreePool(TmpPatch);
FreePool(KernelPatchesLabel);
// check enable/disabled patch (OS based) by Micky1979
@ -1271,7 +1302,6 @@ FillinKextPatches (IN OUT KERNEL_AND_KEXT_PATCHES *Patches,
Patches->KernelPatches[Patches->NrKernels].MatchBuild = AllocateCopyPool (AsciiStrSize (Dict->string), Dict->string);
DBG(" :: MatchBuild: %a", Patches->KernelPatches[Patches->NrKernels].MatchBuild);
}
DBG (" :: data len: %d\n", Patches->KernelPatches[Patches->NrKernels].DataLen);
Patches->NrKernels++;
}
@ -1283,6 +1313,7 @@ FillinKextPatches (IN OUT KERNEL_AND_KEXT_PATCHES *Patches,
INTN i, Count = GetTagCount (Prop);
//delete old and create new
if (Patches->BootPatches) {
//TODO - free all subtree
Patches->NrBoots = 0;
FreePool (Patches->BootPatches);
}
@ -1294,18 +1325,16 @@ FillinKextPatches (IN OUT KERNEL_AND_KEXT_PATCHES *Patches,
DBG ("BootPatches: %d requested\n", Count);
for (i = 0; i < Count; i++) {
CHAR8 *BootPatchesLabel;
UINTN FindLen = 0, ReplaceLen = 0;
UINTN FindLen = 0, ReplaceLen = 0, MaskLen = 0;
UINT8 *TmpData, *TmpPatch;
EFI_STATUS Status = GetElement (Prop, i, &Prop2);
if (EFI_ERROR (Status)) {
DBG (" - [%02d]: error %r getting next element\n", i, Status);
continue;
}
if (Prop2 == NULL) {
break;
}
DBG (" - [%02d]:", i);
Dict = GetProperty (Prop2, "Comment");
@ -1323,7 +1352,6 @@ FillinKextPatches (IN OUT KERNEL_AND_KEXT_PATCHES *Patches,
TmpData = GetDataSetting (Prop2, "Find", &FindLen);
TmpPatch = GetDataSetting (Prop2, "Replace", &ReplaceLen);
if (!FindLen || !ReplaceLen || (FindLen != ReplaceLen)) {
DBG (" :: invalid Find/Replace data - skipping!\n");
continue;
@ -1331,7 +1359,27 @@ FillinKextPatches (IN OUT KERNEL_AND_KEXT_PATCHES *Patches,
Patches->BootPatches[Patches->NrBoots].Data = AllocateCopyPool (FindLen, TmpData);
Patches->BootPatches[Patches->NrBoots].DataLen = FindLen;
FreePool(TmpData);
TmpData = GetDataSetting (Prop2, "MaskFind", &MaskLen);
MaskLen = (MaskLen > FindLen)? FindLen : MaskLen;
if (TmpData == NULL || MaskLen == 0) {
Patches->BootPatches[Patches->NrKexts].MaskFind = NULL;
} else {
Patches->BootPatches[Patches->NrKexts].MaskFind = AllocateZeroPool (FindLen);
CopyMem(Patches->BootPatches[Patches->NrKexts].MaskFind, TmpData, MaskLen);
}
FreePool(TmpData);
Patches->BootPatches[Patches->NrBoots].Patch = AllocateCopyPool (FindLen, TmpPatch);
FreePool(TmpPatch);
TmpData = GetDataSetting (Prop2, "MaskReplace", &MaskLen);
MaskLen = (MaskLen > FindLen)? FindLen : MaskLen;
if (TmpData == NULL || MaskLen == 0) {
Patches->BootPatches[Patches->NrKexts].MaskReplace = NULL;
} else {
Patches->BootPatches[Patches->NrKexts].MaskReplace = AllocateZeroPool (FindLen);
CopyMem(Patches->BootPatches[Patches->NrKexts].MaskReplace, TmpData, MaskLen);
}
FreePool(TmpData);
Patches->BootPatches[Patches->NrBoots].Count = 0;
Patches->BootPatches[Patches->NrBoots].MatchOS = NULL;
Patches->BootPatches[Patches->NrBoots].MatchBuild = NULL;
@ -1341,9 +1389,6 @@ FillinKextPatches (IN OUT KERNEL_AND_KEXT_PATCHES *Patches,
if (Dict != NULL) {
Patches->BootPatches[Patches->NrBoots].Count = GetPropertyInteger (Dict, 0);
}
FreePool(TmpData);
FreePool(TmpPatch);
FreePool(BootPatchesLabel);
Dict = GetProperty (Prop2, "MatchOS");
@ -6192,8 +6237,8 @@ GetUserSettings(
Status = GetElement (Prop, i, &Dict);
if (!EFI_ERROR(Status)) {
Prop2 = GetProperty (Dict, "Comment");
if (Prop2 && Prop2->string) {
DBG(" %a\n", Prop2->string);
if (Prop2 && Prop2->string) {
DBG(" %a\n", Prop2->string);
}
Prop2 = GetProperty(Dict, "Disabled");
if (IsPropertyFalse(Prop2)) {

View File

@ -1732,28 +1732,16 @@ KernelUserPatch(IN UINT8 *UKernelData, LOADER_ENTRY *Entry)
continue;
}
#if 0 //!defined(FKERNELPATCH)
Num = SearchAndCount(
UKernelData,
KERNEL_MAX_SIZE,
Entry->KernelAndKextPatches->KernelPatches[i].Data,
Entry->KernelAndKextPatches->KernelPatches[i].DataLen
);
if (!Num) {
DBG_RT(Entry, "==> pattern(s) not found.\n");
continue;
}
#endif //FKERNELPATCH
Num = SearchAndReplace(
UKernelData,
KERNEL_MAX_SIZE,
Entry->KernelAndKextPatches->KernelPatches[i].Data,
Entry->KernelAndKextPatches->KernelPatches[i].DataLen,
Entry->KernelAndKextPatches->KernelPatches[i].Patch,
Entry->KernelAndKextPatches->KernelPatches[i].Count
);
Num = SearchAndReplaceMask(
UKernelData,
KERNEL_MAX_SIZE,
Entry->KernelAndKextPatches->KernelPatches[i].Data,
Entry->KernelAndKextPatches->KernelPatches[i].MaskFind,
Entry->KernelAndKextPatches->KernelPatches[i].DataLen,
Entry->KernelAndKextPatches->KernelPatches[i].Patch,
Entry->KernelAndKextPatches->KernelPatches[i].MaskReplace,
Entry->KernelAndKextPatches->KernelPatches[i].Count
);
if (Num) {
y++;
@ -1779,14 +1767,16 @@ BooterPatch(IN UINT8 *BooterData, IN UINT64 BooterSize, LOADER_ENTRY *Entry)
continue;
}
Num = SearchAndReplace(
BooterData,
BooterSize,
Entry->KernelAndKextPatches->BootPatches[i].Data,
Entry->KernelAndKextPatches->BootPatches[i].DataLen,
Entry->KernelAndKextPatches->BootPatches[i].Patch,
Entry->KernelAndKextPatches->BootPatches[i].Count
);
Num = SearchAndReplaceMask(
BooterData,
BooterSize,
Entry->KernelAndKextPatches->BootPatches[i].Data,
Entry->KernelAndKextPatches->BootPatches[i].MaskFind,
Entry->KernelAndKextPatches->BootPatches[i].DataLen,
Entry->KernelAndKextPatches->BootPatches[i].Patch,
Entry->KernelAndKextPatches->BootPatches[i].MaskReplace,
Entry->KernelAndKextPatches->BootPatches[i].Count
);
if (Num) {
y++;

View File

@ -149,5 +149,6 @@ UINTN SearchAndCount(UINT8 *Source, UINT64 SourceSize, UINT8 *Search, UINTN Sear
//
UINTN SearchAndReplace(UINT8 *Source, UINT64 SourceSize, UINT8 *Search, UINTN SearchSize, UINT8 *Replace, INTN MaxReplaces);
UINTN SearchAndReplaceMask(UINT8 *Source, UINT64 SourceSize, UINT8 *Search, UINT8 *MaskSearch, UINTN SearchSize, UINT8 *Replace, UINT8 *MaskReplace, INTN MaxReplaces);
#endif /* !__LIBSAIO_KERNEL_PATCHER_H */

View File

@ -69,6 +69,62 @@ UINTN SearchAndReplace(UINT8 *Source, UINT64 SourceSize, UINT8 *Search, UINTN Se
return NumReplaces;
}
BOOLEAN CompareMemMask(UINT8 *Source, UINT8 *Search, UINT8 *Mask, UINTN SearchSize)
{
UINT8 M;
UINTN Ind;
if (!Mask) {
return !CompareMem(Source, Search, SearchSize);
}
for (Ind = 0; Ind < SearchSize; Ind++) {
M = *Mask++;
if ((*Source++ & M) != (*Search++ & M)) {
return FALSE;
}
}
return TRUE;
}
VOID CopyMemMask(UINT8 *Dest, UINT8 *Replace, UINT8 *Mask, UINTN SearchSize)
{
UINT8 M, D;
UINTN Ind;
if (!Mask) {
CopyMem(Dest, Replace, SearchSize);
return;
}
for (Ind = 0; Ind < SearchSize; Ind++) {
M = *Mask++;
D = *Dest;
*Dest++ = (((D ^ *Replace++) & M) ^ D) ^ M;
}
}
UINTN SearchAndReplaceMask(UINT8 *Source, UINT64 SourceSize, UINT8 *Search, UINT8 *MaskSearch, UINTN SearchSize,
UINT8 *Replace, UINT8 *MaskReplace, INTN MaxReplaces)
{
UINTN NumReplaces = 0;
BOOLEAN NoReplacesRestriction = MaxReplaces <= 0;
UINT8 *End = Source + SourceSize;
if (!Source || !Search || !Replace || !SearchSize) {
return 0;
}
while ((Source < End) && (NoReplacesRestriction || (MaxReplaces > 0))) {
if (CompareMemMask(Source, Search, MaskSearch, SearchSize)) {
CopyMemMask(Source, Replace, MaskReplace, SearchSize);
NumReplaces++;
MaxReplaces--;
Source += SearchSize;
} else {
Source++;
}
}
return NumReplaces;
}
UINTN SearchAndReplaceTxt(UINT8 *Source, UINT64 SourceSize, UINT8 *Search, UINTN SearchSize, UINT8 *Replace, INTN MaxReplaces)
{
UINTN NumReplaces = 0;
@ -449,7 +505,7 @@ VOID AppleRTCPatch(UINT8 *Driver, UINT32 DriverSize, CHAR8 *InfoPlist, UINT32 In
if (NumLion_X64 + NumLion_i386 + NumML + NumMavMoj3 + NumMoj4 > 1) {
// more then one pattern found - we do not know what to do with it
// and we'll skipp it
// and we'll skip it
Print(L"AppleRTCPatch: ERROR: multiple patterns found (LionX64: %d, Lioni386: %d, ML: %d, MavMoj3: %d, Moj4: %d) - skipping patching!\n",
NumLion_X64, NumLion_i386, NumML, NumMavMoj3, NumMoj4);
gBS->Stall(5000000);
@ -916,12 +972,14 @@ VOID AnyKextPatch(UINT8 *Driver, UINT32 DriverSize, CHAR8 *InfoPlist, UINT32 Inf
if (!Entry->KernelAndKextPatches->KextPatches[N].IsPlistPatch) {
// kext binary patch
DBG_RT(Entry, "Binary patch\n");
Num = SearchAndReplace(Driver,
DriverSize,
Entry->KernelAndKextPatches->KextPatches[N].Data,
Entry->KernelAndKextPatches->KextPatches[N].DataLen,
Entry->KernelAndKextPatches->KextPatches[N].Patch,
-1);
Num = SearchAndReplaceMask(Driver,
DriverSize,
Entry->KernelAndKextPatches->KextPatches[N].Data,
Entry->KernelAndKextPatches->KextPatches[N].MaskFind,
Entry->KernelAndKextPatches->KextPatches[N].DataLen,
Entry->KernelAndKextPatches->KextPatches[N].Patch,
Entry->KernelAndKextPatches->KextPatches[N].MaskReplace,
-1);
} else {
// Info plist patch
DBG_RT(Entry, "Info.plist data : '");

View File

@ -541,12 +541,11 @@ struct KEXT_PATCH
#endif
UINT8 *Data;
UINT8 *Patch;
UINT8 *MaskFind;
UINT8 *MaskReplace;
CHAR8 *MatchOS;
CHAR8 *MatchBuild;
// KEXT_PATCH *Next;
// UINT64 Index;
INPUT_ITEM MenuItem; //zzzz
// BOOLEAN Disabled;
INPUT_ITEM MenuItem;
};
typedef struct {
@ -554,11 +553,12 @@ typedef struct {
INTN DataLen;
UINT8 *Data;
UINT8 *Patch;
UINT8 *MaskFind;
UINT8 *MaskReplace;
INTN Count;
CHAR8 *MatchOS;
CHAR8 *MatchBuild;
INPUT_ITEM MenuItem;
// BOOLEAN Disabled;
} KERNEL_PATCH;
typedef struct KERNEL_AND_KEXT_PATCHES