티스토리 뷰
이 블로그는 제가 공부한 것을 바탕으로 정리 목적으로 사용되고 있습니다.
작성 내용중 부족한 부분이나 잘못된 부분을 지적해주시면 감사하겠습니다 (꾸벅)
PE 포맷
PE(Portable Executable)은 윈도우 운영체제에서 사용되는 실행 파일, DLL, object 코드, FON폰트 파일등을 위한 파일 형식이다.
PE 포맷은 윈도우 로더가 실행 가능한 코드를 관리하는데 필요한 정보를 캡슐화한 데이터 구조체이다.
종류 |
주요 확장자 |
종류 |
주요 확장자 |
실행 계열 |
EXE, SCR |
드라이버 계열 |
SYS, VXD |
라이브러리 계열 |
DLL, OCX, CPL, DRV |
오브젝트 파일 계열 |
OBJ |
설명을 위해서 노트패드 파일을 이용하여 헥스 에디터 HxD로 열어보도록 하겠다.
HxD로 노트패드를 여는 방법은 (기준은 윈도우 XP이다.) 메뉴 파일 탭에서 열기를 선택하면 아래와 같은 화면이 나온다.
찾는 위치에서 내컴퓨터 -> C:\ -> WINDOWS 로 들어가서 화면에서 보이는 NOTEPAD 를 선택하면 아래와 같은 화면이 다시 나오게 된다.
위의 그림은 노트패드 파일의 시작 부분이며, PE파일의 헤더 부분이다. 여기에는 파일이 실행되기 위해 필요한 모든 정보가 적혀있다.
어떻게 메모리에 적재되고, 어디서부터 실행되어야 하며, 실행에 필요한 DLL들은 어떤 것이 있고, 필요한 Stack / Heap 메모리의 크기를 얼마로 할건지 등등
수많은 정보가 여기에 저장되어 있다.
PE 파일의 기본 구조
<사진 출처 : http://goo.gl/6mjwhu >
위 그림은 노트패트 파일이 메모리에 적재될 때의 모습을 나타낸 것이다. 하나씩 살펴보면 DOS header 부터 Section header 까지를 PE header,
그 아래의 Section 들을 합쳐서 PE body라 한다. 파일에서는 offset으로, 메모리에서는 VA(Virtual Address)로 위치를 표시하게 된다.
파일이 메모리에 적재되면 모양이 달라진다. 섹션 헤더에 각 Section에 대한 파일/메모리에서의 크기, 위치, 속성 등이 정의되어 있다.
VA 와 RVA
VA( Virture Address 절대 주소)는 프로세스 가상 메모리의 절대주소를 말하며, RVA(Relative Virtual Address)는 어느 기준 위치(ImageBase)에서 부터 상대주소를 말한다. VA와 RVA의 관계는
RVA + ImageBox = VA
이다.
PE 헤더 내의 정보는 RVA 형태로 된 것이 많다. 그 이유는 PE 파일이 프로세스 가상 메모리의 특정 위치에 적재되는 순간 이미 그 위치에 다른 PE 파일이 적재되어 있을 수 있다. 이런 오류의 상황에서 재배치 과정을 통해 비어있는 다른 위치에 적재된다. 이때 PE 헤더 정보들이 VA(절대주소)로 되어 있다면 정상적인 접근이 이루어지지 않을 것이다. 대신 정보를 RVA로 해두면 재배치가 발생해도 기준위치에 대해 상대주소가 변하지 않기 때문에 아무런 문제없이 원하는 정보에 접근 할 수 있을 것이다.
IMAGE_DOS_HEADER
마이크로소프트는 PE 파일 포맷을 만들 시에 널리 사용되던 DOS 파일에 대한 하위 호환성을 고려해 만들었다. 그 결과 PE헤더 제일 앞부분에 기존 DOS EXE header를 확장시킨 IMAGE_DOS_HEADER 구조체가 존재한다.
우리가 볼 화면은 EXE나 DLL을 열어서 봤을 때 가장 맨 처음 부분에 해당하는 버퍼이다. 맨 위 부터 PE가 시작된다. ReadFile() 또는 메모리 맵 파일로 볼 경우, 파일의 맨 처음 부분에 해당한다. 아래 코드에 의하면 MapViewOfFile()에서 리턴한 lpFileBase가 PE의 시작이라고 볼 수 있다. 그곳을 IMAGE_DOS_HEADER 구조체로 형변환한 뒤부터 PE의 정보가 시작된다. (4D 5A로 시작하는 부분)
typedef struct _IMAGE_DOS_HEADER {
2357 WORD e_magic; /* 00: MZ Header signature */
2358 WORD e_cblp; /* 02: Bytes on last page of file */
2359 WORD e_cp; /* 04: Pages in file */
2360 WORD e_crlc; /* 06: Relocations */
2361 WORD e_cparhdr; /* 08: Size of header in paragraphs */
2362 WORD e_minalloc; /* 0a: Minimum extra paragraphs needed */
2363 WORD e_maxalloc; /* 0c: Maximum extra paragraphs needed */
2364 WORD e_ss; /* 0e: Initial (relative) SS value */
2365 WORD e_sp; /* 10: Initial SP value */
2366 WORD e_csum; /* 12: Checksum */
2367 WORD e_ip; /* 14: Initial IP value */
2368 WORD e_cs; /* 16: Initial (relative) CS value */
2369 WORD e_lfarlc; /* 18: File address of relocation table */
2370 WORD e_ovno; /* 1a: Overlay number */
2371 WORD e_res[4]; /* 1c: Reserved words */
2372 WORD e_oemid; /* 24: OEM identifier (for e_oeminfo) */
2373 WORD e_oeminfo; /* 26: OEM information; e_oemid specific */
2374 WORD e_res2[10]; /* 28: Reserved words */
2375 DWORD e_lfanew; /* 3c: Offset to extended header */
IMAGE_NT_HEADER
typedef struct _IMAGE_NT_HEADERS64 {
2672 DWORD Signature;
2673 IMAGE_FILE_HEADER FileHeader;
2674 IMAGE_OPTIONAL_HEADER64 OptionalHeader;
typedef struct _IMAGE_FILE_HEADER {
2622 WORD Machine;
2623 WORD NumberOfSections;
2624 DWORD TimeDateStamp;
2625 DWORD PointerToSymbolTable;
2626 DWORD NumberOfSymbols;
2627 WORD SizeOfOptionalHeader;
2628 WORD Characteristics;
IMAGE_OPTIONAL_HEADER
2639 WORD Magic; /* 0x20b */
2640 BYTE MajorLinkerVersion;
2641 BYTE MinorLinkerVersion;
2642 DWORD SizeOfCode;
2643 DWORD SizeOfInitializedData;
2644 DWORD SizeOfUninitializedData;
2645 DWORD AddressOfEntryPoint;
2647 ULONGLONG ImageBase;
2648 DWORD SectionAlignment;
2649 DWORD FileAlignment;
2650 WORD MajorOperatingSystemVersion;
2651 WORD MinorOperatingSystemVersion;
2652 WORD MajorImageVersion;
2653 WORD MinorImageVersion;
2654 WORD MajorSubsystemVersion;
2655 WORD MinorSubsystemVersion;
2656 DWORD Win32VersionValue;
2657 DWORD SizeOfImage;
2658 DWORD SizeOfHeaders;
2659 DWORD CheckSum;
2660 WORD Subsystem;
2661 WORD DllCharacteristics;
2662 ULONGLONG SizeOfStackReserve;
2663 ULONGLONG SizeOfStackCommit;
2664 ULONGLONG SizeOfHeapReserve;
2665 ULONGLONG SizeOfHeapCommit;
2666 DWORD LoaderFlags;
2667 DWORD NumberOfRvaAndSizes;
2668 IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
2736 #define IMAGE_SIZEOF_SHORT_NAME 8
2737
2738 typedef struct _IMAGE_SECTION_HEADER {
2739 BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
2740 union {
2741 DWORD PhysicalAddress;
2742 DWORD VirtualSize;
2743 } Misc;
2744 DWORD VirtualAddress;
2745 DWORD SizeOfRawData;
2746 DWORD PointerToRawData;
2747 DWORD PointerToRelocations;
2748 DWORD PointerToLinenumbers;
2749 WORD NumberOfRelocations;
2750 WORD NumberOfLinenumbers;
2751 DWORD Characteristics;
#define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code.
#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // Section contains initialized data
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // Section contains uninitialized data
#define IMAGE_SCN_CNT_EXECUTE 0x20000000 // Section is executable
#define IMAGE_SCN_CNT_READ 0x40000000 // Section is readable
#define IMAGE_SCN_CNT_WRITE 0x80000000 // Section is writale
< 출처 : 리버싱 핵심 원리 ; 저자 : 이승원 >
'Reversing > Reverse Engineering' 카테고리의 다른 글
실행 압축 테스트 (0) | 2016.04.26 |
---|---|
Huffman Algorithm에 대해서 (0) | 2016.04.23 |
abex’ crackme #1 (0) | 2015.12.26 |
OllyDbg를 이용한 스택 공부하기 (0) | 2015.12.23 |
PACKING (0) | 2015.12.21 |
- Total
- Today
- Yesterday
- Omok
- 패킷
- 오일러 프로젝트 12번
- 팁스강좌
- TIPS강좌
- 화투이미지맞추기
- 2의 1000승
- 오일러 프로젝트 8번
- 오일러 프로젝트 16번
- 와이어샤크
- MFC
- CBrush
- 오일러
- 헤더
- tipssoft
- 비손실 압축
- 오일러 프로젝트 10본
- tipsoft
- 허프만 알고리즘
- arp
- 서버
- 오일러 프로젝트 14번
- 약수 500개
- Tips
- 오일러 프로젝트 13
- 키보드 메시지 이벤트
- 실행 압축
- 오일러 프로젝트 11번
- tipsr강좌
- 이미지게임
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |