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

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

추가 문제점

 저번에 찾은 스크립트를 다른 팀원이 테스트를 해봤고, 해당 스크립트에 약간의 추가 문제점을 찾을 수 있었다. 먼저 SMI는 접근 방식이 하드웨어적 접근과 소프트웨어적 접근으로 발생한다.

  • 하드웨어적 인터럽트 : CPU 온도 상승, 노트북 뚜껑 닫히고 열림 센서 작동 등 하드웨어에서 직접적으로 발생하는 인터럽트
  • 소프트웨어적 인터럽트 : OS가 요청하여 SMM 모드로 들어갈 때 OS가 소프트웨어적으로 요청하는 인터럽트

하지만 SMI를 알리기 위한 핀은 CPU에 단 하나만 연결되어 있으므로, CPU에 SMI 신호가 왔을 때 해당 신호가 하드웨어 신호인지, 소프트웨어 신호인지 알 수 없다. 그래서 이 때 SmmBase2가 나와서 하드웨어와 연결된 레지스터들을 다 찾아서 전기 신호가 들어왔는지 아닌지 여부를 판단한다. 그 중 전기 신호가 들어온 레지스터가 있다면 하드웨어가 요청한 인터럽트로 판단, 그렇지 않다면 소프트웨어 인터럽트로 판단을 진행한다. 이 과정이 바로 Root SMI Handler가 되는 것이다. 그리고 판단한 결과가 하드웨어 인터럽트면 각각 하드웨어에 맞는 디스패처로, 소프트웨어 인터럽트라면 다른 특정 디스패처(EFI_SMM_SW_DISPATCH2_PROTOCOL) 등을 호출하게 되는데 이것들이 Child SMI Handler가 된다.
 하지만 이렇게만 봤을 땐 결국 SmmBase2를 거칠텐데 왜 얘를 거치지 않고 넘어가냐는 궁금증이 생겼다. 이 부분이 바로 처음 분석할 때 이야기하던 Autogen.c라는 파일이다. 이는 코드를 다 짜고 빌드를 하면 컴파일러가 자동으로 삽입하는 코드인데, 이 안에 SmmServicesTableLibConstructor라는 함수가 존재한다. 이 함수가 바로 SmmBase2를 찾아서 InSmm을 호출한 뒤 gSmst의 주소를 찾아서 전역 변수로 올리는 과정을 거치게 되고, 해당 핸들러들은 gSmst를 사용하기 위해 굳이 gBS->LocateProtocol을 통해 SmmBase2를 찾고, InSmm을 통해 SMRAM 내 영역인지 판단한 뒤 GetSmstLocation을 통해 gSmst를 받아오는, 매번 불편한 일을 하지 않아도 되는 것이다. 그리고 우리의 코드는 바로 이 부분을 놓친 것이라 생각했다.

SmmCalloutHunter_v3

SmmCalloutHunter_v3.java 링크
추적 로직은 가볍게 작성했다. 기존 gSmst->SmiHandlerRegister에서 Smi 핸들러 함수를 찾은 것과 더불어 EFI_SMM_SW_DISPATCH2_PROTOCOL의 guid를 호출하는 곳들을 전부 찾은 뒤 XREF를 따라 올라가 함수들을 만나면 등록하는 로직을 추가했다.

그런데…

제목
왜 잡지 못한지에 대해선 뒤에서 잘 설명해줄 것이다…