엔지니어링 vs 리버스 엔지니어링
프로그램
전처리(Preprocessing)
컴파일
-O -O0 -O1 -O2 -O3 -Os -Ofast -Og
어셈블
링크
디스어셈블
디컴파일러
정리
- 전처리: 소스 코드가 컴파일에 필요한 형식으로 가공되는 과정.
- 컴파일: 소스 코드를 어셈블리어로 번역하는 과정.
- 어셈블: 어셈블리 코드를 기계어로 번역하고, 실행 가능한 형식으로 변형하는 과정.
- 링크: 여러 개의 목적 파일을 하나로 묶고, 필요한 라이브러리와 연결해주는 과정.
- 디스어셈블: 바이너리를 어셈블리어로 번역하는 과정
- 디컴파일: 바이너리를 고급 언어로 번역하는 과정.
정적 분석
- 전체 구조를 파악하기 쉽다
- 프로그램을 실행하지 않아도 되므로 분석 환경의 제약에서도 비교적 자유롭다.
- 바이러스 등을 실행할 필요가 없으므로 악성 프로그램의 위협으로부터 안전하다.
- 프로그램의 코드를 변형하는 난독화가 적용되면 분석이 매우 어려워진다.
- 프로그램의 실행 흐름이 복잡할수록 정적 분석만으로는 다양한 동적 요소를 고려하기 어렵다.
동적 분석
코드를 자세히 분석해보지 않고도 프로그램의 개략적인 동작을 파악할 수 있다. 동적 분석을 통해 출력값들을 기반으로 동작을 추론하곤 한다. (대개의 프로그램은 많은 함수로 구성되어 있어 정적 분석만으로는 파악하는데 한계가 있다.)
- 동적 분석은 프로그램을 실행하면서 분석하는 것이므로 분석 환경을 구축하기 어려울 수 있다.
- 디버깅(동적 분석의 일종)을 방해하는 안티 디버깅에 의해 분석이 어려워질 수 있다.
서론
컴퓨터 구조
- 기능 구조에 대한 설계: 컴퓨터가 연산을 효율적으로 하기 위해 어떤 기능들이 컴퓨터에 필요한지 고민하고, 설계하는 분야
- 폰노이만 구조, 하버드 구조, 수정된 하버드 구조 등이 있다.
- 명령어 집합구조: CPU가 처리해야하는 명령어를 설계하는 분야
- x86, x86-64, ARM, MIPS, AVR 등이 있다.
- 마이크로 아키텍처: CPU의 하드웨어적 설계를 하는 분야.
- 캐시 설계, 파이프라이닝, 슈퍼 스칼라, 분기 예측, 비순차적 명령어 처리
- 하드웨어 및 컴퓨팅 방법론
- 직접 메모리 접근 등이 있다.
폰 노이만 구조
명령어 집합 구조(ISA)
x86-64(amd64) 아키텍처
레지스터
레지스터 호환
섹션
.text 섹션
.data 섹션
.rdata
섹션이 아닌 메모리
서론
0과 1로만 구성된 기계어는 해석하기 힘들기 때문에 어셈블리 언어와 어셈블러(어셈블리 언어를 기계어로 번역)가 고안됨.
이후 기계어를 어셈블리 언어로 번역하는 역어셈블러를 개발했다.
어셈블리어만 이해할 수 있다면 역어셈블러를 사용하여 소프트웨어를 분석할 수 있다.
어셈블리 언어
x64 어셈블리 언어
mov
, lea
inc
, dec
, add
, sub
and
, or
, xor
, not
cmp
, test
jmp
, je
, jg
push
, pop
call
, ret
, leave
syscall
타입 \[]
로 표현. 타입에는 Byte, Word, DWord, QWord가 올 수 있으며, 각각 1, 2 4, 8바이트의 크기를 지정한다.x86-64 어셈블리 명령어
mov rdi, rsi
: rsi의 값을 rdi에 대입mov QWORD PTR[rdi], rsi
: rsi의 값을 rdi가 가리키는 주소에 대입.lea rsi, DWORD PTR[rdi]
: rid가 가리키는 주소를 rsi에 대입.add dst, src
: dst += srcsub dst, src
: dst -= srcinc op
: op += 1dec op
: op -= 1and dst, src
: dst와 src가 모두 1이여야 1or dst, src
: dst와 src 중 하나라도 1이면 1xor dst, src
: dst와 src가 서로 다르면 1not op
: op의 비트 전부 반전cmp op1, op2
: op1과 op2를 빼서 대소를 비교. test op1, op2
: op1과 op2에 AND 비트 연산을 취하여 비교한다.jmp addr
: addr로 rip를 이동.je addr
: 직전에 비교한 두 연산자가 같으면 점프jg addr
: 직전에 비교한 두 연산자 중 전자가 더 크면 점프스택과 관련된 명령어
push val
: rsp를 8만큼 빼고, val을 스택 최상단에 쌓음.pop reg
: 스택 최상단의 값을 꺼내서 reg에 대입히고 rsp를 8만큼 더함.프로시저의 호출과 반환을 위한 명령어
call addr
: addr에 위치한 프로시져 호출leave
: 스택프레임 정리ret
: return address로 반환