작은 메모장

PE 파일 개론 본문

KISA 사이버 보안 훈련/멀웨어 식별

PE 파일 개론

으앙내눈 2024. 7. 23. 14:50

PE 파일의 주요 자료구조

PE의 개괄적 구조와 실행 전후 변화

PE 파일, 즉 PE-COFF 파일은 EXE, DLL, SYS 확장자를 가진 파일의 포멧이다.

파일 확장자에서도 알 수 있듯, 윈도우 운영체제에서 주로 사용되는 파일들의 파일 형식이다.

때문에, 주로 동적 라이브러리 정보, API Import/Export 정보, 실행 관련 코드, 실행 관련 리소스 정보 등을 구조화하고 관리하는 목적으로 쓰인다.

PE 파일은 실행 전과 실행 후의 차이가 거이 없으며, 가상메모리에 매핑된 후에도 레이아웃에 큰 변화가 없는 것이 특징이다.

 

PE 파일은 하나의 헤더와 여러개의 섹션으로 이루어진 형태를 띤다.

섹션은 딱히 정해진 갯수가 없다. 파일이 필요로 하는 데이터들의 분류가 많으면 많을수록 섹션은 늘어난다.

 

크게 중요한 내용만 확인하면 다음과 같다.

  • ImageBase: 헤더에 존재. 해당 PE파일이 메모리에서 매핑되는 시작 주소.
  • AddressOfEntryPoint: 헤더에 존재. PE파일이 매핑된 이후 가장 먼저 실행될 코드 위치값.
  • ".text" 섹션: 컴파일 된 기계어 코드가 모여있는 섹션. 즉, 바이너리 값이 들어있음.
  • ".data" 섹션: 식별 가능한 전역 변수, 즉 문자열이 모여있는 섹션.
  • ".idata" 섹션: DLL 이름 및 API 이름이 기록되어 있는 섹션. 보통 EXE 파일 내에 존재하며, 섹션의 내용으로 해당 실행파일의 기능을 추측할 수 있는 특징이 있음.
  • Padding: 파일과 메모리의 시작지점, Alignment가 다른 경우 디스크 -> 메모리로 옮겼을 때 사이즈가 다를 수 있다. 이를 대비하기 위한 여유 공간.

 

운영체제를 공부했다면 알고 있는 내용이지만, 운영체제는 페이지(Page)라는 가상 메모리에서의 공간 단위로 관리한다.

PE 파일이 실행되면 해당 페이지에 로드되어 파일이 실행되는데, 보통 다음의 과정을 거친다.

  1. PE 파일의 헤더가 먼저 읽힌다. 헤더에는 섹션에 대한 각종 정보가 담겨있는데, 이를 섹션 테이블이라고 하며 테이블을 기준으로 운영체제가 파일의 정보를 파악, 다음 페이지부터 섹션을 저장한다.
    해당 페이지는 오직 읽기(r)권한만 부여된다.
  2. 가장 먼저 .text 섹션이 페이지에 매핑된다. 해당 섹션은 실행 코드가 바이너리, 즉 기계어로 저장된 섹션이므로 코드가 직접적으로 실행될 페이지다.
    따라서, 해당 페이지는 읽기(r)와 실행(x)권한이 부여된다.
  3. 두번째로는 .data 섹션이 그다음 페이지에 매핑된다. 해당 섹션은 실행하는 데이터는 아니지만, 전역 변수의 값이 저장되어 있기 때문에 실행에 필요한 주요 값을 담은 페이지가 된다.
    따라서, 해당 페이지는 읽기(r)와 쓰기(w)권한이 부여된다.
  4. 마지막으로 .idata 섹션이 그다음 페이지에 매핑된다. API, DLL 이름이 담겨지는 섹션으로, 통상적으로 실행할 때 참조용으로 많이 사용되는 페이지다. 그러나 실행에 있어 함수의 주소 변화등의 이유로, 메모리에 매핑될 시 구조가 달라지는 경우가 있다. 즉, 디스크에서 메모리로 매핑될 시 섹션의 값이 조금 변형될 수 있는 페이지다.
    따라서, 해당 페이지는 읽기(r)와 쓰기(w)권한이 부여된다.

 

PE 헤더

PE 헤더는 IMAGE_NT_HEADER의 구조를 하고 있으며, 크게 3부분으로 나뉜다.

Signature PE는 해당 헤더의 시작임을 알리는 문자열로, 시그니처인 "PE00" 문자열로 시작된다.

IMAGE_FILE_HEADER는 파일의 실행 가능 여부 및 다른 중요한 속성을 나타내는 곳이다. 쉽게말해, 파일의 기본 속성을 정의하고 실행 가능 여부를 확인하는 곳이다.

IMAGE_OPTIONAL_HEADER는 이미지를 메모리에 올릴 때 중요한 정보를 담고 있다. 가상 주소 공간에 올릴 공간 및 코드 실행 위치 등 메모리 매핑 및 파일 실행과 관련된 중요한 정보를 담고 있다.

 

IMAGE_OPTIONAL_HEADER에서 중요한 요소들을 몇 가지 꼽으면 다음과 같다.

  • ImageBase: 실행 파일이 로드될 가상 주소공간의 주소
  • AddressOfEntryPoint: 메모리에 로드된 후 가장 먼저 실행될 코드의 위치
  • FileAlignment: PE 파일의 주요 요소들의 주소 시작 위치 결정
  • SectionAlignment: 메모리 상에서 각 섹션의 정렬 단위

 

섹션 테이블

섹션 테이블은 파일의 데이터 섹션을 설명하는 메타데이터를 포함하는 섹션이다.

섹션 헤더라고도 불리며, 전체 PE 파일의 섹션에 대한 정보를 포함하고 있다.

 

통상적으로 섹션 테이블은 PE 헤더 바로 뒤에 위치하고 있으며, 각 섹션에 대해 여러 정보를 제공한다.

이를테면, 각 섹션의 이름, 크기 및 시작위치 등의 정보를 제공하며, 메모리에 로드할 때 섹션을 직접 제공하지 않고도 필요한 정보를 탐색할 수 있게 도와주는 역할을 한다.

이를 통해 실행 파일이 올바르게 동작할 수 있도록 보조해주며, 로더는 이 섹션 테이블을 바탕으로 코드 실행 및 데이터 접근이 가능하게 된다.

 

섹션 테이블에서 중요한 요소들을 몇 가지 꼽으면 다음과 같다.

  • VirtualAddress: 섹션의 메모리 내 가상 주소. PE 파일이 로드된 후 섹션이 메모리 내에서 시작되는 위치를 의미한다.
  • PointerToRawData: 파일 내 섹션 데이터의 시작 위치를 바이트 단위 오프셋으로 표현
  • Characteristics: 섹션의 속성을 나타내는 플래그. 예를 들어, 섹션이 읽기, 쓰기, 실행 가능한지 여부를 나타낸다.