https://eatrawlife.github.io/posts/2025/02/19/01 요기에 나오는 드라이버를 개선되기 전(문제가 있는) 버전으로 원복해서 취약점 검증용 드라이버로 만들어 보는 실습을 해보는게 목표

위 드라이버를 우선 언팩해야 되니까 https://starkeblog.com/lenovo/uefi/2022/08/28/extracting-bios-image-from-lenovo-update-exe.html 를 참고해서


innoextract와 7-zip을 사용하여 추출을 완료하였다.

해당 드라이버의 함수 중 func_0001780이 logo fail문제를 발생시켰다는 기록이 존재했고, 현재는 해결된 사항이므로
uint FUN_00001780(byte *param_1,ulonglong param_2,char param_3,longlong param_4,ushort param_5,
ushort param_6,longlong param_7)
{
ushort uVar1;
uint uVar2;
byte bVar3;
undefined1 *puVar4;
ushort uVar5;
ushort uVar6;
ushort uVar7;
undefined2 *puVar8;
ulonglong uVar9;
ushort uVar10;
ushort uVar11;
byte bVar12;
byte bVar13;
ushort uVar14;
ushort uVar15;
byte bVar16;
ushort uVar17;
uint uVar18;
ushort uVar19;
ushort uVar20;
ushort uVar21;
byte local_68;
ushort local_66;
ushort local_64;
uVar11 = 1 << (*param_1 & 0x1f);
bVar16 = *param_1 + 1;
uVar21 = 0xffff;
local_64 = 0xffff;
uVar6 = uVar11 + 2;
uVar18 = 0;
uVar7 = 0;
uVar15 = 0;
uVar10 = 0;
puVar8 = DAT_00001d48;
if (uVar11 != 0) {
do {
*(char *)(puVar8 + 1) = (char)uVar10;
uVar10 = uVar10 + 1;
*puVar8 = 0xffff;
puVar8 = puVar8 + 2;
} while (uVar10 < uVar11);
}
puVar4 = DAT_00001d50;
uVar9 = (ulonglong)(bVar16 >> 3);
uVar10 = uVar6;
uVar1 = uVar6;
uVar5 = local_64;
puVar8 = DAT_00001d48;
bVar12 = bVar16;
bVar3 = bVar16;
do {
if (param_2 < uVar9) {
return uVar18;
}
uVar2 = uVar18 >> 3;
bVar13 = (byte)uVar18;
uVar18 = uVar18 + bVar12;
uVar19 = (ushort)(*(uint *)(param_1 + (ulonglong)uVar2 + 1) >> (bVar13 & 7)) &
(1 << (bVar12 & 0x1f)) - 1U;
if (uVar19 == (ushort)(uVar11 + 1)) {
return uVar18;
}
uVar14 = uVar11;
uVar20 = uVar6;
bVar13 = bVar16;
local_68 = bVar16;
local_66 = uVar6;
local_64 = uVar11;
if (uVar19 == uVar11) {
LAB_00001a81:
uVar21 = uVar19;
uVar5 = uVar19;
if ((1 << (bVar13 & 0x1f) <= (int)(uint)uVar20) &&
(uVar21 = uVar14, uVar5 = local_64, bVar13 < 0xc)) {
bVar13 = bVar13 + 1;
uVar21 = uVar19;
local_68 = bVar13;
uVar5 = uVar19;
}
}
else {
if (uVar15 == param_6) {
return uVar18;
}
uVar17 = 0xffff;
uVar14 = uVar19;
local_68 = bVar3;
local_66 = uVar1;
if (uVar19 < uVar10) {
for (; uVar14 != 0xffff; uVar14 = puVar8[(ulonglong)uVar14 * 2]) {
uVar17 = uVar17 + 1;
puVar4[(short)uVar17] = *(undefined1 *)(puVar8 + (ulonglong)uVar14 * 2 + 1);
}
if (uVar21 != uVar11) goto LAB_0000196a;
LAB_0000198b:
uVar14 = uVar21;
uVar20 = uVar10;
bVar13 = bVar12;
local_64 = uVar5;
if (-1 < (short)uVar17) {
do {
uVar9 = (ulonglong)uVar17;
uVar17 = uVar17 - 1;
uVar21 = uVar7 + 1;
*(undefined4 *)
(param_7 + (longlong)(int)((uint)uVar15 * (uint)param_5 + (uint)uVar7) * 4) =
*(undefined4 *)(param_4 + (ulonglong)(byte)puVar4[uVar9] * 4);
uVar7 = uVar21;
puVar8 = DAT_00001d48;
uVar14 = uVar5;
uVar20 = local_66;
bVar13 = bVar3;
if (uVar21 == param_5) {
if (param_3 == '\0') {
uVar15 = uVar15 + 1;
}
else if ((uVar15 & 7) == 0) {
uVar15 = uVar15 + 8;
if (param_6 <= uVar15) {
uVar15 = 4;
}
}
else if ((uVar15 & 3) == 0) {
uVar15 = uVar15 + 8;
if (param_6 <= uVar15) {
uVar15 = 2;
}
}
else if ((uVar15 & 1) == 0) {
uVar15 = uVar15 + 4;
if (param_6 <= uVar15) {
uVar15 = 1;
}
}
else {
uVar15 = uVar15 + 2;
}
uVar7 = 0;
if (uVar15 == param_6) break;
}
} while (-1 < (short)uVar17);
}
goto LAB_00001a81;
}
uVar20 = uVar10;
bVar13 = bVar12;
if (uVar21 != uVar11) {
uVar17 = 0;
for (uVar1 = uVar21; uVar1 != 0xffff; uVar1 = puVar8[(ulonglong)uVar1 * 2]) {
uVar17 = uVar17 + 1;
puVar4[(short)uVar17] = *(undefined1 *)(puVar8 + (ulonglong)uVar1 * 2 + 1);
bVar12 = bVar3;
}
*puVar4 = puVar4[(short)uVar17];
LAB_0000196a:
uVar9 = (ulonglong)uVar10;
uVar10 = uVar10 + 1;
puVar8[uVar9 * 2] = uVar21;
*(undefined1 *)(puVar8 + uVar9 * 2 + 1) = puVar4[(short)uVar17];
local_66 = uVar10;
goto LAB_0000198b;
}
}
local_64 = uVar5;
uVar9 = (ulonglong)(bVar13 + uVar18 >> 3);
uVar10 = uVar20;
uVar1 = local_66;
uVar5 = local_64;
bVar12 = bVar13;
bVar3 = local_68;
} while( true );
}
해당하는 부분이 under/overflow를 발생하게 끔 만들어 보기로 하였다.
![]() line 1244 offset 58 입력 데이터를 검증 |
![]() line 1266 offset 79 크기나 자료의 깊이 등을 제한 |
![]() line 1292 offset 106 배열의 범위 확인 |
|
위와 같은 부분이 https://www.binarly.io/advisories/brly-logofail-2023-007 에서 언급한 데이터를 검증하지 않는 문제점이 해결된 부분이라고 판단하였다(구조상 유사해 보여서).
이 부분을 다시 취약점으로 되돌리기 위해서는 검증 부분을 제거하면 된다고 판단하였고, 우선적으로 편집을 위해서 c로 export하였다.

