본문 바로가기

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

[26.05.01] 개구리버싱 4주차 활동

12강, 13강 NT Header

1. IMAGE_NT_HEADERS (NT Header)

  • 구성 요소: Signature, File Header, Optional Header
  • Signature: PE 파일임을 식별하는 "PE" (0x50450000) 값
  • 위치: DOS Header 및 DOS Stub 다음에 위치

1) Signature

- 값: "PE"

- PE 파일임을 나타내는 식별자

- DOS Header의 MZ와 같은 역할

 

2) IMAGE_FILE_HEADER         FileHeader;

<#1. Machine>

CPU 호환칩의 고유한 번호(정보 Intel 32bit 등)를 저장, CPU 종류를 구분

4C 01 -> 0x014C 저장

저장법) 리틀 엔디안 방식

 

<#2. NumberOfSections>

PE파일 섹션의 개수 (무조건 0보다 커야함..)

섹션의 개수와 실제 섹션의 개수가 다르면 실행 오류 발생

ex) NumberOfSection = 1;

     원래 Section = 3;이면 //오류

 

<#3. SizeOfOptionalHeader>

IMAGE_OPTIONAL_HEADER32의 크기.(32bit / 64bit 구조 차이 때문에 필요)

 

<#4. Characteristics> 🌟

PE 파일 속성 정보 저장 

여기서 파일 속성이란, 실행 가능한 형태(exe) 혹은 DLL(동적라이브러리)파일인지의 정보를 저장.(Bit OR로)

Characteristics 이 값이 없는 파일이 존재(obj, res, dll)

저장법) 비트플래그

 

3) IMAGE_OPTIONAl_HEADER32       OptionalHeader;

<#1. Magic>

IMAGE_OPTIONAL_HEADER32 10B

IMAGE_OPTIONAL_HEADER32 20B

구분자.

 

<#2. AddressOfEntryPoint>

EP(Entry Point)의 RVA(상대주소) 값

*EP는 상대주소만!!!!

프로그램의 최초로 실행되는 코드에 시작주소로 매우 중요.

 

<#3. ImageBase>

프로세스의 가상 메모리는 0~FFFFFF 범위.(32bit)

IB 이렇게 광활한 메모리에서 PE파일이 로드되는 시작주소를 나타냄. <—ImageBase

- 매커니즘 : PE 로더가 PE파일을 실행하기 위해 프로세스를 생성하고 파일을 메모리에 로드한 후 EIP(RIP) Reg 값을 ImageBase + AddressOfEntryPoint Point값으로 세팅하여 실행 시작.

*매핑은 메모리에 파일을 적재하는 것의 정의

 로드는 매핑을 실제로 하는 것.

**EIP는 CPU가 다음 실행할 명령어

EP vs. IB
IB는 실행파일이 로드될 때 BaseAddress(기본주소)를 나타내는 값
EP는 실행파일이 시작될 때 실행되는 함수의 주소를 나타내는 값
정리하면, IB와 EP는 모두 파일의 메모리에 로딩과 관련이 있지만
IB는 실행파일의 기본주소를, EP는 실행파일 내의 시작 함수의 주소를 나타냄.


<#4. SectionAlignment& FileAlignment>

PE파일의 바디 부분은 섹션으로 나뉨. 

파일에서 섹션의 최소단위를 나타내는 것이 FileAlignment

메모리에서 섹션의 최소단위를 나타내는 것이 SectionAlignment

 

<#5. SizeOfImage>

PE 파일이 메모리에 로딩되었을 때 가상메모리 PE IMAGE가 차지하는 크기. 일반적으로 파일의 크기와 메모리의 로딩된 파일의 크기는 다름.

*IMAGE 는 메모리에 로딩된 상태

 

<#6. SizeOfHeaders>

메모리 로딩 시 PE파일의 전체 크기.

 

<#7. Subsystem>

.sys인지 dll or exe인지 구분.(시스템 파일인지 아닌지를 구분)

 

<#8. NumberOfRvaAndSizes>

IMAGE_OPTIONAl_HEADER32의 마지막 멤버인 DataDirectory의 배열의 개수를 나타냄.

 

<#9. DataDirectory>

IMAGE_OPTIONAl_HEADER32의 배열(주요 데이터 구조 import, export 등의 위치/크기 정보를 담음)


14강 Section Header

  • 각 섹션 속성을 정의 (.code, .data, .rsrc)
  • 세가지로 나누어서 섹션을 저장하는 이유
    : 프로그램 복잡함 감소, 프로그램 안전성
    따라서, code/data/rsrc 마다 권한이 주어짐.
        - code : 실행, 읽기 권한
        - data : 비실행, 읽기 권한
        - rsrc : 비실행, 읽기 권한

1) IMAGE_SECTION_HEADER

<#1. DWORD VirtualSize>

메모리에서 섹션이 차지하는 크기

 

<#2. DWORD Virtual Address>메모리에서 섹션의 시작주소(RVA)

*VA 절대주소 아님.

 

<#3. DWORDSizeOfRawData> 

파일에서 섹션이 차지하는 크기

 

<#4. DWORD PointerToRawData>

파일에서 섹션의 시작주소(RVA)

 

<#5. DWORD Characteristics>

섹션의 속성을 저장(Bit OR)

//WORD Characteristics는 파일의 속성을 저장

 

15강 RVA to RAW(주소 변환)

  • 개념: 메모리 주소(RVA)와 실제 파일 내 오프셋(offset)을 잘 매핑하는 과정
  • 필요성: 메모리 상의 데이터 위치와 실제 파일 내 위치가 Alignment 차이로 인해 다름
  • RAW(File Offset)
    PointerToRawData : 파일에서 섹션의 시작위치

    VA(Virtual Address) : 메모리에서 섹션의 시작위치
  • 변환 공식 :
    RAW - PointerToRawData = RVA - VA
    RAW = RVA - VirtualAddress(섹션) + PointerToRawData(섹션)
  • 절차 :
    1. RVA 가 속한 섹션 찾기

    2. 공식을 이용하여 파일 오프셋(RAW)를 계산

[PE 파일 구조 전체 흐름]

DOS Header

  ↓

DOS Stub

  ↓

NT Header

  ├─ Signature (PE)

  ├─ File Header

  └─ Optional Header

  ↓

Section Header

  ↓

Section Data

  (.code, .data, .rsrc 등)