[UEFI] SMI 발생 원리 및 처리 방법

2026. 3. 10. 13:15·CS/Graduation project

Ring -2 권한인 SMM으로 진입하기 위해서는, CPU에게 하던 일을 멈추도록 명령하게 하는 SMI를 발생시키는 방법 밖에 없다.

 

 

SMI가 발생하는 원리

SMI는 크게 하드웨어적 접근과 소프트웨어적 접근 두 가지 원리로 발생한다.

  • 하드웨어적 접근 (HW SMI): 메인보드의 온도 센서가 과열을 감지하거나 사용자가 전원 버튼을 누르는 등, 하드웨어 부품이 물리적인 신호를 보내는 방식
  • 소프트웨어적 접근 (SW SMI): 운영체제 환경에서 동작하는 소프트웨어가 펌웨어에게 특정한 작업을 요청하기 위해 APM I/O 포트(일반적으로 0xB2 포트)에 특정한 값을 기록함으로써 인위적으로 인터럽트를 유발하는 방식
    • APM: Advanced Power Management
    • 최근에는 전원관리를 ACPI가 대체한다. 근데 특정 I/O 포트에 값을 쓰면 SMI가 발생해서 SMM으로 진입한다는 그대로 남음 그래서 관습적으로 APM I/O포트라고함

 

 

 

 

 

SMM 인프라 초기화 방식 (부팅 시점의 드라이버 구현 관점)

PEI 단계에서 CPU의 캐시를 RAM처럼 쓰다가, 메모리 초기화가 끝나면 실제 RAM으로 데이터를 옮긴다. 이후 DXE 단계가 시작되면 SMM IPL(Initial Program Load)이 SMM Core를 실제 RAM의 격리된 SMRAM 영역에 적재하는데, 이때 메인보드 플래시칩에 포함된 SMM 드라이버들도 함께 로드되어 엔트리 포인트를 한 번씩 실행한다.

 

SMM 드라이버는 당장 어떤 작업을 수행하는 것이 아니라, 나중에 SMI가 발생했을 때 호출될 수 있도록 본인의 역할에 맞는 단 하나의 계층(Root 또는 Child)만을 선택해 핸들러를 등록해 두고 대기 상태로 들어가는 것임.

 

 

 

 

 

SMI 처리 방법: Root와 Child의 2계층 구조 (런타임 시점의 시스템 흐름 관점)

CPU에 존재하는 SMI# 핀은 단 하나뿐이므로, 하드웨어 센서(HW SMI)나 0xB2 포트(SW SMI) 등 어떤 경로로 인터럽트가 발생하든 메인보드 칩셋(PCH)은 동일한 SMI# 핀에 단일 신호를 전달한다. 따라서 CPU가 SMM 모드로 진입한 직후 시스템은 어떤 장치나 이벤트가 SMI를 유발했는지 전혀 알 수 없는 상태이다.

 

이를 식별하고 처리하기 위해 SMM 아키텍처는 전체 시스템의 인터럽트 처리 흐름과 개별 SMM 드라이버의 역할을 분리하여 설계했다. 런타임에 실제 인터럽트가 발생하면, 시스템은 사전에 각 계층에 등록된 개별 드라이버들을 순차적으로 호출하여 원인을 좁혀나감

 

 

1. Root SMI Handler (SMM 인프라 레벨 / gSmst의 0xE0 오프셋 사용)

가장 먼저 호출되는 것은 SMM Core에 직접 등록된 Root SMI Handler이다.

  • 주로 칩셋 제조사가 제공하는 핵심 드라이버(SMI Dispatcher)가 이 역할을 수행하며, X64 환경 기준으로 gSmst구조체의 0xE0 오프셋에 위치한 SmiHandlerRegister 함수 포인터를 직접 호출하여 핸들러를 등록해 둠
  • SMI가 발생하면 이 Root 핸들러가 가장 먼저 실행되어 칩셋 내부의 하드웨어 레지스터(SMI Status Register)를 직접 읽고, 지금 발생한 인터럽트가 물리적 버튼인지, 0xB2 포트를 통한 SW SMI인지 1차적으로 판별

 

2. Child Dispatcher (기능 레벨 / Protocol의 Register 함수 사용)

Root 핸들러가 레지스터를 분석하여 SMI의 정확한 하드웨어적 원인을 파악하고 나면, 모든 작업을 직접 처리하는 대신 해당 원인을 전문적으로 담당하는 Child Dispatcher에게 소프트웨어적 실행 권한을 위임함

  • 일반적인 OEM이나 서드파티 SMM 드라이버 개발자는 하드웨어 레지스터를 직접 조회할 필요 없이, 처음부터 EFI_SMM_SW_DISPATCH2_PROTOCOL과 같이 특정 이벤트에 매칭되는 Child 프로토콜을 찾아 해당 프로토콜 구조체 내부의 Register 함수(보통 오프셋 0x0)를 호출해 본인의 기능을 사전에 등록해 둠
  • 결과적으로 Root 핸들러가 판별한 원인에 따라 적절한 Child Dispatcher가 선택되고, 이 Dispatcher가 사전에 등록해 둔 특정 서드파티 SMM 드라이버의 핸들러를 호출하여 최종적인 작업이 수행되는 인과관계를 형성

 

 

 

 

 

탐지 로직의 분류 (정적 분석 관점)

