본 게시글은 책 <악성코드 분석 시작하기> 의 내용을 정리한 글 입니다.

 

악성코드 분석 시작하기 : 네이버 도서

네이버 도서 상세정보를 제공합니다.

search.shopping.naver.com

1.6 PE 헤더 정보 조사

- 윈도우 실행 파일은 PE/COFF (Portable Executable/Common Object File Format)를 반드시 준수해야 함

 

- PE 파일 포맷

> 윈도우 실행 파일(.exe, .dll, .sys, .ocx, drv)이 사용

> 운영 시스템이 메모리로 로딩할 때 필요한 정보를 가진 일련의 구조체와 하위 컴포넌트

 

- 실행 파일을 컴파일하면 해당 구조체를 설명하는 헤더 (PE 헤더)를 포함

> 실행 파일이 메모리에서 실행될 위치

> 실행 파일의 시작 위치

> 애플리케이션이 의존하는 라이브러리/함수 목록

> 바이너리가 사용하는 리소스와 같은 정보가 포함

 

- PE 파일 구조체를 이해하기 위한 유용한 자료 링크 
> Win32 PE 파일 포맷에 대한 심층적인 조사 - 파트 1 : https://www.delphibasics.info/home/delphibasicsarticles/anin-depthlookintothewin32portableexecutablefileformat-part1
> Win32 PE 파일 포맷에 대한 심층적인 조사 - 파트 2 : https://www.delphibasics.info/home/delphibasicsarticles/anin-depthlookintothewin32portableexecutablefileformat-part2
> PE 헤더와 구조 : https://www.openrce.org/reference_library/files/reference/PE%20Format.pdf
> PE101 - 윈도우 실행 파일 공략 : https://github.com/corkami/pics/blob/master/binary/pe101/pe101ko.pdf

 

- PE 구조와 그 하위 컴포넌트를 검사하고 수정할 수 있는 몇 가지 도구 
> CFF Explorer : https://ntcore.com/explorer-suite/

> PE Internals : https://www.andreybazhan.com/pe-internals.html

> PPEE(puppy) : https://www.mzrst.com/
> PEBrowse Professional : https://download.cnet.com/developer/smidgeonsoft/i-6276008

파일 의존성과 임포트 조사

- 악성코드는 파일, 레지스트리, 네트워크 등과 상호작용하며, 이를 위해 운영 시스템에서 제공하는 함수에 많이 의존

- 윈도우는 API로 불리는 함수를 임포트하며, 상호작용을 위해 동적 링크 라이브러리 (DLL, Dynamic Link Library) 파일이 필요

> DLL에서 여러 함수를 임포트 (Import) 하거나 호출

> 악성코드가 의존하고 있는 DLL과 그런 DLL이 임포트하고 있는 API 함수를 조사하면 악성코드의 기능과 성능, 실행 중 예상할 수 있는 기능을 알 수 있음

 

- 윈도우 실행 파일의 파일 의존성은 PE 파일 구조의 임포트 테이블에 저장

> pestudiolibraries 버튼을 클릭하면 의존성을 가진 모든 DLL 파일과 각 DLL에서 임포트한 함수의 수를 보여줌

> imports 버튼을 클릭하면 DLL에서 임포트한 API를 표시

- 때때로 악성코드는 LoadLibrary() 또는 LdrLoadDLL()과 같은 API를 호출해서 실행 중 명시적으로 DLL 로드 가능

- 또는, GetProcAddress() API를 사용해 함수 주소를 확인할 수 있음

> 실행 중 로드한 DLL의 정보는 PE 파일의 임포트 테이블에 나타나지 않음

> 윈도우 API 함수와 그 함수의 기능 정보 참고 : https://learn.microsoft.com/ko-kr/search/

 

- Python을 이용해 DLL 파일과 임포트한 함수를 나열할 수 있으며, pefile 모듈을 사용

import pefile
import sys

# 명령행 인자 체크
if len(sys.argv) != 2:
    print("Usage: python script.py <filename>")
    sys.exit(1)

