<1강 리버싱 OT 및 분석 방법론>
1. 리버싱이란? 역공학
RE(Reverse Engineering) : 역공학의 총칭
= RCE(Reverse Code Engineering) : 소프트웨어 실행 파일 분석에 특화된 역공학
2. 리버싱 분석 방법
- 정적 분석
-파일을 실행하지 않고 분석하는 방법
-파일의 겉모습(Header, String, Import Table)을 분석 / 전체 구조 파악에 용이함. (ex. IDA, DIE)
- 동적 분석
-(디버거로) 파일을 실행하고 분석하는 방법 / 메모리, 레지스터의 실시간 변화를 관찰
-내부 파일까지 깊이 들어가서 분석, 관찰 (ex. Cheat Engine, Ollydbg, x64dbg)
3. 데이터 표현 단계
- 소스코드: 개발자가 작성한 고수준 언어
>> printf(“Hello, World!”)
- Hex code : 기계어를 16진수로 표현한 형태
>> 45 46 44 43
- assembly code : 기계어와 1:1 대응되는 최하위 수준의 인간 가독형 언어
>> mov eax, ebx / add1
4. 패치(Patch)와 크랙(Crack)
패치란? 프로그램의 동작 수정을 위해 프로세스의 메모리나 파일의 코드를 변경하는 것
크랙이란? 불법적인 메모리 수정, 비도덕적인 목적으로 행해지는 패치
<2강 Hello World 분석 및 디버거 활용>
1. 프로그램 빌드 과정
전처리(Preprocessing) → 컴파일(Compile) → 어셈블(Assemble) → 링킹(Linking)
2. 디버깅 목적
Hello World 실행 파일을 디버깅하여 어셈블리 언어로 변환 > main 함수 탐색
이 과정을 통해 기본적인 디버거의 사용법과 어셈블리 명령어 체계를 알아 보는 것
3. 디버거 핵심 개념 (x64dbg 사용)
- 엔트리 포인트 (EP) : 운영체제(OS)가 프로그램을 메모리에 올린 후 제어권을 넘겨주는 공식적 시작 주소
- 브레이크 포인트 (BP) : 특정 코드의 동작을 확인하거나 변수값을 조사하기 위해 실행 흐름을 멈추게 하여 상태를 조사하는 도구
4. 실습 및 기능 활용
-문자열 변조 : 메모리 상의 문자열 주소를 찾아 데이터를 수정함으로써 실행 결과 변경 가능
-주요 단축키 : Ctrl+G (특정 주소 이동), Space바 (어셈블리 코드 직접 수정)
<3강 바이트 오더링(Byte Ordering)>
1. 바이트 오더링이란?
데이터를 메모리에 저장할 때 바이트(8 bits) 단위의 배치 순서를 결정하는 규칙
2. 빅 엔디안(Big-Endian) vs. 리틀 엔디안(Little-Endian) -> MSB(가장 큰 자릿수)를 어디에 두느냐
- 빅 엔디안
-저장 방식 : MSB(가장 큰 수)를 낮은 주소부터 저장, 사람이 읽는 순서와 동일.
-특징 : 데이터의 순서가 직관적이라 디버깅 시 사람이 읽기 용이.
-주요 사용 : 네트워크 프로토콜(TCP/IP), 대형 메인 프레임 등
- 리틀 엔디안
-저장 방식 : LSB(가장 작은 수)를 낮은 주소부터 저장, 바이트 단위로 역순 배치됨
-특징 : Intel x86/x64 CPU의 기본 방식. 산술 연산 시 하위 바이트부터 계산하므로 물리적 회로 설계상 효율적임.
3. 리버싱 실습 포인트!
- 메모리 덤프 확인 : 디버거에서 보이는 메모리와 실제 값, 즉시 치환 가능해야함.
- 문자열 예외 : 숫자는 엔디안의 영향을 받아 뒤집히지만, 문자열은 배열 형태이므로 엔디안의 영향을 받지 않고 정방향으로 저장됨
- 주소값 분석 : 점프문이나 포인터가 가리키는 주소 역시 리틀 엔디안으로 기록됨을 인지해야 함.
- 수치 데이터: 리틀 엔디안 방식에 따라 메모리 덤프를 역순으로 조합해야 실제 값을 얻을 수 있음.
4. 리버싱 중요성 강조 !!
1) 값의 변조: 특정 변수값을 찾으려 할 때, 리틀 엔디안 방식을 모르면 메모리에서 해당 값을 찾을 수 없음
2) 포인터 분석: 점프할 대상 주소(Adress) 역시 리틀 엔디안으로 저장됨
<4강 레지스터(Register)>
1. 레지스터의 역할
: CPU 내부에 위치한 초고속 임시 저장소. 명령어 실행에 따라 가장 빈번하게 값이 변하는 지점
★ 리버싱 포인트 : 디버거로 프로그램을 한 줄씩 실행 시, 가장 먼저 변함
2. 범용 레지스터
: 가장 자주 쓰이는 8개 레지스터 (32비트 기준)
- 범용 레지스터의 종류
-EAX: 산술 연산 수행 및 함수의 리턴값 저장
-ECX: 반복문(Loop)을 돌 때 횟수 카운트
-EDX: EAX를 보조하여 큰 숫자의 곱셈/나눗셈을 도움
-ESP: 현재 스택의 가장 윗부분 주소
-EBP: 함수의 시작 지점 주소를 고정해서 가리킴 (스택 프레임의 기준점)
-ESI / EDI: 주로 데이터를 복사할 때 각각 ‘출발지’와 ‘목적지’ 주소를 저장
3. 플래그 레지스터 (EFLAGS)
: 숫자가 아니라 ‘상태’ 저장 / 비트(0 또는 1) 단위로 기록되며 조건문을 분석할 때의 핵심
- ZF(Zero Flag) : 연산 결과가 0일 때, 1(True)이 됨 / 두 값을 비교(CMP)했을 때 일치하면 결과가 0이 되므로 ZF가 세팅
- CF (Carry Flag): 연산 중 자릿수 올림/내림이 발생할 때 세팅
- SF (Sign Flag): 연산 결과가 음수일 때 세팅
★ 리버싱 포인트 : JZ(Jump if Zero) 같은 명령어는 ZF 플래그를 보고 점프할지 말지(실행여부)를 결정함. 크랙을 할 때 이 플래그를 강제로 조작하기도 함.(리버싱의 핵심 기법)
4. 세그먼트 레지스터(Segment Register)
: 메모리를 용도별로 구획화하여 효율적으로 관리하기 위한 특수 포인터
- CS (Code Segment): 현재 실행 중인 기계어 코드가 저장된 메모리 영역을 가리킴.
- DS (Data Segment): 프로그램의 전역 변수나 정적 데이터가 위치한 영역을 가리킴.
- SS (Stack Segment): 함수 호출 시 사용하는 스택 메모리 영역의 시작 주소를 가리킴.
- ES/FS/GS: 추가적인 데이터 저장이나 운영체제별 특수 목적(예: 윈도우의 TEB/PEB 정보 접근)을 위해 사용됨.
5. 실습의 핵심 : 변화 관찰(Tracing)
1) 명령어 실행: MOV EAX, 1 실행하면?
2) 레지스터 확인: 디버거 창의 EAX 값이 즉각적으로 00000001로 갱신되는 것을 디버거의 Register 창에서 실시간 확인
3) 프로그램 흐름(Control Flow) 파악:
-비교 연산 : CMP EAX, EBX 명령 실행 시, 두 값의 차이에 따라 변하는 EFLAGS(특히 ZF,SF)의 상태를 분석.
-분기 판단 : 현재 플래그 상태를 바탕으로 다음에 올 JMP, JZ, JNZ 등의 분기문이 실행될지 여부를 예측하여 프로그램의 전체적인 로직 파악.
-메모리 덤프 활용 : 특정 주소의 값이 의도한 대로 변경되었는지 메모리 맵을 통해 검증하고, 코드 패치(Patch)의 성공 여부를 판단.
'2. Reversing (리버싱) > 2) 개념 정리' 카테고리의 다른 글
| [26.04.03] 개구리버싱 2주차 활동 (0) | 2026.04.03 |
|---|---|
| [2025.05.24] 리버싱난다_6주차 활동 (5) | 2025.05.30 |
| [2025.05.17]리버싱난다_5주차 활동 (2) | 2025.05.22 |
| [2025.05.10] 리버싱난다_4주차 활동 (0) | 2025.05.14 |
| [2025.04.05] 리버싱난다_3주차 활동 (0) | 2025.04.10 |