결국 취약점 분석을 위해 개별 .efi 드라이버를 뜯어볼 때는, 이 드라이버가 전체 흐름 중 어느 계층에 자신의 핸들러를 구현해 넣었는지 그 패턴을 찾아내야 한다

  • Root SMI Dispatcher (칩셋 핵심 드라이버)
    • gSmst 오프셋 0xE0*를 호출하면서, 동시에 하드웨어 I/O 포트 Read 명령어(IN 명령어, 특히 PMBASE + 0x30 같은 SMI Status 레지스터 주소)를 수행하는 경우
  • SMM 인프라 시스템 드라이버 (보조 드라이버)
    • gSmst 오프셋 0xE0 호출은 하지만, 하드웨어 I/O 포트를 직접 읽고 분류하는 로직은 없는 경우
  • 기능 단위 핸들러 (OEM/서드파티 타겟 드라이버)
    • LocateProtocol (또는 Smst->SmmLocateProtocol)로 특정 GUID를 찾은 뒤, 반환된 포인터의 +0x0 오프셋(Register 함수)을 호출하는 경우

 

 

즉! SmiHandlerRegister와 Register 모두 추적해야 한다!!

  • 모든 예외 케이스를 다 포괄할 수는 없지만, gSmst 기반 핸들러는 보통 CommBuffer를 직접 전달받지 않으므로 공격자는 NVRAM 변수 값 등을 조작하는 우회적인 취약점을 노리고, Register로 등록된 핸들러의 경우 OS와 직접 통신하는 CommBuffer 영역을 통한 공격 시도가 주를 이룸

 

 

 


260309 기준 스크립트와 데이터의 차이

스크립트를 테스트하기 위한 데이터는 SW SMI 디스패처 방식(오프셋 0x00)과 CommBuffer 조작 시나리오를 기준으로 만들어졌다. 하지만 

 

 

현재의 기드라 분석 스크립트는 gSmst 구조체의 0xE0 오프셋(SmiHandlerRegister)으로 등록되는 Root SMI Dispatcher만 찾는다. 따라서 아래의 결과 코드를 보면, 스크립트는 실행되지만 취약한 부분을 탐지하지 않는 것을 볼 수 있다.

 

 

 

SmmCalloutHunter_v2.java> Running...
==================================================
Starting SMM Callout using gBS...v3.1
==================================================
[SMM_BASE2_PROTOCOL GUID] 발견! 위치: 00000590
SMM 드라이버 확인 완료. 본격적인 분석 시작.️

[CALLIND] function: entry (P-Code address: 000003c1)
-> [LOAD]
   -> [상수] 0x1b1
   -> [CAST]
      -> [INT_ADD]
         -> [LOAD]
            -> [상수] 0x1b1
            -> [CAST]
         -> [상수] 0x140

[CALLIND] function: entry (P-Code address: 000003d6)
-> [LOAD]
   -> [상수] 0x1b1
   -> [CAST]
      -> [INT_ADD]
         -> [INDIRECT]
            -> [COPY]
            -> [상수] 0x30
         -> [상수] 0x8
==================================================
탐색 및 생성 완료!
gBS 전역 변수 탐색 시작
[+0x60 Catch!] 함수: entry
gBS 전역 변수 발견: 000006c8
타겟 gBS 주소: 000006c8
--------------------------------------------------
SMM Callout 취약점 스캔 시작!
--------------------------------------------------
런타임 스캔 대상 함수 총 0개 추출 완료!

Safe : 런타임(SMI)에서 gBS를 사용하는 Callout 패턴이 발견되지 않았습니다.
JSON 파일 저장 중 오류 발생: C:\Users\0jing\Desktop\SmmCalloutHunter_v2_report.json
모든 분석이 완료되었습니다.
SmmCalloutHunter_v2.java> Finished!

진행 흐름을 보면 아래와 같다.

 

 

1. SMM_BASE2_PROTOCOL을 보고 이 바이너리가 SMM 드라이버가 맞다고 정상적으로 판단함

 

 

 

2. gBS전역 변수의 메모리 주소(00006c8)도 완벽하게 잘 추적해서 잡아냄

 

 

 

3. local_30(SwDispatch 프로토콜)의 오프셋 0(*local_30), 즉 Register 함수를 간접 호출함

  • 이때 local_28에 SW SMI를 발생시킬 트리거 값(0x41)을 세팅하고, 두 번째 인자로 0x240이라는 실제 취약한 핸들러의 주소를 넘겨서 등록

 

펌웨어 런타임에는 취약한 서드파티 핸들러(0x240)가 정상적으로 등록되고 실행되지만, 현재 스크립트가 gSmst의 0xE0만 찾도록 되어있어 놓치는 것!

 

따라서 SMM 취약점 탐지를 위해서는 SW SMI도 고려해야 한다.

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

[UEFI] Oob 탐지 스크립트 검증 데이터 생성 -1  (0) 2026.03.29
[UEFI] DEPEX Cycle Vulnerability 가능성 판단하기  (1) 2026.03.25
Taint Analysis 개념 정리  (0) 2026.03.01
[UEFI] Ghidra에서 edk2 함수 P-code로 확인해 보기  (0) 2026.02.26
[UEFI] gRT(Runtime Services)란?  (0) 2026.02.24
'CS/Graduation project' 카테고리의 다른 글
  • [UEFI] Oob 탐지 스크립트 검증 데이터 생성 -1
  • [UEFI] DEPEX Cycle Vulnerability 가능성 판단하기
  • Taint Analysis 개념 정리
  • [UEFI] Ghidra에서 edk2 함수 P-code로 확인해 보기
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
[UEFI] SMI 발생 원리 및 처리 방법
상단으로

티스토리툴바