mal_file = sys.argv[1]


def enum_import(mal_file):
    try:
        # PE 파일 로드
        pe = pefile.PE(mal_file)
        
        # Import Table이 존재하는지 확인
        if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
            print(f"[+] {mal_file} Import Table Found")
            for entry in pe.DIRECTORY_ENTRY_IMPORT:
                print(f"DLL : {entry.dll.decode('utf-8')} ({len(entry.imports)})")
                for i, imp in enumerate(entry.imports):
                    if imp.name is not None:
                        print(f"  {i + 1}. {imp.name.decode('utf-8')}")
                    else:
                        print(f"  {i + 1}. Ordinal: {imp.ordinal}")
                print()
        else:
            print("[-] No Import Table Found")

    except FileNotFoundError:
        print("[-] File not found.")
    except pefile.PEFormatError:
        print("[-] Invalid PE file.")
    except Exception as e:
        print(f"[-] Error: {e}")


if __name__ == '__main__':
    enum_import(mal_file)

익스포트 (Export) 조사

- 실행 파일과 DLL은 다른 프로그램에서 사용할 수 있는 함수를 익스포트 (Export)할 수 있음

> 일반적으로 DLL은 실행 파일이 임포트할 수 있는 함수 (익스포트)를 노출

> DLL은 단독으로 실행할 수 없기 때문에 호스트 프로세스를 통해 실행

> 공격자는 악의적인 함수를 익스포트하는 DLL을 자주 생성

※ 익스포트 함수명이 매번 악성코드의 기능에 대한 힌트를 주는 것은 아님

 

- pestudio의 exports 메뉴에서 확인 가능

> Python 예시 참조

import pefile
import sys

# 명령행 인자 체크
if len(sys.argv) != 2:
    print("Usage: python script.py <filename>")
    sys.exit(1)

mal_file = sys.argv[1]


def enum_import(mal_file):
    try:
        # PE 파일 로드
        pe = pefile.PE(mal_file)
        
        # Import Table이 존재하는지 확인
        if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
            print(f"[+] {mal_file} Import Table Found")
            for entry in pe.DIRECTORY_ENTRY_IMPORT:
                print(f"DLL : {entry.dll.decode('utf-8')} ({len(entry.imports)})")
                for i, imp in enumerate(entry.imports):
                    if imp.name is not None:
                        print(f"  {i + 1}. {imp.name.decode('utf-8')}")
                    else:
                        print(f"  {i + 1}. Ordinal: {imp.ordinal}")
                print()
        else:
            print("[-] No Import Table Found")
        
        # Export Table이 존재하는지 확인
        if hasattr(pe, 'DIRECTORY_ENTRY_EXPORT'):
            print(f"[+] {mal_file} Export Table Found")
            for entry in pe.DIRECTORY_ENTRY_EXPORT.symbols:
                if entry.name is not None:
                    print(f"DLL : {entry.name.decode('utf-8')}")
                else:
                    print(f"Ordinal : {entry.ordinal}")
        else:
            print("[-] No Export Table Found")

    except FileNotFoundError:
        print("[-] File not found.")
    except pefile.PEFormatError:
        print("[-] Invalid PE file.")
    except Exception as e:
        print(f"[-] Error: {e}")


if __name__ == '__main__':
    enum_import(mal_file)

PE 섹션 테이블과 섹션 조사

- PE 파일의 실제 내용은 섹션 (Section)으로 구분

> 섹션은 코드 (Code)데이터 (Data)를 나타내고, 읽기/쓰기와 같은 메모리 내부 속성을 가짐

구분 설명
코드 - 프로세스가 실행할 명령어를 포함
데이터 - 읽기/쓰기 프로그램 데이터 (전역변수)
- 임포트/익스포트 테이블
- 리소스 등

 

- 각 섹션은 해당 섹션의 목적을 나타내는 고유한 이름을 갖고 있음

> 실행 파일을 컴파일하는 동안 컴파일러는 일관된 섹션 이름을 추가

