Home > 졸업프로젝트 > Ghidra P-Code 알아보기 6

Ghidra P-Code 알아보기 6
Ghidra P-Code

기존 코드의 문제점

기존 코드는 다음과 같은 문제점을 지닌다. 결론부터 말하면 매우 휴리스틱하며,

  1. isSanitized 함수의 의미론적 불일치
    CBRANCH가 있으면 무조건 Safe 판정. 실제로 sink를 지배하고 있는지 보고 있지 않다.
  2. 하드코딩된 Sink 모델
    만약 memcpy가 아니라 memmove/strncpy 이런 함수라면? 인자 위치가 다를 것.
  3. 제어 의존성은 휴리스틱으로, 데이터 의존성만 보고 있음

Upgrade 요소

먼저 Sink를 담을 요소를 memcpy로 한정짓지 않기 위해 따로 table을 뺀다. 예를 들어

Map<String, SinkSpec> Sinks = Map.of {
      "memcpy", new SinkSpec(2, 0), //1번 인자 : size 인자 위치, 2번 인자 : bound 계산을 위한 버퍼 위치
      "memmove", new SinkSpec(2, 0),
}

와 같은 식으로 Table을 정의한다면 각 Sink들에 따라 인자 순서가 달라져도 좀 더 정확한 판단을 할 수 있지 않을까 싶다.

다음으로 Source다. 추후 Taint 등을 사용한다면 필요하므로 Source를 한번 더 정의한다면

  1. 네트워크 입력 함수의 리턴이나 출력 인자
    예를 들어 recv(sock, buf, …)이라면 buf에 공격자 데이터가 담길 것이고, 이런 것을 오염으로 마킹한다.
  2. LOAD
    모든 LOAD를 무조건 위협으로 보는 것이 아닌 이미 오염된 메모리 영역에서만 읽는 LOAD로 좁히기
  3. 함수 파라미터
    외부에서 들어오는 파라미터. 다만 이건 추후 확장 영역으로 남기고자 한다.

다음으로 Dataflow인데, 기존처럼 def-use 흐름의 visited 흐름은 비슷하게 가져가되 상수면 무조건 안전, LOAD면 무조건 경고같은 판정을 수집 과정에서 바로 확인하지 않고 여기서는 의존성 관계만 수집하고, 판정을 따로 뺀다. 이 때 판정 방식은 동일하게 sink에서 getDef 함수를 가지고 역추적을 수행한다.

다음으로 Heartbleed의 핵심인 경계값 체크 로직이 들어가 있는가다. isSanitized 함수를 개선하기 위해 sink에 도달한 taint 값 v에 대해서 CBRANCH가 존재하고, 그 CBRANCH의 BB가 sink의 BB를 지배하며, sink가 검사 통과 edge에 위치하면 경계값 체크가 정상적으로 수행된다 생각하면 될 것이라 생각한다.

(여기서 더 나간다면 Z3 등을 통해서 SAT 여부를 판단하지 않을까…싶다.)