[★]An Empirical Study of Semantic Deviation in Static Binary Lifting
- admin
- 2024년 6월 4일
- 2분 분량
최종 수정일: 2024년 11월 18일
팀명
바이너리 리프핑
팀원 명단
김선규, 안형진, 유형곤
지도교수
이성호 교수님
작품 배경 및 목적
많은 정적 분석 도구가 IR 수준에서 동작하기 때문에, 정적 분석의 결과가 원본 프로그램과 크게 차이가 나지 않도록 바이너리 리프팅을 하는 것이 연구의 목적입니다.
대표적인 중간 표현으로는 LLVM IR이 있습니다. LLVM IR은 프로그래밍 언어와 아키텍처에 독립적인 범용 컴파일러 프레임워크인 LLVM에서 사용되는 중간 표현입니다. LLVM IR은 LLVM 프레임워크에서 지원하는 모듈을 사용하여 프로그램을 분석하거나 변환할 수 있습니다. 이러한 이유로, 일부 바이너리 리프터는 바이너리 파일을 LLVM IR로 변환합니다.
현존하는 바이너리 리프터들은 EIR(Emulation-style IR) 또는 HIR(High-level IR) 형태로 바이너리 파일을 변환합니다. EIR은 바이너리 파일의 실행 동작을 재현하는 데 초점을 맞추어 프로그램의 실행 동작에 대해 정확도가 높습니다. 하지만, 변수나 함수 시그니처 복원 등이 이루어지지 않고, 레지스터나 메모리를 사용하여 코드를 표현하기에 정적 분석 도구를 적용하기는 어렵습니다. 또 다른 형태인 HIR은 EIR에서 더 추상적으로 변환된 형태로 변수나 함수 시그니처 복원이 이루어져 정적 분석 도구를 적용할 수 있습니다. 하지만, 컴파일 과정에서 사라진 정보를 복원하니 정확도가 높지 않아 정적 분석의 결과가 원본 프로그램에 비해 크게 달라집니다.
우리는 기존의 LLVM IR 기반 바이너리 리프터들의 리프팅 정확도 개선을 위해, 바이너리 리프터들이 가진 문제점을 파악하고, 어디서 문제가 발생하는 지점을 찾아 정리하는 것을 목표로 하고 있습니다.
작품 내용
1. 바이너리 리프터 탐색
가. RetDec
바이너리 파일을 LLVM IR로 변환 후 C 코드까지 디컴파일하는 바이너리 리프터입니다. 바이너리 파일을 어셈블리 명령어를 생성하고 저수준의 LLVM IR 변환합니다. 저수준의 LLVM IR은 LLVM Pass를 통해 저수준의 명령어를 최적화 및 규칙을 기반으로 한 변환을 통해 HIR을 생성합니다.
나. McSema
바이너리 파일 분석을 위해 개발된 바이너리 리프터로, 바이너리 파일을 EIR 형태로 리프팅하며 총 두 단계로 나누어 리프팅을 진행합니다. 먼저, IDA-Pro와 같은 디스어셈블러를 사용하여 바이너리 파일에서 필요한 정보를 추출하여 CFG 파일을 생성합니다. 그리고 CFG 파일을 통해 LLVM IR을 생성합니다.
다. Mctoll
보다 쉬운 re-engineering 위해 마이크로소프트에서 개발한 바이너리 리프터로 EIR 형태로 변환합니다. 바이너리 파일을 디스어셈블하여 직접 정의한 MCInst 명령어 배열로 변환합니다. MCInst 배열로 CFG를 생성하고 MCInst를 직접 정의한 MachineInstr로 리프팅합니다. 그리고 CFG를 4번 순회하며 보완하여 LLVM IR을 생성합니다.
라. Reopt
애플리케이션의 로직을 재활용하기 위해 개발된 바이너리 리프터입니다. 바이너리 파일의 text와 data 영역을 분석하여 코드가 위치한 영역을 식별합니다. 이를 분석하여 CFG를 생성합니다. 함수의 인자와 스택을 분석하여 각 함수별로 LLVM IR을 생성합니다.
2. 테스트케이스 설계
C 언어에서 사용되는 배열, 구조체, 포인터 연산, 함수 간접 점프 등의 다양한 경우에 대해 테스트 코드를 생성합니다.
3. 테스트케이스 분석
가. 테스트케이스 분석 절차
1) C 코드를 x86_64환경에서 gcc 컴파일러로 컴파일
2) 바이너리 리프터 별 테스트케이스 리프팅
3) 프로그램 semantic 보존 확인을 위한 리프팅 IR 재컴파일
4) 원본 실행 파일과 재컴파일한 실행 파일의 실행 결과를 비교하여 다음의 분류 기준에 따라 분류
가) 모든 코드 리프팅 성공
(1) Full Pass: 실행 결과 동일
(2) Full Fail: 실행 결과 달라짐
나) 부분적으로 리프팅 성공
(1) Partial Pass: 실행 결과 동일
(2) Partial Fail: 실행 결과 달라짐
다) Exception: 리프팅 중 오류가 발생
라) Empty: 아무것도 리프팅되지 않음
5) 바이너리 리프터 별 실패한 테스트케이스에 대한 분석 진행

댓글