리버싱(리버스 엔지니어링)이란?
완성된 제품을 해체하고 분석하여 구조와 기능, 디자인을 파악하는 행위입니다.
대부분의 공학 분야에는 리버싱이 있습니다.
필자가 배우게 될 리버싱은 컴퓨터 공학의 SW 리버싱입니다.
리버싱이 사용되는 이유
좋은 예시👍 | 나쁜 예시👎 |
- 오랫동안 개발 중단된 프로그램을 패치해야 할 때 - 각종 프로그램의 보안성을 평가할 때 - 악성코드를 분석할 때 |
- 상용 프로그램 무료로 이용하기 위해 불법 프로그램을 만들 때 - 게임의 핵을 만들 때 |
하지만 리버싱을 하면서 프로그램의 전체적인 작동 원리를 알아낼 수 있으므로,
상용 프로그램의 지적 재산권을 침해할 수 있습니다.
따라서 리버싱은 저작권을 침해하지 않는 선에서 제한적으로 허용됩니다.
Binary
자연어 -- 어셈블리어 --어셈블러--> 기계어
자연어 -- 고급언어(C,C++,Go,Rust) --컴파일러--> 기계어
저급언어: 어셈블리어, 기계어
그러면 많은 컴퓨터 분야 엔지니어들이
프로그램을 바이너리(Binary)라고 하는 이유는 무엇일까요?
Stored-Program Computer에서는 프로그램들이 저장 장치에 이진 형태로 저장되기 때문입니다.
컴파일러: 소스 코드를 기계어로 번역해주는 프로그램 ex) GCC, Clang, MSVC
인터프리터: 컴파일이 필요하지 않는 언어를 번역해주는 프로그램
ex) Python, Javascript는 컴파일 필요 X
컴파일 과정
전처리
1. 주석제거
2. 매크로 치환
3. 파일 병합
컴파일
: 소스 코드의 문법을 검사 후, 다른 언어의 목적 코드로 번역
코드에 문법적 오류가 있다면 컴파일을 멈추고 에러를 출력
몇몇 조건을 만족하면 최적화 기술을 적용하여 효율적인 어셈블리 코드를 생성
어셈블
: 생성된 목적 코드를 정해진 형식(윈도우는 PE형식이고 리눅스는 ELF형식)의 목적 파일로 변환
변환된 목적 파일은 더이상 사람이 해석하기 어려움
링크
: 여러 목적파일들을 연결하여 실행 가능한 바이너리로 만드는 과정
디스어셈블
바이너리를 분석하려면 바이너리를 읽을 수 있어야 하는데,
바이너리는 기계어로 작성되어 있습니다.
그래서 분석가들은 이를 어셈블리어로 재번역 하고자 했습니다.
디컴파일
리버싱 엔지니어들은 어셈블리어를 더 이해하기 쉬운 고급 언어로
바이너리를 번역하는 디컴파일러를 개발했습니다.
원래의 바이너리와 100% 일치하지는 않지만,
디스어셈블러보다는 압도적으로 분석 효율을 높여줍니다.
최근에는 Hex Rays, Ghidra 등의 뛰어난 디컴파일러들이 개발되었습니다.
따라서
바이너리 --디스어셈블--> 어셈블리어 --디컴파일--> 고급언어
이런 과정으로 번역된다고 볼 수 있습니다.
Static Analysis vs. Dynamic Analysis
- 정적 분석: 프로그램을 실행시키지 않고 분석하는 것
- 장점
- 프로그램의 전체 구조를 파악하기 쉽다.
- 분석 환경에 제약을 받지 않는다.
- 악성 프로그램의 위협을 받지 않는다.
- 단점
- 많은 개발자가 리버싱으로부터 보호하기 위하여 난독화 기법을 적용한다.
- 다양한 동적 요소(함수)를 고려하기 어렵다.
- 장점
- 동적 분석: 프로그램을 실행시키면서 동작을 분석하는 것
- 장점: 코드를 자세히 분석하지 않아도 프로그램의 개략적인 동작 파악이 가능하다.
- 단점: 분석 환경을 구축하기 어렵다. ( 프로그램 구동 가상 머신 필요, 안티 디버깅)
리버싱 응용 분야
- 악성코드 분석: 악성코드가 exe의 형태로 실행되면 어떤 행동을 하는지 파악
- DRM 등 보호 알고리즘 분석: 소프트웨어 복제 방지 기술
- 개발 효율성 증가:
- 안전성 테스트
- 응용 프로그램 패치: 소스파일이 없을 경우에 사용
결론은 리버싱은 개발자가 아닌,
사용자가 원하는대로 프로그램이 동작하게 하기 위하여
존재하는 기술이라는 점이다.
정보 보안 기술 모두 그렇겠지만,
절대로 윤리에 벗어난 목적으로 기술을 사용하면 안된다.