> PE 파일의 공통 섹션

섹션명 설명
.text 또는 CODE - 실행 코드를 포함
.data 또는 DATA - 읽기/쓰기 데이터와 전역 변수 포함
.rdata - 읽기 전용 데이터를 포함. 때에 따라 임포틑 또는 익스포트 정보 포함
.idata - 존재한다면 임포트 테이블 포함. 존재하지 않으면, .rdata 섹션에서 탐색 가능
.edata - 존재한다면 익스포트 정보 포함. 존재하지 않으면, .rdata 섹션에서 탐색 가능
.rsrc - 실행 파일에서 사용하는 아이콘, 대화창, 메뉴, 문자열 등의 리소스

> 섹션명은 사람을 위한 것으로 운영 시스템에서는 사용하지 않으며, 공격자 또는 난독화 소프트웨어가 섹션명을 변경할 수 있음

 

- 섹션에 대한 정보 (섹션명, 섹션의 위치, 특징)는 PE 헤더에 있는 섹션 테이블 (Section Table)에 존재

> pestudio의 sections 메뉴에서 섹션 테이블에서 추출한 섹션 정보와 그 속성 (읽기/쓰기)을 표시

> 섹션 테이블 필드

필드 설명
name - 섹션 이름
virtual-size - 메모리에 로딩할 때 섹션의 크기 
virtual-address - 섹션을 메모리 어디에서 찾을 수 있는지 나타내는 상대적 가상 주소(실행 파일 베이스 주소에서 얼마나 떨어져 있는지를 나타내는 오프셋)
raw-size - 해당 섹션이 디스크에 존재할 때의 크기
raw-data - 파일에서 해당 섹션을 찾을 수 있는 오프셋 
entry-point - 코드가 실행을 시작하는 RVA(Relatve Virtual Address, 상대적 가상 주소). 일반적으로 .text 섹션에 존재

> 만약 컴파일러에서 생성한 일반적인 섹션명 (.text, .data 등)이 아니라면 의심

> 일반적으로 raw-size와 virtual-size의 크기는 거의 같아야 함

> 만약 raw-size ≒ 0인데, virtual-size가 더 큰 공간을 갖고 있다면, 이는 패킹한 바이너리일 수 있음 (패킹한 바이너리를 실행할 때 패커의 압축 해제 루틴이 런타임 중 압축 해제한 데이터 또는 명령어를 메모리로 복사하기 때문)

컴파일 타임스탬프 조사

- PE 헤더는 바이너리가 컴파일될 때 생성되는 정보를 포함

- 타임스탬프 (Timestamp) 필드를 조사하면 악성코드가 언제 처음 생성됐는지 알 수 있음

> 공격 활동의 타임라인을 작성할 때 도움을 줌

> 공격자가 실제 타임스탬프를 알 수 없도록 수정해 분석 방해 가능

> pestudio의 file-header 메뉴에 “compiler-stamp” 항목에서 확인 가능

PE 리소스 조사

- 아이콘, 메뉴, 대화장사, 문자열과 같이 실행 파일에 필요한 리소스는 실행 파일의 리소스 섹션 (.rsrc)에 저장

> 공격자는 때때로 추가 바이너리, 미끼 문서, 설정 데이터 같은 정보를 리소스 섹션에 저장

> 리소스 해커 (Resource Hacker)는 의심 바이너리에서 리소스를 조사하고 확인 후 추출할 수 있는 도구

[캡쳐 1] PE 파일 구조

1. PE Header

- PE view를 활용해 메모장.exe(PE 파일) 구조 확인

- Visual Studio에서 #include <winnt.h>를 입력->winnt.h에 마우스 우클릭->문서로이동을 통해 구조체를 확인할 수 있다.

1.1) DOS Header

- DOS 파일에 대한 호환성을 고려하여 만들어 졌으며, 총 64Byte 크기를 가짐.

[캡쳐 2] DOS Header

