UEFI 스터디 13차 - 드라이버 탐색, 드라이버 로직 보완.

5 minute read

Published:

취약점이 있는 드라이버를 찾아라 Season.02

서웅이가 캐치한 실제 드라이버가 없다는 단점의 해결을 위해서 실제 취약점이 있는 드라이버를 찾고자 했다.
하지만 쉽게 찾지 못한듯 보였고, 조원들에게 헬프를 요청했다. 나도 자기전에
‘30분만 찾아봐야지’ 라고 가볍게 시작했으나, 30분이 지났을 무렵에
상용 드라이버 찾은걸로 게시글도 썼는데 이걸 못찾는다고?
라는 쓸데없는 오기가 발동해서 인터넷을 뒤지기 시작했다.
운좋게 성공을 했고, 접근방법을 공유한다.

  1. 이 버전은 실제 배포된 모델인가?
    보고서에 있던 문제있던 드라이버 버전은 ver 3.01.
    다운로드 링크를 계속 바꿔보았지만 해당 버전은 없었다. 하지만 그 주변으로 구글링을 하다보니 알게된것

프레임워크 intel 12th 노트북은 최초 bios 버전이 3.04 란 것이다.
3.01은 최초로 사내에서 나왔고, 뒤에 추가사항이 붙어서 3.04로 탑재된 것이다.
(심지어 추후 sha256 해시값도 동일했다)

  1. 과거의 바이오스 배포 다운로드 링크는 어떨까?
    gemini가 과거 다운로드 링크도 확인해보라고 wayback 머신을 추천했다.
    과거의 사이트의 모습을 캡쳐해서 저장한 아카이브 사이트였다.
    덕분에 다운로드 드라이버가 exe일때도 있고, msi일때도 있다는 걸 알 수 있었다. (크게 도움은 안됐지만, 운좋으면 즉시 다운로드 링크를 얻을 수도 있을듯?)

  2. 다운로드 링크 브루트포스
    여러 글을 구글링했지만, 3.04가 공식적으로 사이트에서 배포된 버전이 아니라
    최초 출시했을때, 공장에서 메인보드에 그냥 구워서 배포된 첫 버전 이었단점,
    그리고 생각보다 최초버전의 바이오스 덤프를 원하는 사람이 없었던 점으로
    벤더 외 3자의 다운로드 링크, 덥프를 찾기가 불가능에 가까웠다.
    결국, 최초 버전이 3.04라는것만알고 마지막 여한으로 끝부분 확장자만 몇번 바꿨는데
    기적처럼 3.04.exe가 있었고 다운로드가 되었다!
    근데 서웅이의 코드는 이걸 못 잡았다

  3. 펌웨어 공유 사이트 이용
    오픈 소스를 지지하는 인터넷 이용자들 특성상 클로즈드 소스를 고수하는 펌웨어들도 맘에 들지 않는 모양이다.
    나름 펌웨어들을 공유하는 사이트들이 꽤나 있었다.
    해당 사이트
    단 이미 배포 시스템이 잘되어있는 대형 벤더들것들은 기대하기 힘들고,
    아까 문제가 되었던 드라이버들도, 문제가 터진 후 해결된 버전들 위주로 있었다.
    즉 잘 써먹진 못했다.

  4. LLM 이용
    아까 framework사의 경우 진짜 작아서 검색해도 결과가 거의 나오지 않았지만,
    이 후 hp의 드라이버도 찾을일이 생겼으나, 보안권고 페이지가 터져서 곤란했지만
    클로드를 쓰니 10초만에 해결해버렸다. (파일이름 -> 버전이름 대응시키는 정보 찾기 => 이전 버전 찾기 => HP의 FTP URL 형식을 참고해서 가져옴)

  5. SHA256 해시값 이용 검증
    문제는 이를 까도 이게 과연 문제가 해결되기 전 버전인가가 확실치 않다.
    이는 보고서에 있는 해시값을 이용해서 비교해보면 된다.





    (내가 검증하던 녀석. 동일하다.)

검증 로직 보완하기 2

지금 까지의 개선

  • 초안 : pcode 상에서 피연산자들이 곱해지기전 비교연산에 사용된적있으면 안전하다 판단.
  • 개선 : pcode 상에서 피연산자들이 곱해지기전 0과 int_equal 연산되면 안전하다 판단. (단순화, 참조구현 고려)

여전히 남은 이슈 -> 오버플로우는?

접근법

  1. 참조구현(edk2)의 이미지 파서가 빌드될경우 어떤형태인지 살핀다.(함수 인라이닝 고려)
  2. 해당 형태가 기존 취약한 코드에 있는지 살펴 마지막으로 오버플로우 검사여부를 살핀다.
  3. 해결 방법 고안.

참조 구현 살피기

이전 주에 edk2의 bmp파서 라이브러리를 찾는데는 성공했다.
그러나 edk2의 ovmf 빌드에서 해당 라이브러리 사용 드라이버를 찾을 수가 없었다..
(아마 실제 빌드에서는 사용안하는듯)

그래서 직접 해당 라이브러리를 포함한 드라이버를 빌드하기로 했다.
edk2를 통해 간단히 빌드했고, 드라이버가 매우 거대했으나, 디버깅용 에러출력 코드 덕에 쉽게 찾을 수 있었다.
(기드라 -> search -> for string)


음. 명백히 인라이닝 되었다. 기존에 있던 안전 곱셈 함수가 사라졌다.


edk2 소스코드

그냥 보니 해석하기 힘드니, C++ 수도코드를 통해 함께 보도록하자.

즉 edk2는 오버플로우를 막기위해

  • 매곱셈마다
  • 32 -> 64bit로 확장한 곳에 곱셈 결과를 넣고
  • 32bit 최대값과 비교하는 형태로 32비트를 못넘게 한다
    매우 단순하지만 강건해보인다.

문제의 드라이브에도 이런 검사가 있을까?

확인해 본 결과 따로 없다.
하지만 혹시나 싶어, 마지막으로 클로드에게 어셈블리와, 역컴파일 코드를 넘겨주니
어셈블리 쪽에서 그 안전망을 찾아줬다. (역컴파일 코드 위주로본 나를 반성한다.)


movzx로 가로, 세로의 하위 16비트만 32비트에 확장 -> 즉 저둘의 곱만으로는 32비트 오버플로우는 나지 않는다.
역컴파일 코드만 보고 “얘는 왜이렇게 형변환이 잔뜩 붙어있지” 하고 넘긴 실책이었다.

그럼 진짜 안전할까?

이 뒤에도 혹시나 싶어 어셈블리 코드를 넣고 클로드에 여러번 물어봤다.
여기까진 안전하다 생각했으나 곱하기 4 (쉬프트 2)가 문제가 될 여지가 있다!

근데 이게 참 곤란한게 기드라 리스팅으로 봐도 이건 모르는거다. 길다란 리스팅의 low-pcode로만 봐야만 알 수 있었다


저기보면 기드라가 고맙게도 ?CX 레지스터를 param1이라고 친절히 써두었다.
함수 위쪽을 확인하면 해당 레지스터가 64비트 레지스터 RCX라는 것을 확인할수 있다.
오버플로우가 나도 34비트 < 64비트니 문제가 없다.

여기에 제미나이, GTP 다 끄덕X2 했지만 클로드만 여기서 딴지를 걸었다.
“저거 RCX아니라 ECX인데?..”
저게 ECX니까 만약 좌측 비트에 뭔가 채워져 있으면 잘린다는 거다. 만약 RCX면 저 기계어 코드 중간에 48이 들어가야한다고 한다.
ECX라는게 RCX 64비트 레지스터를 그냥 이름만 바꿔서 쓰는것 정도인줄 알았으나 클로드가 계속 아니라한다.

직접 검증해보자

일단 param1은 명백하게 RCX라고 기드라가 명시해뒀다. 그러니 클로드가
저 param1으로 보기좋게 하는걸 한번 꺼보라고 했다.
(Edit → Tool Options → Listing Fields → Operands Field)


진짜네?

그러면 일단 복잡하게 명세를 찾아보기전에 간단히 intel 64비트 환경에서 해당 어셈블리를 돌려보자.
오버플로우를 일으킬수 있는 0x????FFFF, 0x????FFFF로 실험해봤다.


정답 : 17179344900
결과(RCX) : 4294443012
진짜 오버플로우가 일어나면서 더 작은 수가 되었다.

결론 : 원하는 수를 저 구조체의 너비, 높이값에 위치시키면 진짜 오버플로우가 일어남.



오버플로우 방어로직 정리

  • edk2 -> 32비트를 넘기지 못하도록 모든 곱셈 연산을 검증
  • 벤더(레노버) -> 하위 16비트를 가져와서 연산. 하지만 그 곱셈을 여러번 해버리며 32비트를 초과해버림.

해결책(생각중..)

  • edk2 방식을 지키는지 패턴 매칭 검사 -> 해당 벤더처럼 할시 모두 오탐이남.
  • p코드상에서 저장하는 바노드가 x비트 레지스터일때 int_mult, int_shift로 피연산자가 모두 동일한 x 비트이면 탐지?
    -> 역시 거의 모두 오탐날것. 그래서 보완 위해 이전에 피연산자의 크기를 검사했는지도 동반되어야하는데, 아마 구현에 진짜 오랜 시간이 걸릴것이다.
  • 차라리 린터처럼 작동 (너 왜 피연산자 3개 곱해? 왜 edk2식 검사 안해?) -> 우리 툴의 역할과 다름.

너무 복잡한 문제다보니 일단 보고서의 문제 (0인 피연산자)를 해결에 만족하고 차라리 오버플로우와 관련된
다른 CVE, 보고서로 다른 스크립트도 짜보고 보완하는게 좋을듯 하다. 너무 하나의 보고서, 스크립트에 매몰되어 있는듯해서..