Closed DecoderCoder closed 1 year ago
You're right that this isn't really an EfiGuard issue, but it's fine.
I don't really see any issues with your code, other than being unnecessarily verbose. NtBuildNumber
is exported, so if you want to change it you can just do this instead:
UINT8* NtBuildNumberAddress = GetProcedureAddress((UINTN)ImageBase, NtHeaders, "NtBuildNumber");
CONST UINT32 NewBuildNumber = *(UINT32*)NtBuildNumberAddress + 1;
CopyWpMem(NtBuildNumberAddress, &NewBuildNumber, sizeof(NewBuildNumber));
(Note that NtBuildNumber
is a 32 bit value, not 16.)
There is no need to modify RtlGetVersion
or MmCreatePeb
since they already reference NtBuildNumber
.
However, this does not prevent the kernel from writing the original build number to SharedUserData->NtBuildNumber
, because the instruction that does this uses a hardcoded value. See InitBootProcessor
:
mov rcx, MmWriteableSharedUserData
; ...snip...
mov dword ptr [rcx+0x260], 0x585D ; for build 22621
Additionally, there is a new registry key since Windows 11 that may contain a replacement build number. This registry key is located at HKLM\SYSTEM\Software\Microsoft\BuildLayers
and contains several sub-keys, each of which may specify a BuildNumber
which will be used to update SharedUserData->NtBuildNumber
later during boot. See CmpLoadSystemVersionData
:
or eax, 0xF0000000
mov NtBuildNumber, eax
mov rax, MmWriteableSharedUserData
mov ecx, [rdx+8] ; *(uint32_t*)(CmpEditionVersion + 8)
mov [rax+0x260], ecx
If you want the SharedUserData->NtBuildNumber
value to match the kernel's NtBuildNumber
in .data
, you will need to do something about these two functions. By far the easiest way is to simply change the value in the registry. If that's not an option, you will need to patch at least one of the two occurrences (which one depends on whether the registry key is present or not).
Also, if the registry key is present, it will be used to update NtBuildNumber
again as you can see.
Note that I couldn't reproduce the PEB build number not changing; for me the first three lines of code to update NtBuildNumber
suffice to change the build number in the PEB.
Thank for answer, I've already know about InitBootProcessor and patching it. Didn't know about SharedUserData. I will try and post the result
I patching it successfully, but in windows doesn't matter about my patches 👍 like it upload some sections after load
Code for quick test
STATIC CONST UINT8 SigInitBootProcessor[] = {
0xC7, 0x81, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,0xCC,0xCC,0xC7,0x41,0xCC,0xCC,0xCC,0xCC,0xCC
};
///
UINT8* InitBootProcessorAddress = NULL;
{
PRINT_KERNEL_PATCH_MSG(L"== Searching for nt!InitBootProcessor pattern in PAGE ==\r\n");
EFI_STATUS FindInitBootProcessor = FindPattern(SigInitBootProcessor,
0xCC,
sizeof(SigInitBootProcessor),
ImageBase + InitSection->VirtualAddress,
InitSection->SizeOfRawData,
(VOID**)&InitBootProcessorAddress);
if (EFI_ERROR(FindInitBootProcessor))
{
PRINT_KERNEL_PATCH_MSG(L" Failed to find InitBootProcessor. Skipping patch.\r\n");
}
else {
PRINT_KERNEL_PATCH_MSG(L" Found InitBootProcessor pattern at 0x%llX.\r\n", (UINTN)InitBootProcessorAddress);
}
}
if (InitBootProcessorAddress) {
short newWinBuildNumber = 24000;
CopyWpMem(InitBootProcessorAddress + 6, &newWinBuildNumber, sizeof(short));
PRINT_KERNEL_PATCH_MSG(L" Patched InitBootProcessor [RVA: 0x%X]\r\n", (UINT32)(InitBootProcessorAddress - ImageBase));
}
UINT8* NtBuildNumberAddress = GetProcedureAddress((UINTN)ImageBase, NtHeaders, "NtBuildNumber");
if (NtBuildNumberAddress != NULL) {
CONST UINT32 NewBuildNumber = 24000;
CopyWpMem(NtBuildNumberAddress, &NewBuildNumber, sizeof(NewBuildNumber));
PRINT_KERNEL_PATCH_MSG(L" Patched NtBuildNumberAddress [RVA: 0x%X]\r\n", (UINT32)(NtBuildNumberAddress - ImageBase));
}
else {
PRINT_KERNEL_PATCH_MSG(L" Failed to find NtBuildNumberAddress");
}
Im idiot forgot about CmpLoadSystemVersionData
STATIC CONST UINT8 SigCmpLoadSystemVersionData[] = {
0x48, 0x83, 0x3D, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x74, 0x6A
};
//----------------------
UINT8* CmpLoadSystemVersionDataAddress = NULL;
{
PRINT_KERNEL_PATCH_MSG(L"== Searching for nt!CmpLoadSystemVersionData pattern in PAGE ==\r\n");
EFI_STATUS FindCmpLoadSystemVersionData = FindPattern(SigCmpLoadSystemVersionData,
0xCC,
sizeof(SigCmpLoadSystemVersionData),
ImageBase + PageSection->VirtualAddress,
PageSection->SizeOfRawData,
(VOID**)&CmpLoadSystemVersionDataAddress);
if (EFI_ERROR(FindCmpLoadSystemVersionData))
{
PRINT_KERNEL_PATCH_MSG(L" Failed to find CmpLoadSystemVersionData. Skipping patch.\r\n");
}
else {
PRINT_KERNEL_PATCH_MSG(L" Found CmpLoadSystemVersionData pattern at 0x%llX.\r\n", (UINTN)CmpLoadSystemVersionDataAddress);
}
}
//---------------------------
if (CmpLoadSystemVersionDataAddress) {
CmpLoadSystemVersionDataAddress += 8;
UINT8 jmp = 0xEB;
CopyWpMem(CmpLoadSystemVersionDataAddress, &jmp, sizeof(UINT8));
PRINT_KERNEL_PATCH_MSG(L" Patched CmpLoadSystemVersionData [RVA: 0x%X]\r\n", (UINT32)(CmpLoadSystemVersionDataAddress- ImageBase));
}
else {
PRINT_KERNEL_PATCH_MSG(L" Failed to find CmpLoadSystemVersionData");
}
Mattiwatti I want to say that you helped me A LOT and now it's working PERFECTLY, thank you very much. I close Issue
After trying to fake Windows Build Number (compatibility purpose) RtlGetVersion Patch works normally , but patch MmCreatePeb does not apply after win loading, neither does NtBuildNumber. I viewed Kernel Memory and there was not modified memory. But if modify ntoskrnl.exe file, it works perfect.
RtlGetVersion![dbgView](https://i.imgur.com/Bn3MC00.png)
MmCreatePeb (from PEB and import from ntdll.dll)![RtlGetVersion](https://i.imgur.com/5DMLJXt.png)
Sorry for off topic, if it is, close it
code: