티스토리 뷰

728x90
반응형

[Reversing] PE 파일 만들기 


제작 과정은 간략한 설명으로 건너뛰고 넘어가는 부분이 많습니다.

이전 게시물을 참조 PE Format 참조

 

직접 제작해 보는 것을 추전을 받아 작성합니다.

직접 제작하다 보면 자신이 잘 몰랐거나 잘 못 이해하던 부분을 정확히 파악하고 제대로 공부할 수 있다고 생각합니다.

CLI 기반, printf문 사용, 'Hello World !' 출력을 목적으로 제작할 것입니다.


 

1. IMAGE_DOS_HEADER

- MZ는 IMAGE_DOS_HEADER의 Signature입니다.(4D5A = ASCII 값 "MZ")

- 해당 구조체의 크기는 40h으로(64byte) 고정이며, 여러개의 필드로 구성되어있습니다.

- IMAGE_DOS_HEADER의 구조체 중 e_lfanew가 PE 헤더의 시작점을 가르키는 오프셋 값입니다.

- e_magic와 e_lfanew 사이에 있는 DOS 헤더의 다른 필드는 0으로 채우도록 하겠습니다.

- 추후 출력값('hello world')과 DLL 해당 부분에 작성할 것입니다.


2. DOS Stub

- 다음 DOS Stub은 필수 구성 요소는 아니기 때문에 없더라도 프로그램 실행과는 무관합니다.(Size도 고정되어 있지 않음)

- DOS Stub은 맨처음 시작 지점으로 부터 40h이후(64byte) 떨어진 곳이 시작지점입니다.

- DOS Stub 필드는 0으로 채웁니다.

- 추후 IDT을 해당 부분에 작성할 것입니다.


중간정리

지금까지의 IMAGE_DOS_HEADER와 DOS Stub의 내용을 가지고 제작해 보겠습니다.

저는 DOS Stub을 제외하고 제작하려고 합니다.

그렇게 하기 위해서는 위에서 말하였듯이 e_lfanew의 값을 0x80(128byte)로 설정하여 IMAGE_DOS_HEADER 뒤 DOS Stub 이후 PE 헤더가 오게 만들어 줍니다.(0x80)

즉, e_lfanew 필드는 PE 파일의 시작 위치와 관련!!


[Hello.exe HxD]


[PE 구조]


3. IMAGE_NT_HEADER

- IMAGE_NT_HEADERS 구조체의 시작 부분인 Signature는 항상 'PE\0\0' 데이터가 고정으로 들어옵니다.(50 45 00 00)

- 다음 부분은 20bytes를 가지고 있는 IMAGE_FILE_HEADER 입니다.(Size 고정)


3.1 IMAGE_FILE_HEADER 

IMAGE_FILE_HEADER 구조체의 필드 설명 및 제작


Machine

- 컴퓨터의 유형을 식별하는 번호입니다.

- 인텔 아키텍쳐 32비트 환경일 때는 0x14c

- 인텔 아키텍쳐 64비트 환경일 때는 0x200

더 자세한 내용은 Machine 정보 참고


Number of Sections

- 파일이 가지고 있는 섹션의 수를 나타냅니다.

- 최소 1개 이상의 섹션으로 구성이 됩니다. 그렇기 때문에 저는 1개의 섹션만 제작할 것입니다.


Time Date Stamp

- 1970년 1월 1일 00시 기준으로 PE 파일이 생성된 시간을 초단위로 작성하는 부분인거 같습니다.

- TEST를 통해 해당 값 4byte를 0으로 채워도 실행이 되었기 때문에 0으로 제작할 것입니다.


Pointer to Symbol Table, Number of Symbols

- Symbol 관련 필드로 해당 필드 2개에 대해서는 Symbol의 크기가 커져 따로 파일로 저장되어 사용하기 때문에 사용되지 않는다고 알고 있다.

- 해당 필드는 0으로 제작할 것입니다.


Size of Optional Header

- IMAGE_OPTIONAL_HEADER 구조체의 크기에 대한 정보를 가지는 부분입니다.

- 해당 필드로 인해 OPTIONAL_HEADER는 고정된 Size가 아니라는 걸 알수 있습니다.

- 32bit PE 파일은 0xE0(224byte)

- 64bit PE 파일은 0xF0(240byte)

- 저는 32bit PE 파일 0xE0으로 제작할 것입니다.

더 자세한 내용은 Size of Optional Header 정보 참고


Characteristics

- 해당 필드는 PE 파일이 exe, dll 등 여러가지 특성이 정의되어 있습니다.

- 일반적인 실행 파일 0x10F 이며, 이 점을 통해 exe 파일을 이야기하고 재배치가 절대로 발생하지 않습니다.(가장 먼저 로드 되기 때문에)

더 자세한 내용은 Characteristics 정보 참고


중간정리

위에서 제작 한 부분을 이어 제작해 보겠습니다.

먼저 IMAGE_NT_HEADERS Signature부분을 'PE\0\0' 작성합니다.

IMAGE_FILE_HEADER도 작성합니다.

Machine 필드는 0x14c 작성

Number of Sections 필드는 1개 작성

Time Date Stamp, Pointer to Symbol Table, Number of Symbols 필드는 0으로 작성

Size of Optional Header 필드는 0xE0 작성

Characteristics 필드는 0x10F 작성

 

[Hello.exe HxD]


[PE 구조]


3.2 IMAGE_OPTIONAL_HEADER

IMAGE_OPTIONAL_HEADER 구조체의 필드 설명 및 제작


Magic

- IMAGE_OPTIONAL_HEADER의 시작 부분인 Signature 처럼 0x10B으로 고정되어 있습니다.


Linker Ver. (Major) | Linker Ver. (Minor)

- 링커와 관련된 필드로 보여집니다.

- TEST를 통해 해당 값을 0으로 채워도 실행이 되었기 때문에 0으로 제작할 것입니다.


Size of Code

- 코드 섹션의 크기를 나타냅니다.(text 섹션 = 코드 섹션)

- text 섹션과 관련 있으며, 저는 Size를 0x200으로 제작할 것입니다.(저는 1개의 섹션(.text)만 제작할 계획입니다.)


Size of Initialized Data

- 여러 섹션 헤더 중 .data .rdata .reloc 등과 같은 섹션 헤더는 읽기, 쓰기 변수들을 저장되어 있습니다. Size of Initialized Data 필드에서 이러한 섹션 헤더들의 영역의 크기를 지정합니다.

- 저는 1개의 섹션(.text)만 제작할 계획이기에 .text 섹션 헤더에 읽기, 쓰기 변수들 저장할 것입니다. 그러므로 0으로 제작할 것입니다.


Size of Uninitialized Data

- 따로 공간을 잡아줄 필요가 없는 변수의 크기를 지정합니다.

- 저는 0으로 제작할 것입니다.


Entry Point

- 코드 섹션(.text)의 시작점을 가르키는 경우가 많이 있습니다.(시작 위치 RVA 가지고 있습니다.)

- 즉, Image Base + Entry Point 코드 영역이 시작 됩니다

- 저는 0x1000으로 제작할 것입니다.


Base of Code

- 코드 섹션이 시작되는 RVA 값을 가집니다.

- 저는 Section Alignment 필드에서 0x1000(4096byte) 설정할 예정으로 Base of Code 필드는 0x1000(4096byte) 될 것입니다.

- 그런데 TEST시 해당 필드를 0으로 채워도 실행에 문제는 없었습니다.


Base of Data

- 데이터 섹션이 시작되는 RVA 값을 가집니다.

- 저는 Section Alignment 필드에서 0x1000(4096byte) 설정할 예정으로 Base of Data 필드는 0x2000(8192byte) 될 것입니다.

- 해당 필드 역시 TEST시 0으로 채워도 실행에 문제는 없었습니다.


ImageBase

- exe파일의 값은 0x400000 입니다,

- Entry Point와 ImageBase 합은 EIP 레지스터에 저장이 됩니다.(EIP는 다음 주소를 저장하니까)


Section Alignment

- 각 섹션들이 메모리에 차지하는 최소단위 입니다.

- 저는 Section Alignment 필드에서 0x1000(4096byte)로 제작할 것입니다.

- PE Format 공식적인 문서를 보게 되면 Section Alignment 필드의 page 사이즈는 4096byte 작을 수 없다는 걸 알수 있습니다.(제한적인 상황에서는 작아도 실행하는데 제한이 없다고 합니다.)


File Alignment