이후 해당 검증 파트 부분들을

아래와 같이 주석 처리하였다. 이로써 이론적으로 오버플로우가 발생할 수 있는 환경은 조성을 하였고, 이 소스코드를 활용하여 드라이버를 빌드해보자.


decompile된 추출 코드 위 아래에 아래와 같은 코드를 추가하고,
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = GifDecoderDxe
FILE_GUID = 1353de63-b74a-4bef-80fd-2c5cfa83040b
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
ENTRY_POINT = UefiMain
[Sources]
GifDecoderDxe.c
[Packages]
MdePkg/MdePkg.dec
[LibraryClasses]
UefiApplicationEntryPoint
UefiLib
[BuildOptions]
MSFT:*_*_*_CC_FLAGS = /W0
GifDecoderDxe.inf 라는 파일을 위와 같이 작성한다. 아래에 빌드 옵션으로 경고는 깔끔하게 무시했다.
[Defines]
PLATFORM_NAME = GifDecoderDxe
PLATFORM_GUID = 056D93D5-69E2-43D4-A61F-10029E65E923
PLATFORM_VERSION = 0.1
DSC_SPECIFICATION = 0x00010005
OUTPUT_DIRECTORY = Build/GifDecoderDxe
SUPPORTED_ARCHITECTURES = X64
BUILD_TARGETS = DEBUG|RELEASE
SKUID_IDENTIFIER = DEFAULT
[LibraryClasses]
# 기본적인 UEFI 라이브러리 설정
UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
[Components]
MdeModulePkg/Application/GifDecoderDxe/GifDecoderDxe.inf
edk2 최상위 폴더에 GifDecoderDxe.dsc를 넣어서 필요한 빌드를 정의해 주었다.
이후 edksetup과 빌드를 해서

D:\project\edk2-edk2-stable202102\edk2-edk2-stable202102\Build\GifDecoderDxe\DEBUG_VS2019\X64
해당 경로에

이렇게 취약점이 반영된 드라이버를 빌드할 수 있었다.
p.s
'fun_00001780은 뭐하는 함수였을까'라는 생각이 들어서 ai한테 물어보니까 LZW(Lempel-Ziv-Welch, 무손실 압축 알고리즘) 중 복구에 해당하는 함수로 추측하였다.
함수의 시작 부분의 다음 로직들이 LZW의 전형적인 방식이라고 하였고(초기 사전의 크기 결정방식와 가변 비트읽기 로직),
함수 중간의 조건문이 사전을 통한 데이터 복원 패턴과 일치하여, LZW 중 복원 함수로 판단하였다.
'졸업프로젝트' 카테고리의 다른 글
| 이제 depex hunter를 자동화 해보자 (1) | 2026.03.15 |
|---|---|
| 결과 json에는 어떤 것들이 들어가야 빼 먹지 않고 잘 들어갔다고 소문이 날까? (0) | 2026.02.26 |
| ghidra headless 사용 (0) | 2026.02.13 |
| 사전공부 6 (0) | 2026.02.06 |
| 사전공부 5 (0) | 2026.01.30 |


