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

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

코드 개선사항

이전에 짰던 gBS 탐지 스크립트는 아래와 같은 문제를 가지고 있었다.

  1. ghidra가 SMM 런타임 함수를 찾지 못한다.
    이는 entry부터 찾아들어가는 ghidra의 특성과 달리 SMI를 통해 강제로 점프하여 들어오는 곳이라 참조가 끊겨 생기는 문제로 추측한다.
  2. 부팅 중에는 gBS가 실행되어도 된다.
    하지만 기존 코드는 모든 함수를 다 돌아버리면서 부팅용 함수든 런타임용 함수든 전부 다 검사해버려 오탐(False Positive)가 발생한다.
  3. 나중에 자동화 과정에서 이게 SMM 단에서 실행되는지, 일반 DXE 드라이버인지 알 수 없다.

개선 로직

개선 로직은 다음과 같이 고민했다.

  1. 먼저 검사 로직을 수행하기 전에 해당 프로그램의 모든 바이너리를 순회한다.
  2. 순회한 각 코드의 P-Code를 뽑아내고, 뽑아낸 P-Code에 간접 호출(CALLIND)가 있는지 찾는다.
  3. 만약 간접 호출이 있고, 0xE0 오프셋을 더한다면 SMM 핸들러를 등록하는 것으로 간주한다.
  4. 만약 해당 함수가 등록되어있지 않으면 등록을 해준다.
  5. 이후 gBS 주소 찾기 및 Taint Analysis를 수행한다.
    이 때 모든 함수를 찾던 기존 Taint Analysis가 아닌 찾아낸 핸들러들을 대상으로 한다.

왜?

 사실 굉장히 휴리스틱한 접근이였다.
먼저 어떻게 함수들을 찾았는지다. SMI이 울렸을 때 실행되는 함수들은 gSmst->SmmHandlerRegister에 저장되어 있다. 이 때 이는 gSmst에서 0xE0만큼 떨어져 있다. 원래라면 추적을 두번, 세번, 네번 이어 가야 gSmst를 찾아낼 수 있지만, 일단 빠르게 결과부터 보기 위해 0xE0을 더해서 호출하는 로직만 찾아서 찾는, 일종의 찍기를 한 것이다.(……)
다음으로 런타임 함수들만 잡는 방법이였다. 바이너리 자체에는 어떤게 부팅 중 실행되는지, 어떤게 런타임에 실행되는지 알 수 없다. 하지만 부팅 중에 실행되지 않는 함수들은 entry에 연결되지 않는다는 점을 생각했다. 그러면 어디에 저장되는가. 사실 이 저장되는 위치가 바로 gSmst->SmmHandlerRegister다! 이 안에 있는 모든 CALL들을 가져와 리스트, 또는 이터레이터 형태로 저장 후 순회하는 방식으로 바꾸면 된다.