- 디스크에서의 섹션과 관련 있습니다.

- 저는 File Alignment 필드에서 0x200(512byte)로 제작할 것입니다.

- 512byte ~ 64KB 사용하도록 되어 있습니다.(2의 n승 형태)


Major O/S Version, Minor O/S Version, Major Image Version, Minor Image Version

- TEST를 통해 해당 값 4byte를 0으로 채워도 실행이 되었기 때문에 0으로 제작할 것입니다.

- 해당 내용은 정보 참고


Major Subsystem Version, Minor Subsystem Version

- PE 파일 실행하는데 필요한 서브시스템의 최소 버전입니다.

- TEST시 O/S, Image Version 필드는 0으로 채워도 실행이 된 반면 해당 필드는 오류가 발생했습니다.

- Win32 경우 버전을 4.0으로 해야 된다고 합니다.(Major Subsystem Version = 4, Minor Subsystem Version = 0 설정)

 

Size of Image

- 메모리에 로드된 PE 파일의 총 크기이며, Section Alignment 필드의 배수가 되어야 합니다.

- 저는 Number of Sections 필드에서 1개의 섹션만 제작하기로 했습니다.

- Entry Point RVA 값 0x10은 IMAGE_DOS_HEADER부터 IMAGE_SECTION_HEADER .text (1개 섹션)까지 입니다.

- 다음 IMAGE_SECTION_HEADER .text 크기는 0x1000 입니다.

- Size of Image 값은 0x2000으로 제작되어야 합니다.(Section Alignment 필드 배수)


Size of Headers

- 디스크에 헤더의 총 크기이며, File Alignment 필드의 배수가 되어야 합니다.

- 0x200으로 제작할 것입니다.

 

Checksum

- 체크섬 값은 커널 모드나 DLL인 경우 설정이 필요하다고 합니다. 

- 그 이외의 경우는 보통 0으로 설정하기에 저는 0으로 제작할 것입니다.


Subsystem

- GUI 기반인지 드라이버 파일인지 등의 설정값을 가지고 있습니다.

- 0x1 .sys 확장자를 갖는 드라이버 파일

- 0x2 GUI 기반

- 0x3 CLI 기반


DLL Characteristics

- 해당 필드는 DLL 초기화 함수가 호출되어야 하는지 지시하는 플래그였다고 합니다.(잘모르겠다)

- 대부분 0으로 설정되어 있는 것을 확인할 수 있습니다.

- 저도 역시 0으로 제작할 것입니다.

 

Size of Stack Reserve, Size of Stack Commit, Size of Heap Reserve, Size of Heap Commit

- 잘모르겠다.

- Size of Stack Reserve, Size of Heap Reserve는 0x10000

- Size of Stack Commit, Size of Heap Commit은 0x1000

- 대부분 위 값을 갖는다고 합니다. 저도 위와 같이 제작할 것입니다.


Loader Flags

- 이전에는 디버깅 지원에 관계된 목적으로 존재하는 것 같지만, 현재는 0으로 설정 된다고 합니다.

- 저도 0으로 제작할 것입니다.

 

Number of RVAs and Sizes

- Number of RVAs and Sizes 필드는 IMAGE_DATA_DIRECTORY 구조체와 관련있는데 항상 0x10(16)이다. (존재하지 않을 수도 있습니다.)

 

중간정리

위에서 제작 한 부분을 이어 제작해 보겠습니다.


Magic 필드는 0x10B 작성 

Linker Ver. (Major) | Linker Ver. (Minor) 필드는 0으로 작성

Size of Code 필드는 0x200 작성 

Size of Initialized Data 필드는 0으로 작성 

Size of Uninitialized Data 필드는 0으로 작성

Entry Point 필드는 0x1000 작성

Base of Code 필드는 0x1000 작성

Base of Data 필드는 0x2000 작성

ImageBase 필드는 0x400000 작성 

Section Alignment 필드는 0x1000 작성 

File Alignment 필드는 0x200 작성 

Major O/S Version, Minor O/S Version, Major Image Version, Minor Image Version 필드는 0으로 작성 

Major Subsystem Version, Minor Subsystem Version 필드는 0x4, 0으로 작성 

Win32 Version Value 필드는 0으로 작성

Size of Image 필드는 0x2000 작성 

Size of Headers 필드는 0x200 작성

