2023. 5. 3. 14:59ㆍ코딩/공부 [STUDY]
1. 정적 디스어셈블
바이너리 분석 기술은 크게 두 가지로 구분할 수 있다.
첫 번째로 정적 분석과 두 번째로 동적 분석이다.
우선 정적 분석은 바이너리 파일을 실행하지 않고서 내부의 명령어 정보를 추출하여 이를 이용해서 흐름을 분석하는 방법인데,
이를 달성하기 위해서 디스어셈블 툴들은 아래와 같은 과정을 거친다.
바이너리를 로드함 -> 바이너리 내부의 기계어 명령을 찾음 -> 사람이나 컴터가 이해하고 처리할 수 있을 정도로 번역함
하지만 두 번째 과정이 달성하기 매우 어려운 편에 속하는데, 그 이유로는 2번 과정에서 많은 오류가 발생하기 때문이다.
이런 오류를 막기 위해서 2가지 방법이 고안 되었다.
1. 선형 디스어셈블
2. 재귀적 디스어셈블
두 방법 모두 각자의 장 단점이 존재한다.
우선 선형 디스어셈블 같은 경우는 개념 자체는 매우 간단하다.
바이너리 내부의 코드 세그먼트를 순차적으로 접근하면서 마주치는 모든 바이트들을 연속적으로 디코딩하고 일련의 명령어로 번역하는것인데, 이때 주의해야 할 점은 바이너리 내ㅢ 모든 바이트들이 항상 대응 되지 않는다.
비쥬얼 스튜디오 컴파일러의 경우에 점프 테이블 등의 데이터를 코드와 함께 섞어버려서 데이터가 무엇인지를 구분할 단서를 남기지 않는다.
따라서 이를 디스어셈블 툴로 디스어셈블 할 시에 인라인 데이터와 코드를 혼동하여 해석해버려서 바이트가 밀리는 경우도 발생한다.
이때, 재정렬을 시도하는 경우도 있는데 그 과정에서 오히려 인라인 데이터 다음에 존재하는 몇 개의 명령어를 누락해 버리기도 한다.
두번째로 재귀적 디스어셈블이다.
재귀적 디스어셈블은 해당 프로그램의 특정 엔트리 포인트를 시작지점으로 잡고나서 그곳에서부터 실행 흐름을 따라가면서 코드를 찾는다.
하지만 단점이 존재하는데, 모든 제어 흐름을 따라가기가 쉽지 않다는 것이다.
간접 점프나 함수 호출의 목적지를 정적으로 전부 파악하는 것이 굉장히 어려울 수 있다.
현대의 컴파일러는 점프 테이블을 기반으로 작동하는데, 예를들어서 스위치의 입력으로 사용된 값을 확인한 후 해당 인덱스를 계산해서 테이블 내에 저장돼 있는 코드 구문 중 적절한 상황에 부합하는 것을 찾는다.
이런식으로 간접 점프 명령어로 점프 테이블에 정의 된 어떤 위치의 주소로도 이동할 수 있는 것이다.
또한, ret 명령어가 포함 돼 있는, 예를들어 특정 함수가 호출되고 오류 메시지가 표출된 후 강제로 종료되므로 해당 구문으로 다시 복귀가 불가능하고, 패딩 바이트 뒤에 나타난 명령어들은 코드로 해석돼서는 안 되는 경우도 발생할 수 있다고 한다.
2. 동적 디스어셈블
데이터와 코드를 구분할 수 없는 문제, 간접 호출을 처리할 수 없는 것등이 정적 분석의 한계다.
동적 분석에서는 이를 해결할 수 있다.
게다가, 바이너리가 실행될 때 구체적인 레지스터와 메모리 값등을 활용할 수 있는 등의 이점이 있다.
동적 분석 방식의 한계로는 코드 커버리지라고 불리는 문제가 있는데,
동적 분석에서는 바이너리가 수행되는 동안 실제로 만나는 명령어들만 분석을 진행한다.
따라서 만약 명령어 사이에 실제로 더 중요한 정보가 가려져 있다면 분석가는 그것을 알 수가 없다.
따라서 주어진 프로그램에서 수행 가능한 전체 경로를 전부 조사하는 것은 매우 어렵고 시간이 많이 드는 문제이기 때문에
적용 범위를 증진시키는 몇 가지 방법을 사용 할 뿐이다.
- 테스트 케이스
- 퍼징
- 기호 실행
3. 디스어셈블 코드 구조화
- 구획화 : 코드들을 논리적 조각의 연결로 구분해서 쪼개는 것임
- 제어 흐름 파악 : 코드 실행 과정들을 시각화함
디스어셈블 도구들이 함수 탐지를 하고자 사용하는 주요 전략은 바로 '함수 시그니처' 다.
일반적인 시그니처의 경우에는 쉽게 찾아낼수 있지만,
간접호출이나 꼬리 호출을 통해서 실행되는 함수들은 난이도가 높다.
따라서 이러한 어려운 상황들에 대처하고자 시그니처 기반 함수 탐지 시 이미 잘 알려진 다양한 함수들의 시그니처를 데이터베이스화해서 관리한다.
4. 분석 방법론
- 프로시저 간 분석과 프로시저 내부 분석 :
대부분의 프로그램들은 상당수의 조건 분기를 가지고 있다. 따라서 보통의 프로그램에 대해 가능한 모든 경로를 분석하려는 시도
는 쉽지 않다.
그렇기 때문에, 프로시저 내부 분석 방법을 사용한다. 한 번에 주어진 함수 하나만을 대상으로 살펴보는 것이다.
이에 대조적으로, 프로시저 간 분석은 프로그램 전체를 대상으로 연결 관계를 호출 그래프를 통해 파악하려는 시도다.
하지만 프로시저 내부 분석의 단점이 있는데, 만약에 어떤 일련의 함수가 호출되어야만 버그가 트리거 된다면,
개별의 프로시저만으로는 발견 되지 않을 수 있다.
- 흐름 위주 방법 :
- 문맥 위주 방법 :
문맥 위주 분석은 함수들이 호출되는 순서를 누적해서 판단한다.
프로시저간 분석에서만 적용된다.
또한 길이가 정해지지 않은 상태의 경로를 온전히 탐색할 수 없으며, 문맥이 클수록 지나치게 많은 계산량을 요구한다.
심지어 재귀 함수가 존재한다면 문맥의 경우의 수가 무한대로 측정된다.
- 제어 흐름 분석 :
제어 흐름 속성을 파악하고자 하는 시도를 제어 흐름 분석이라고 하고
데이터 흐름에 기반한 분석을 데이터 흐름 분석이라고 한다.
- 데이터 흐름 분석 :
1. 도달 정의 분석
2. use - def 체인
3. 프로그램 슬라이싱
'코딩 > 공부 [STUDY]' 카테고리의 다른 글
Best of the Best 프로젝트 - 시놀로지 NAS (0) | 2023.09.19 |
---|---|
[STUDY] DFS & BFS - 그래프 탐색 (0) | 2023.05.28 |
[STUDY] - 스택,덱,큐 (0) | 2023.04.22 |
실전바이너리분석 - 1장 (0) | 2023.04.19 |
[STUDY] 유클리드 호제법 (0) | 2023.04.17 |