[정보 보안] 리버스 엔지니어링 3편 : 리버싱에 필요한 기초 구조 이해

Cookie·2025년 7월 31일
0

정보보안

목록 보기
39/40
post-thumbnail

2편의 기본 개념과 분석 방식 내용의 다음으로 리버싱의 기본적인 원리와 구조 대해 정리하고 파악함




🫧프로그램 동작 구조 파악

프로그램 분석에서 프로그램이 실행될 때 어떤 모듈이 먼저 로딩되고, 어떤 함수가 호출되는지 구조를 파악하는 것이 중요함

프로그램 내부구조(PE 헤더), 로딩되는 라이브러리, 진입점(Entry Point) 등의 정보를 파악해야 함


전체 적인 흐름 요약

[1] PE 구조 분석 → 어떤 섹션이 존재하는지

[2] Entry Point 확인 → 프로그램의 시작점 찾기

[3] Import Table 분석 → 어떤 기능(API)을 사용하는지

[4] 동적 분석(promon 등) → 실행 중 DLL 및 파일 동작 추적



🔸PE(Portable Executable)구조 이해

Windows에서 실행되는 대부분의 실행 파일(.exe,.dll)은 PE포맷으로 구성되어 있음

구성 요소설 명
DOS Header맨 앞에 위치하고 "This porogram cannot be run in DOS mode" 메시지가 포함되어있음
PE Header본격적인 구조 시작점으로 파일의 전반적인 정보를 담고 있음
Section Header.text, .data, .rdata 등 실제 코드, 데이터가 있는 영역 정보
Optional HeaderEntry Point 주소, ImageBase, Stack/Heap 크기 등 실행에 필요한 정보 포함

예시 흐름

파일 로딩DOS HeaderOptional HeaderEntry Pint 주소Section (.txext 등) 진입



🔸섹션(Section) 분석

PE 구조에서 섹션은 프로그램의 코드, 데이터, 리소스, 심볼 등을 분리 저장하는 공간

섹 션설 명
.text실행 가능한 기계어 코드
.data초기화된 전역/정적 변수
.rdata읽기 전용 데이터 (ex: 상수, API 이름)
.idataImport Table: 어떤 외부 라이브러리를 사용하는지에 대한 정보
.rsrc리소스(아이콘, 이미지, 문자열 등)
.reloc재배치 정보(ASLR 관련)

.idatardata는 API 함수 분석에 유용
.rsrc는 가짜 리소스나 악성 페이로드가 숨겨질 수 있는 공간



🔸Import Table, 라이브러리 의존성 분석

외부 라이브러리(DLL)의 함수(API)를 어떻게 호출하는지 확인
이 정보는 프로그램이 어떤 기능을 사용하는지 빠르게 파악할 수 있게 해줌


주요 분석 포인트

  • 어떤 DLL이 필요한가
  • 어떤 API를 호출하는가
  • Forwarding 되는 함수나 API Hooking 흔적은 없는가



🔸Entry Point 추적

Entry Point는 프로그램이 실행될 때 최초로 실행되는 코드 주소이자 진입점
보통은 main() 함수 이전의 초기화 루틴(C/C++ 런타임 초기화 등)이 존재함


확인 방법

  • PE-Bear,IDA,x64dbg에서 Entry Point 주소 확인 가능
  • 디버깅 시 EP에서 BreakPoint를 설정하여 초기 실행 흐름 분석 시작
.text:00401000; Entry Point
call  sub_401050

❗ 악성 코드나 보호된 실행파일은 진짜 EntryPoint가 숨겨져 있는 경우가 있음 이 경우 packer로 감싸져 있으며 진짜 EP는 언패킹 후 메모리 상에 존재함



🔸활용 도구 예시

목 적도 구
PE 구조 확인PE-Bear, CFF Explorer
DLL 의존성 확인Dependency Walker
Entry Point 추적x64dbg, IDA Free
실행 중 동작 분석procmon, Process Hacker




🫧메모리, 레지스터, 스택의 역할

리버싱에서 프로그램이 어떤 값을 저장하고, 어디로 흐르며, 무엇을 연산하는지 파악하려면 레지스터(임시 저장소), 스택(함수 호출 관리), 메모리(데이터 저장) 3요소의 역할을 정확히 이해해야 함


🔹레지스터(Register)

레지스터는 CPU 내부의 아주 빠른 임시 저장소로 연산, 함수 반환, 루프 카운터, 조건 비교 등 거의 모든 실행 흐름에 직접 관여함


🔍대표적인 32bit 레지스터(x86 기준)

레지스터역 할레지스터역 할
EAX연산 결과 저장, 함수 반환값 저장ESI / EDI문자열 처리, 배열 이동 시
EBX범용EBP함수 프레임 기준 포인터
ECX반복문 카운터(loop 명령에서 사용)ESP스택 포인터(핸재 스택 꼭대기)
EDXI/O, 곱셈 나눗셈에 사용EIP다음 실행 명령 주소(제어 흐름)

✅분석 팁

  • EAX의 값을 보면 함수의 반환값이 뭔지 알 수 있음
  • ESP, EBP는 스택 구조 파악에 매우 중요함
  • EIP를 추적하면 프로그램 흐름을 제어 가능 (breakpoint, jump 등)



🔹스택(Stack)

스택은 함수 호출, 지역 변수, 리턴 주소, 인자 전달 등에 사용되는 후입선출(LIFO) 메모리 구조


🔍 함수 호출 시 스택의 동작