- 구조체 : IMAGE_DOS_HEADER

typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
    WORD   e_magic;                     // Magic number
    WORD   e_cblp;                      // Bytes on last page of file
    WORD   e_cp;                        // Pages in file
    WORD   e_crlc;                      // Relocations
    WORD   e_cparhdr;                   // Size of header in paragraphs
    WORD   e_minalloc;                  // Minimum extra paragraphs needed
    WORD   e_maxalloc;                  // Maximum extra paragraphs needed
    WORD   e_ss;                        // Initial (relative) SS value
    WORD   e_sp;                        // Initial SP value
    WORD   e_csum;                      // Checksum
    WORD   e_ip;                        // Initial IP value
    WORD   e_cs;                        // Initial (relative) CS value
    WORD   e_lfarlc;                    // File address of relocation table
    WORD   e_ovno;                      // Overlay number
    WORD   e_res[4];                    // Reserved words
    WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
    WORD   e_oeminfo;                   // OEM information; e_oemid specific
    WORD   e_res2[10];                  // Reserved words
    LONG   e_lfanew;                    // File address of new exe header
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

e_magic : DOS signature(매직넘버)로 PE파일을 나타내는 첫 2바이트, MZ(5A4D로 고정 값)

                      각 파일은 고유의 signature(매직넘버)를 가짐.

[캡쳐 3] e_magic 값 5A4D(=MZ)

② e_lfanew : IMAGE_NT_HEADER의 시작 Offset 값을 가짐.

- e_flanew에 설정된 주소를 확인하면 PE로 시작하는 것을 확인할 수 있으며, 한번 더 시작점을 알려준다.

[캡쳐 4] e_lfanew 값

1.2) DOS Stub

- 구조체 형태가 아니며, DOS 환경에서 돌아갈 명령어가 16Bit 형태로, 가변 크기를 가짐.

- 일종의 옵션으로 없어도 파일 실행에 문제 없음.

- 32Bit 윈도우 플랫폼에서 실행되도록 만들어진 PE파일이 16Bit DOS 환경에서 실행되려 하는것을 방지하기위해 만들어짐.

[캡쳐 5] DOS Stub

1.3) NT Header

- 파일 실행에 필요한 정보가 저장됨.

- DOS Header의 e_flanew 값이 NT Header를 가리킴

- 구조체에는 총 3개의 멤버로 구성

- 구조체 : IMAGE_NT_HEADERS

typedef struct _IMAGE_NT_HEADERS64 {
    DWORD Signature;
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;

1.3.1) Signature

- NT header구조체의 시작을 판별하실 수 있으며, ASCII 값으로 PE(0x00004550)를 나타낸다.

[캡쳐 6]&nbsp;Signature

1.3.2) FileHeader

- 파일의 개략적인 속성을 나타낸다.

- 구조체 : IMAGE_FILE_HEADER

typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine;
    WORD    NumberOfSections;
    DWORD   TimeDateStamp;
    DWORD   PointerToSymbolTable;
    DWORD   NumberOfSymbols;
    WORD    SizeOfOptionalHeader;
    WORD    Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

Machine : 이 파일이 어떤 CPU에서 동작할 수 있는지, 즉 실행될 수 있는 CPU의 타입을 나타냄

                       IA-32 호환 4C01, IA-64 호환 0020, AMD64 호환 시 6486

NumberOfSections : 파일에 존재하는 색션의 개수(파일에 따라 다름)를 나타내며, 0보다 커야함

                                        정의된 색션 개수 > 실제 색션 개수 : 에러 / 정의된 색션 개수 < 실제 색션 개수 : 정상 실행

③ TimeDateStamp : 해당 파일이 만들어진 시각, 즉 이 파일이 빌드된 날짜가 기록됨. 변조가능(신뢰할 수 있는 값 아님)

④ PointerToSymbolTable : COFF 파일의 심볼 테이블의 오프셋을 나타냄. 없는 경우가 대부분임

