본문 바로가기

2. Reversing (리버싱)/2) 개념 정리

[26.04.03] 개구리버싱 2주차 활동


<5강: 스택>

-스택(Stack): 메모리 내에 존재

스택은 함수 동작을 이해하기 위해 필수
특히 함수 실행 시:
로컬 변수(함수 내부 변수) 저장
매개변수(parameter) 전달
리턴 주소(복귀 주소) 저장
-> 함수 실행과 직접적으로 연결된 메모리 구조

*스택의 특징
LIFO(FILO) 구조
(Last In First Out)
ex)
push A → push B → push C
pop 하면  C → B → A 순서로 나옴

push: 데이터 넣기
pop: 데이터 꺼내기
항상 위(top)에서만 넣고 빼는 구조

스택포인터 esp(유동), esp의 값을 저장하는 ebp(고정)
스택에 값을 넣는 push 명령어, 스택의 값을 빼는 pop 명령어
Stack Frame


<6강: Stack Frame>

-스택프레임: ESP가 아닌 EBP를 이용하여 스택 내의 변수 파라미터 복귀 주소에 접근하는 기법

ESP는 함수 실행 중 계속 변함 -> 기준으로 쓰기 어려움
반면 EBP는 고정된 기준점 역할 -> 안정적으로 스택 데이터를 참조

-예시) [Assembly Code]

PUSH EBP ;함수시작 EBP 백업 -> 스택
MOV EBP, ESP ;ESP백업, EBP에 저장
. ;함수 로직
. ;여기서 ESP가 변경되어도 괜찮음
.
MOV ESP, EBP ;ESP 복원
POP EBP ;EBP 복원
RETN ;함수 종료

>>> ESP값이 아무리 변해도 EBP를 기준으로 안전하게 해당 변수나 파라미터, 복귀주소에 접근이 가능
*스택에 데이터가 저장되는 것이 보안상 취약할 수 있음.

*함수 실행 흐름
(1) 함수 시작
push ebp
mov ebp, esp
기존 EBP 값을 스택에 저장
현재 ESP를 EBP에 복사 → 기준 설정
(2) 함수 실행 중
지역 변수 생성, push/pop 등으로 ESP는 계속 변함
하지만 EBP는 변하지 않음
따라서 EBP를 기준으로 다음에 접근 가능: 지역 변수 / 매개변수 / 복귀 주소
(3) 함수 종료
mov esp, ebp
pop ebp
ret
ESP를 원래 상태로 복구
EBP도 복구
함수 종료 후 원래 위치로 돌아감

* 보안 관점
스택에 중요한 정보가 저장되기 때문에 스택이 조작되면 문제가 발생할 수 있다.
예: 스택 오버플로우 공격


<7강: 크랙미 실습>

-코드엔진 Basic L01 문제 풀이

1. 문제 개요
실행 파일을 분석해서 올바른 조건을 만족시키면 성공 메시지 출력
기본 실행 시 → 에러 메시지 출력 후 종료

2. 분석 과정
(1) 디버거로 실행
x64dbg로 실행 후 엔트리 포인트 진입
주요 흐름: MessageBox 호출 (문자 출력) / GetDriveTypeA 호출 / 결과값을 비교하는 cmp 존재
(2) 핵심 구조 파악
프로그램 내부에는 분기 구조가 있음:
성공 분기
실패(에러) 분기
cmp 결과에 따라 분기
조건이 맞으면 성공 메시지
틀리면 에러 메시지 + 종료

3. 실패 원인
cmp 결과 → 0이 아님
따라서 Zero Flag = 0
je (jump if equal) 실행 안 됨
→ 실패 분기로 이동

4. 해결 방법 (핵심)
방법 1: 실행 흐름 강제 변경 (EIP 조작)
치트엔진 사용
EIP를 성공 주소로 강제로 변경
→ 바로 성공 코드 실행
방법 2: 조건문 패치
je: 조건 만족 시 점프
mp: 무조건 점프
→ 조건 무시하고 성공 분기로 이동

5. 핵심 개념 정리
cmp + je 구조
cmp: 값 비교
결과가 같으면 → Zero Flag = 1
je: Zero Flag = 1일 때만 점프
Zero Flag 연산 결과가 0이면 1로 설정 0이 아니면 0
jmp 조건 없이 무조건 점프

6. 결론: 이 문제의 본질:조건을 만족시키는 것이 아니라 분기 흐름을 강제로 바꿔서 성공으로 보내는 것



<8강: 함수 호출 규약>

-함수 호출 규약(Calling Convention): 함수를 호출할 때 매개변수(파라미터)를 어떤 식으로 전달하는가에 대한 일종의 약속
* 기본 용어
Caller (호출자): 함수를 호출하는 쪽
Callee (피호출자): 호출당하는 함수

Cdecl: C언어에서 사용되는 방식/ Caller에서 스택을 정리함
*동작 흐름:
매개변수를 스택에 push
함수 호출
함수 실행 후
Caller가 스택 정리

Stdcall: Win32 API에서 사용되는 방식/ Callee에서 스택을 정리함
* 동작 흐름:
매개변수 push
함수 호출
함수 내부에서 스택 정리 후 return

fastcall: (Stdcall과 유사)
x64아키텍처에서 사용되는 방식/ 매개변수를 최대 2개까지 레지스터 ECX EDX RDX RCX를 이용하여 전달, 나머지는 스택으로 정리-> 레지스터를 이용하여 호출이 더 빠름
* 동작 방식:
최대 2개 정도의 매개변수:
ECX, EDX (32비트)
RCX, RDX (64비트)
나머지 → 스택