push arg1
push arg2
call function	; 스택에 return address 자동 push
  • 함수 시작 시 : push ebpmov sbp, esp → 지역 변수 공간 확보 (sub esp, N)
  • 함수 종료 시 : mov esp, ebppop ebpret

🔍 스택 프레임 예시

  • [ESP+0x00] → 리턴 주소
  • [ESP+0x04] → 인자 1
  • [ESP+0x08] → 인자 2
  • [EBP-0x04] → 지역 변수 1

💡 스택의 구조를 이해하면, 함수 내 변수, 전달값, 리턴 주소 등을 쉽게 추적할 수 있음

✅분석 팁

  • EBP는 함수의 기준점 → EBP-4,EBP+8 등으로 변수와 인자 추적
  • 스택 오버 플로우, 버퍼 위치 등 취약점 분석에도 필수적



🔹메모리

프로그램에서 사용하는 모든 데이터는 메모리에 올라가며, 전역 변수, 힙 할당된 객체, 문자열, 구조체, 함수 테이블 등 다양하게 존재함


🔍 메모리 영역

영 역설 명
.text실행 코드(기계어)
.data초기화된 전역 변수
.bss초기화되지 않은 전역 변수
.rdata상수 문자열, 읽기 전용 데이타
Heap동적 할당 영역(malloc, new 등)
Stack함수 실행 시 자동 생성/삭제 되는 공간

✅분석 팁

  • 문자열이 평문으로 들어 있는 경우 .rdata,.data에서 검색 가능
  • Heap에서 할당된 구조체, 객체 등은 동적 분석으로 추적
  • 악성코드는 VirtualAlloc등을 통해 코드 자체를 메모리에 동적 생성하기도 함



🔹디버거에서 메모리 관찰

디버거에서는 레지스터, 스택, 메모리 구조를 실시간으로 관찰 가능


주요 디버깅 기능

기 능설 명
Register 창EAX 등 값 실시간 확인 및 수정 가능
Stack 창현재 스택 상태, 인자, 리턴 주소 추적 가능
Memory Dump특정 주소에 어떤 데이터가 있는지 확인
Follow in Dump특정 포인터 값 따라가기 (ex: 문자열 주소 추적)
Breakpoint특정 레지스터/메모리 변화 시 중단




🫧암호화, 난독화 기법의 기본 이해

악성코드, 상용 프로그램 보호, 크랙 방지 목적 등으로 사용되며 분석자가 정적/동적 분석을 하지 못하도록 코드나 데이터를 숨기거나 흐름을 꼬아놓는 기법


🔹암호화 (Encryption)

주로 문자열, API 이름, DLL 경로, 키 값 등을 평문으로 보이지 않도록 인코딩함 코드 실행시 메모리에서 복호화(Decryption) 과정을 통해 원래 값으로 복원됨


🔍 대표적인 암호화 대상

대 상예 시
문자열"cmd.exe", "CreateProcessA" 등
쉘코드공격용 페이로드
구성 파일C2 서버 주소, 사용자 정보 등
함수 이름API 이름 숨기기 (kernel32.dll, LoadLibraryA 등)

✅분석 전략

  • 복호화 루틴을 찾고, 해당 루틴 실행 이후의 결과를 메모리에서 확인
  • 암호화 알고리즘: XOR, RC4, AES, Base64 등 다양함
  • 복호화 위치는 대부분 call 직후 혹은 mov 이후 메모리에 저장됨

🔧 예시 (XOR 암호화 복호 루틴)

mov ecx, len
mov esi, encoded_string
mov edi, decoded_buf
xor_loop:
	mov al, [esi]
    xor al, 0x55
    mov [edi], al
    inc esi
    inc edi
    ioop xor_loop
  • 실행 후 decoded_buf 주소를 dump에서 보면 평문 문자열을 확인 가능



🔹난독화

암호화가 데이터를 숨기는 거라면, 난독화는 코드 흐름 자체를 꼬는 행위로 사람이 분석하기 어렵도록 구조를 복잡하게 만들고, 논리적 흐름을 숨김


🔍대표적인 난독화 방식

기 법설 명
Junk Code 삽입분석 시간 낭지 유도 ( [add eax, 0], [nop], [jmpnext])
API Call 우회GetProcAddress + 문자열 복호로 간접 호출
Control Flow Flatteningswitch-case 나 상태머신처럼 실행 흐름 분산
Self-Modifying Code코드가 실행 중에 자신을 수정함

✅분석 전략

  • 제어 흐름 추적이 가장 중요함: EIP, call, jmp 경로 관찰
  • 반복되는 XOR, shift 연산, jump table 등 → 루프 구조 분석
  • 코드를 메모리에서 덤프하고 IDA 등으로 복호화된 영역 리로드
  • 함수 실행 후 Memory, Dump, Disasm 동시 비교



🔹언패킹

암호화∙난독화 바이너리는 실제 실행 코드가 압축/암호화 상태로 이를 실행 중에 복호화된 시점에서 덤프해 복원하는 과정을 언패킹이라 함


🔍대표적인 언패킹 방식

방 법설 명
Dump 후 수동 재정렬OEP 진입 이후 전체 영역 덤프 + IAT 복원
Scylla, ImpRec자동화된 IAT 복원 도구
Dynamic Instrumentation실행 중 특정 함수 호출 후 덤프

✅실전 팁

  • ESP에 저장된 리턴 주소 확인 → 원래 진입점 (OEP) 추적 가능
  • 메모리 상에서 .text 섹션이 복원된 순간을 dump로 저장
  • Anti-debug 기능 우회 후 언패킹 도전
profile
나만의 공부 일지... [임시 休]

0개의 댓글