⑤ NumberOfSymbols : COFF 심벌 테이블 내에서의 심벌의 수를 나타냄. 없는 경우가 대부분임

SizeOfOptionalHeader : IMAGE_NT_HEADER 구조체 내 IMAGE_OPTIONAL_HEADER 구조체의 크기에 대한 정보

Characteristics : 파일의 속성을 나타내는 값으로, 실행 파일인지 DLL 파일인지 등의 정보들이 OR 연산을 통해 설정

                                  아래 사진을 보아 메모장은 executable 형식이며, 32bit 라는 것을 알 수 있다.

[캡쳐 7] IMAGE_FILE_HEADER 값

1.3.3) OptionalHeader

- 파일 실행에 필요한 주요 정보들을 저장한다.

- 구조체 : IMAGE_OPTIONAL_HEADER

typedef struct _IMAGE_OPTIONAL_HEADER {
    //
    // Standard fields.
    //

    WORD    Magic;
    BYTE    MajorLinkerVersion;
    BYTE    MinorLinkerVersion;
    DWORD   SizeOfCode;
    DWORD   SizeOfInitializedData;
    DWORD   SizeOfUninitializedData;
    DWORD   AddressOfEntryPoint;
    DWORD   BaseOfCode;
    DWORD   BaseOfData;

    //
    // NT additional fields.
    //

    DWORD   ImageBase;
    DWORD   SectionAlignment;
    DWORD   FileAlignment;
    WORD    MajorOperatingSystemVersion;
    WORD    MinorOperatingSystemVersion;
    WORD    MajorImageVersion;
    WORD    MinorImageVersion;
    WORD    MajorSubsystemVersion;
    WORD    MinorSubsystemVersion;
    DWORD   Win32VersionValue;
    DWORD   SizeOfImage;
    DWORD   SizeOfHeaders;
    DWORD   CheckSum;
    WORD    Subsystem;
    WORD    DllCharacteristics;
    DWORD   SizeOfStackReserve;
    DWORD   SizeOfStackCommit;
    DWORD   SizeOfHeapReserve;
    DWORD   SizeOfHeapCommit;
    DWORD   LoaderFlags;
    DWORD   NumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

 Magic : 실행하는 PE파일의 구조체가 32bit(0B01)인지, 64bit(0B02)인지 알려주는 부분

SizeOfCode : 코드영역(.text)의 크기

AddressOfEntryPoint : 프로그램의 실제 시작주소로, ImageBase 값에 이 값을 더해 시작 지점을 설정

ImageBase : PE 파일이 메모리에 로드되는 시작 주소. EXE의 경우 00400000, DLL의 경우 00000001

SectionAlignment : 메모리에서 섹션의 최소 단위, 각 섹션은 반드시 이값의 배수

FileAlignment : 파일에서 섹션의 최소 단위, 각 섹션은 반드시 이값의 배수

SizeOfImage : 메모리에 로딩될 때 가상 메모리에서 PE Image가 차지하는 크기, 즉 PE 파일의 전체 크기

SizeOfHeaders : 모든 PE Header의 크기

Subsystem : 동작환경을 정의. sys 파일 1, GUI 파일 2, CLI 파일 3의 값을 가짐

NumberOfRvaAndSizes : Data Directory의 구조체 멤버 개수

DataDirectory : IMAGE_DATA_DIRECTORY구조체의 배열로써 디렉토리별로 각각의 정보를 담음

- Export Directory : DLL등의 파일에서 외부에 함수를 공개하기 위한 정보들을 가짐
- Import Directory : 프로그램 실행을 위해 Import하는 DLL 이름과 사용할 함수 정보가 담긴 INT주소와 IAT주소 같은 정보가 담김
- TLS Directory : 스레드 지역 저장소 초기화 섹션에 대한 포인터
- IAT Directory : IAT의 시작번지를 가리킴

[캡쳐 8] IMAGE_OPTIONAL_HEADER 값

1.4) Section Header

- Section의 속성을 정의한 헤더

- Section 유형

