Information Security
PE File Format 본문
PE File Format
PE(Portable Executable) 파일이란 Windows OS에서 사용하는 실행 파일 형식이다. 우리는 메모장(notepad.exe)으로 PE 파일의 기본 구조를 알아볼 것이다.
PE 파일은 PE 헤더(DOS 헤더 ~ 섹션 헤더)와 PE 바디(섹션)로 이루어진다.
PE 헤더에는 파일이 실행되기 위해 필요한 정보들이 구조체 형식으로 저장되어 있다.
IMAGE_DOS_HEADER
HxD로 확인한 DOS Header이다.
e_magic DOS signature MZ(4D5A)
e_lfanew NT_header의 offset(000000E0)
e_lfanew 멤버의 값을 따라서 000000E0에는 IMAGE_NT_HEADERS 구조체가 위치한다.
이 구조체는 signature와 두 개의 구조체 멤버로 구성된다.
Signature: PE signature PE(50450000)
File Header
Machine |
CPU별 고유한 값(14C: 32비트 Intel x86 호환 칩) |
NumberOfSections |
섹션의 개수 |
TimeDateStamp |
해당 파일의 빌드 시간(파일의 실행에 영향을 미치지 않는 값) |
SizeOfOptionalHeader |
NT 구조체의 마지막 멤버 OPTIONAL 구조체의 크기 |
Characteristic |
파일의 속성들이 bit OR 형식으로 조합(0002h: File is executable. / 2000h: File is a DLL.) |
Optional header
Magic |
IMAGE_OPTIONAL_HEADER32 구조체: 10B / IMAGE_OPTIONAL_HEADER64 구조체: 20B |
AddressOfEntryPoint |
EP(Entry Point)의 RVA 값으로, 프로그램의 최초 실행 코드의 시작 주소(VERY IMPORTANT) |
ImageBase |
메모리에서 PE 파일이 로딩되는 시작 주소 * PE 로더는 PE 파일을 실행시키기 위해 프로세스를 생성하고, 파일을 메모리에 로딩한 후 EIP의 값을 AddressOfEntryPoint + ImageBase의 결과로 세팅한다. |
File/SectionAlignment |
파일에서/메모리에서 섹션의 최소단위. 섹션크기는 각각 이 값의 배수여야 한다. |
SizeOfImage |
파일이 메모리에 로딩되었을 때 가상 메모리에서 PE Image가 차지하는 크기 |
SizeOfHeader |
PE 헤더의 전체 크기로 FileAlignment의 배수여야 한다. |
Subsystem |
이 값(Driver: 1/ GUI: 2/ CUI: 3)을 보고 파일 구분 |
NumberOfRvaAndSizes |
DataDirectory 배열의 개수 |
DataDirectory |
IMAGE_DATA_DIRECTORY 구조체의 배열 |
* VA(Virtual Address): 프로세스 가상 메모리의 절대주소
* RVA(Relative Virtual Address): 어느 기준 위치(ImageBase)에서부터의 상대주소
=> VA와 RVA의 관계식: RVA + ImageBase = VA
* Image: PE 파일은 섹션 헤더에 정의된 대로 맞춰서 메모리에 로딩된다. 메모리에 로딩된 상태를 이미지라고 한다.
NT 헤더 다음에 등장하는 섹션 헤더는 각 섹션별 IMAGE_SECTION_HEADER 구조체의 배열로 되어 있다.
VirtualSize |
메모리에서 섹션이 차지하는 크기 |
VirtualAddress |
메모리에서 섹션의 시작 주소(RVA) |
SizeOfRawData |
파일에서 섹션이 차지하는 크기 |
PointerToRawData |
파일에서 섹션의 시작 위치 |
Characteristic |
섹션의 속성(bit OR) |
★ RVA to RAW
PE 파일이 메모리에 로딩되었을 때, 각 섹션에서 메모리 주소와 파일 옵셋을 잘 매핑할 수 있어야 한다.
섹션 헤더를 참고하여 메모장 파일이 메모리에 적재되는 모습과 위치를 그림으로 표현한 것이다.
그러면 이제, 어떤 메모리 주소가 주어졌을 때 그에 매핑되는 오프셋을 구하는 방법을 알아보겠다.
Q. RVA가 7A60일 때, RAW(File offset)의 값은 무엇일까요??
RVA(7A60) + ImageBase(1000000) = VA(1007A60)
VA의 공식을 통해, RVA 7A60 값이 첫번째 text 섹션에 속해있다는 것을 알 수 있다.
그리고 RAW = RVA - VirtualAddress(RVA) + PointerToRawData 비례식을 이용하면 끝!
7A60 - 메모리에서 text 섹션의 시작 주소(RVA: 1000) + 파일에서 text 섹션의 시작 위치(400) = 6E60
A. RVA가 7A60일 때 RAW의 값은 6E60이다.
'Reverse Engineering' 카테고리의 다른 글
DLL Ejection (0) | 2019.06.21 |
---|---|
DLL Injection - Remote Thread 생성 & 레지스트리 이용 (0) | 2019.06.20 |
Windows Message Hooking (0) | 2019.06.17 |
EAT(Export Address Table) (0) | 2019.06.12 |
IAT(Import Address Table) (0) | 2019.06.12 |