Checksum 필드는 0으로 작성 

Subsystem 필드는 CLI 0x3 작성 

DLL Characteristics 필드는 0으로 작성

Size of Stack Reserve, Size of Heap Reserve 필드는 0x10000

Size of Stack Commit, Size of Heap Commit 필드는 0x1000

Loader Flags 필드a는 0으로 작성

Number of RVAs and Sizes 필드는 0x10 작성 


[Hello.exe HxD]


[PE 구조]


3.2.1 IMAGE_DATA_DIRECTORY

- 위 Number of RVAs and Sizes 필드에서 알수 있듯 디렉토리의 엘리먼트 수를 저장했습니다.

- IMAGE_DATA_DIRECTORY[0] ~ IMAGE_DATA_DIRECTORY[15] 입니다.

- 각 8byte * 16 총 128byte 입니다.

간략하게 디렉토리의 엘리먼트를 보겠습니다.


IMAGE_DIRECTORY_ENTRY_EXPORT

- Export tables(.edata)의 시작 주소를 가리킨다.(DLL에 존재)


IMAGE_DIRECTORY_ENTRY_IMPORT

- Import Section(.idata)의 시작 주소를 가리킨다. 


IMAGE_DIRECTORY_ENTRY_BASERELOC

- 재배치와 관련된 데이터 구조에 대한 시작점과 크기를 가리킨다.(DLL)


IMAGE_DIRECTORY_ENTRY_IAT

- 첫 번째 IAT 시작 주소를 가리키며, Size 필드는 IAT 크기를 가리킨다.


3.2.1.1 IMAGE_IMPORT_DESCRIPTOR

- PE 파일이 IMPORT해서 사용하는 함수에 대한 정보를 담고 있는 구조체입니다.(DLL과 같은 라이브러리)

- 대부분 여러개를 Import하게 됩니다.

- IMAGE_IMPORT_DESCRIPTOR 구조체는 PE 파일이 Import한 dll만큼 배열형식으로 되어 있습니다.

- 구조체 배열의 마지막은 NULL 구성되어있습니다.

- 예를 들어 a.exe 프로그램에서 Import 하는 dll부분이 3개일 경우는 IMAGE_IMPORT_DESCRIPTOR 구조체는 총 4개가 됩니다.(각 1개씩, 마지막 NULL)


* 바인딩

- IAT 정보를 통하여 라이브러리에 연결되어 있는 다른 라이브러리를 같이 로드하며, 참조하고 있는 다른 라이브러리의 함수 주소를 EAT에서 찾아 IAT의 IMAGE_THUNK_DATA32에 기록하는 것


OriginalFirstThunk(IMPORT_NAME_TABLE)

- INT RVA를 가리킨다.(INT, IAT의 크기는 같아야 합니다.)


TimeDataStamp, ForwarderChain

- 해당 필드는 라이브러리가 바인딩 과정을 거치기 전에는 항상 0이며, 바인딩이 완료된 후에는 -1을 가집니다.(잘모르겠다)


Name(IMPORT_DLL_NAME)

- 라이브러리 이름 문자열이 존재하는 RVA를 가르킨다.


FirstThunk(IMPORT_ADDRESS_TABLE)

- IAT 주소를 가리킨다.


3.2.1.2 IMAGE_IMPORT_BY_NAME


Hint

- Import 하려는 라이브러리의 EAT의 인덱스 값을 가지고 있다고 합니다.(함수를 빠르게 찾게 도와주는 필드)

- 필수적이지 않기 때문에 0으로 채우도록 제작할 것입니다.


Name

- Import 하려는 함수의 이름


중간정리

IMAGE_DATA_DIRECTORY 크기는 128byte 입니다.(8byte * 16)


[IMAGE_DATA_DIRECTORY 크기 추가 HxD]


[PE 구조]


[현재까지 PE 구조]



728x90
반응형

'Reversing > Reversing Tech' 카테고리의 다른 글

[Reversing] Inline Code Patch ②  (0) 2019.07.19
[Reversing] Inline Code Patch ①  (0) 2019.07.17
[Reversing] PE 파일 만들기④  (0) 2019.06.25
[Reversing] PE 파일 만들기③  (0) 2019.06.25
[Reversing] PE 파일 만들기②  (0) 2019.06.17
댓글
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today