Code .text 프로그램 실행 코드를 담고 있는 섹션
Data .data 일고 쓰기가 가능한 테이터 섹션으로 초기화된 전역변수와 정적 변수 등이 위치
.rdata 읽기 전용 데이터 섹션으로 상수형 변수, 문자열 상수 등이 위치
.bss 초기화되지 않은 전역변수로, 초기화 시 .data 영역으로 이동
Import API .idata Import 할 DLL과 API에 대한 정보를 담고 있는 섹션으로 IAT 정보가 저장
.diata Delay-Loading Import DLL 정보 (프로그램 실행 후 DLL 사용시에만 연결하며, 릴리즈 모드 시 다른 섹션에 병합)
Expoit API .edata Export할 API 정보를 담고 있는 섹션 (주로 DLL에서 사용되며 .text 또는 .rdata에 병합)으로 EAT 정보가 저장
Resource .rsrc 리소스 관련 데이터를 담고 있는 섹션 (아이콘, 커서 등)
재배치 정보 .reloc 기본 재배치 정보를 담고 있는 섹션 (주로 DLL에서 사용)
TLS .tls 스레드 지역 저장소
Debugging .debug$p 미리 컴파일된 헤더 사용시에만 존재

 

참고 : 

 

[악성코드분석] PE (portable Executable) 기초 개념잡기

PE포맷 이란? 윈도우 운영체제에서 사용되는 실행파일, DLL Object코드, FON 폰트파일 등을 위한 파일형식입니다. OE파일은 윈도우 로더가 실행가능한 코드를 관리하는데 필요한 정보를 캡슐화한 데

rednooby.tistory.com

 

윈도우 실행파일 구조(PE파일)

1. 윈도우 실행파일(PE파일) 개요 1.1 PE파일이란? PE(Portable Executable)파일은 윈도우 실행파일이라고 부르며 윈도우OS에서 사용되는 실행파일형식을 의미하며 UNIX의 COFF(Common Object File Format)을 기반..

rninche01.tistory.com

 

악성코드 분석- 기초 정적 분석, PE 파일

윈도우에서 가장 많이 악성코드로 제작되어 배포되는 PE 파일에 대해 알아보겠습니다. PE(Portable Excutable)파일 - win32 기본 파일형식 - exe, scr, sys, dll ... PE파일의 실행과정은 다음과 같습니다. 1. PE..

hxxyxxn-1238.tistory.com

 

PE 파일 포맷의 이해

※ 주의사항 아래 공격 코드는 연구 목적으로 작성된 것이며, 허가 받지 않은 공간에서는 테스트를 절대 금지합니다. 악의 적인 목적으로 이용할 시 발생할 수 있는 법적 책임은 자신한테 있습

unabated.tistory.com

 

[Analysis] PE(Portable Executable) 파일 포맷 공부

드디어 PE(Portable Executable) 파일 포맷 포스팅을 하고자한다. 내용이 길것으로 예상되나 중요한 파트이므로 천천히 짚고 넘어가자. 1. PE 포맷? PE 포맷이란 Portable Executable 약자로 윈도우 운영체제에

saynot.tistory.com

 

PE(Portable Executable) 구조

Win32의 기본적인 파일 형식 PE(Portable Executable) 구조 오늘은 PE(Portable Executable)에 대해서 알아보도록 하겠습니다. PE라는 말을 들어보신 적이 있나요? 아마 이 글을 보고 계시는 분들 중에 리버싱 경

unabated.tistory.com

 

PE 구조 이해하기 - IMAGE_FILE_HEADER 구조

windows 시스템 실행파일의 구조와 원리 책 내용을 요약 및 정리 하는 포스팅이에요. PE파일의 PE 시그니처 다음에 이어지는 IMAGE_FILE_HEADER에 대한 내용을 알아볼 거에요. IMAGE_FILE_HEADER 구조체IMAGE_FIL

777bareman777.github.io

 

[프로그래밍 일반] PE 파일 분석 - 헤더분석

