Home > 졸업프로젝트 > UEFI DXE 바이너리 취약점 분석기 프로젝트_11

UEFI DXE 바이너리 취약점 분석기 프로젝트_11
UEFI Ghidra

원하는 드라이버만 가지고 빌드해보자

 이번에는 지난 시간에 이어서 .fd 파일 내에 다른 딸려오는 드라이버들을 전부 쫙 빼버리고 내가 원하는 드라이버만 선택하여 빌드해보았다.
우선 fdf, dsc 파일의 변경이 필요하여 복구 과정의 귀찮은 일들을 피하기 위해 기존에 clone을 떠온 폴더를 복제한 새 폴더를 만들고 진행하였다.
제목
먼저 최상위 폴더에 빌드에 집어넣을 폴더를 만든다. 폴더를 만들고 그 폴더 안에 만들 드라이버들의 폴더들을, 그리고 그 안에 .dsc 파일과 .fdf 파일을 만든다.
여기서 .dsc 파일과 .fdf 파일은 C의 Makefile에 대응된다고 보면 생각하면 좋다. 대신 역할의 분리가 좀 있긴 한데, .dsc 파일은 소스 코드들을 가져와서 어떻게 .efi 실행 파일로 만들지에 대한 명세를 담고 있고, .fdf 파일은 .dsc를 통해 만든 .efi 드라이버 파일들을 모아서 어떻게 최종 펌웨어로 올릴지에 대한 명세를 담고 있다.

[Defines]
  PLATFORM_NAME                  = DepexTestPkg
  PLATFORM_GUID                  = 11111111-2222-3333-4444-555555555555
  PLATFORM_VERSION               = 1.0
  DSC_SPECIFICATION              = 0x00010005
  OUTPUT_DIRECTORY               = Build/DepexTest
  SUPPORTED_ARCHITECTURES        = X64
  BUILD_TARGETS                  = DEBUG|RELEASE
  SKUID_IDENTIFIER               = DEFAULT
  FLASH_DEFINITION               = DepexTestPkg/DepexTestPkg.fdf

[LibraryClasses]
  UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
  UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
  DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
  BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf

[Components]
  DepexTestPkg/VulnMissingSmm/VulnMissingSmmDxe.inf
  DepexTestPkg/TestCycleA/TestCycleADxe.inf
  DepexTestPkg/TestCycleB/TestCycleBDxe.inf

DepexTestPkg 아래 .dsc 파일이다. 여기서 볼 것은 [Defines] 아래 PLATFORM_NAME, OUTPUT_DIRECTORY, FLASH_DEFINITION, 그리고 [Components]다. PLATFORM_NAME은 해당 패키지 플랫폼 이름을, OUTPUT_DIRECTORY는 저장될 경로를, 그리고 FLASH_DEFINITION의 .fdf 위치를 통해 파일을 읽어 펌웨어로 패키징까지 수행하게 된다. 그리고 [Components] 아래에 내가 만들 드라이버들의 .inf 파일들을 담게 된다.

[FD.DepexTestROM]
BaseAddress   = 0x0
Size          = 0x00100000
ErasePolarity = 1
BlockSize     = 0x1000
NumBlocks     = 0x100

0x00000000|0x00100000
FV = DXEFV

[FV.DXEFV]
# 오직 펌웨어 볼륨을 구성하는 필수 뼈대 3개만 남깁니다.
BlockSize          = 0x1000
FvAlignment        = 16
ERASE_POLARITY     = 1

INF DepexTestPkg/VulnMissingSmm/VulnMissingSmmDxe.inf
INF DepexTestPkg/TestCycleA/TestCycleADxe.inf
INF DepexTestPkg/TestCycleB/TestCycleBDxe.inf

[Rule.Common.DXE_DRIVER]
  FILE DRIVER = $(NAMED_GUID) {
    DXE_DEPEX    DXE_DEPEX Optional      |.depex
    PE32         PE32                    |.efi
    UI           STRING="$(MODULE_NAME)" Optional
  }

동일 경로의 .fdf 파일의 [FV.DXEFV] 안에 필수 드라이버들의 inf 파일들을 적어주면 된다.
이 때 .inf란 파일도 나왔는데, 이건 각 드라이버들의 명세라고 볼 수 있다.
제목
각 드라이버 폴더 내에는 C 코드와 .inf 파일를 만든다.

[Defines]
  INF_VERSION                    = 0x00010005
  BASE_NAME                      = VulnMissingSmmDxe
  FILE_GUID                      = AAAAAAAA-1111-2222-3333-444444444444
  MODULE_TYPE                    = DXE_DRIVER
  VERSION_STRING                 = 1.0
  ENTRY_POINT                    = VulnMissingSmmEntryPoint

[Sources]
  VulnMissingSmmDxe.c

[Packages]
  MdePkg/MdePkg.dec

[LibraryClasses]
  UefiDriverEntryPoint

[Depex]
  gEfiSmmBase2ProtocolGuid

.inf 파일 내에는 드라이버명, GUID, 컴파일 과정 중 C 파일 내에서 처음 읽을 진입점 함수명, C 파일의 위치, 필요한 의존성(Depex)들 등이 담겨있다.

#include <Uefi.h>

EFI_STATUS EFIAPI VulnMissingSmmEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  return EFI_SUCCESS; 
}

C 코드는 잘 작성하면 되고(…), .inf 파일의 시작점 함수를 잘 포함해주면 된다.

이후 빌드는

build -p DepexTestPkg/DepexTestPkg.dsc -a X64 -t XCODE5

위 명령어처럼 패키지의 .dsc 파일을 기준으로 하여 빌드를 수행하면
제목
빌드가 잘 저장된 것을 볼 수 있고,
제목
FV/DEPEXTESTROM.fd 파일을 UEFITool을 통해 열어보면 전부 다 펼쳐봐도 드라이버가 딱 세 개만 들어있는 것을 볼 수 있다.