원문 : kkamagui의 프로그래밍 작업실 http://kkamagui.springnote.com/pages/401262 개요  윈도우 시스템 프로그래밍한다는 사람치고 PE 파일에 대해서 모르는 사람은 아마 거의 없을 것이다. 윈도우 실행 파일

clansim.tistory.com

 

PE파일 구조

PE파일 분석 도구 :  실행파일(Executable File)이란 명령(Operation Codes)에 따라 지시된 작업을 수행하도록 하는 파일을 말한다. 이 파일은 실행 코드, 전역 데이터, Import/Export 함수정보, 리소스 데이터

moaimoai.tistory.com

'악성코드 > 기본' 카테고리의 다른 글

PE 파일 #1 개요 및 구조  (0) 2022.08.02
Malware #1  (0) 2022.07.11

1. PE(Portable Executable) 파일 개요

1.1) PE(Portable Executable) 파일 이란?

[캡쳐 1] https://ko.wikipedia.org/wiki/PE_%ED%8F%AC%EB%A7%B7

- PE(Portable Executable) 파일이란 윈도우 실행파일이며, 윈도우에서 사용되는 실행 가능한 파일 형식이다.

- 유닉스 실행파일 형식인 COFF(CommonObject File Format)을 기반으로 만들어졌다.

- 하나의 실행파일을 다양한 운영체제에서 실행할 수 있다는 의미로 "이식 가능한 실행파일"로 이름이 붙었다.

- 윈도우 환경에 따라 32bit 환경에서는 PE32, 64bit 환경에서는 PE32+ 또는 PE+로 불린다.

- 실행되기 위한 모든 정보와 어느 메모리주소에 파일이 로딩되는지 알 수 있다.

1.2) PE 파일 종류

- 실행 계열 : EXE, SCR
- 드라이버 계열 : SYS, VXD
- 라이브러리 계열 : DLL, OCX, CPL, DRV
- 오브젝트 파일 계열 : OBJ

2. PE 파일 구조

[캡쳐 2] PE 파일 구조

- PE Header에 각 정보들이 구조체 형식으로 저장되어 있다.

- 파일에서는 Offset, Memory에서는 VA(Virtual Address)로 위치를 표현한다.

  Offset : 파일의 첫 바이트부터 거리

  VA(Virtual Address, 절대주소) : 프로세스 가상 메모리의 절대주소

  RVA(Relative Virtual Address, 상대주소) : 기준 위치(ImageBase)부터의 상대주소

  VA = RVA + ImageBase

- RVA(상대주소)를 사용하는 이유는 PE Header에 많은 정보는 RVA 형태로 되어있으며, PE 파일(주로 DLL)이 메모리에 로딩될 때 해당 위치에 다른 PE 파일이 로딩되어 있을 수 있어, Relocation 과정을 통해 빈 공간에 로딩되어야 한다.

만약 VA(절대주소)로 되어있다면 정상적인 액세스가 이루어지지 않지만, RVA(가상주소)로 되어있다면 Relocation이 발생하여도 ImageBase에 대한 상대주소는 변하지 않기에 정상적인 액세스가 가능하다.

2-1) NULL Padding

- 헤더의 끝과 각 섹션 값 사이에 NULL 값이 존재한다.

- 파일 또는 메모리에서 섹션의 시작위치는 각각 최소 기본단위의 배수에 해당하는 위치여야하므로 Null로 채우는 것이다.

 

참고 : 

 

[악성코드분석] PE (portable Executable) 기초 개념잡기

PE포맷 이란? 윈도우 운영체제에서 사용되는 실행파일, DLL Object코드, FON 폰트파일 등을 위한 파일형식입니다. OE파일은 윈도우 로더가 실행가능한 코드를 관리하는데 필요한 정보를 캡슐화한 데

rednooby.tistory.com

'악성코드 > 기본' 카테고리의 다른 글

PE 파일 #2 헤더  (0) 2022.08.02
Malware #1  (0) 2022.07.11

+ Recent posts