이번에는 이전 글에서 다루지 못한 .rsrc 섹션에 대해서 알아보도록 하겠다.

[.rsrc 섹션]
이 섹션은 GUI 프로그램에서 많이 볼 수 있는 섹션으로 그래픽 정보를 저장하는 섹션이다.
해당 섹션의 구조는 다른 섹션과는 달리 트리구조로 되어 있으며 이 트리를 구성하는데 있어 각 노드들에는 두가지의 구조체가 있다. IMAGE_RESOURCE_DIRECTORY라는 구조체와 IMAGE_RESOURCE_DIRECTORY_ENTRY 구조체이다.
또 섹션의 트리에는 속하지 않지만 실제 리소스들의 대한 정보를 가지고 있는 IMAGE_RESOURCE_DATA_ENTRY
구조체가 있다.
해당 섹션의 속성정보를 알아본 뒤 각 구조체에 대해서 알아보도록 하겠다.
 - IMAGE_SCN_CNT_INITIALIZED_DATA
 - IMAGE_SCN_MEM_READ

[IMAGE_RESOURCE_DIRECTORY]
해당 구조체는 해당 노드에 대한 정보를 가지고 있는 구조체로, 아래와 같은 형태이다.

[그림 1 - IMAGE_RESOURCE_DIRECTORY 구조체 형태]

 - Characteristics : 속성정보를 나타내지만 현재는 예약 영역으로 쓰이고 있어 항상 0으로 설정되어 있다.
                            크기는 4바이트 이다.

 - TimeDateStamp : 섹션이 컴파일된 날짜와 시간을 의미한다. 하지만 현재 쓰이지 않고 있어 0으로 설정되어 있다.
                             크기는 4바이트 이다.

 - MajorVersion : 리소스의 주버전을 나타낸다. 하지만 현재 쓰이지 않고 있어 0으로 설정되어 있다.
                         크기는 2바이트 이다.

 - MinorVersion : 리소스의 하위버전을 나타낸다. 하지만 현재 쓰이지 않고 있어 0으로 설정되어 있다.
                         크기는 2바이트 이다.

 - NumberOfNameEntries : 해당 노드 다음에 나오는 노드들 중 이름으로 자신을 구별하는 노드들의 개수를
                                       가지고 있다. 크기는 2바이트 이다.

 - NumberOfIdEntries : 해당 노드 다음에 나오는 노드들 아이디로 자신을 구별하는 노드들의 개수를 가지고 있다.
                                 크기는 2바이트 이다.

결국 이 구조체에서는 마지막 2개의 구조체 멤버만 쓰인다. 


[IMAGE_RESOURCE_DIRECTORY_ENTRY]
해당 구조체는 다른 노드나 하위 노드들의 정보와 실제 리소스 데이터를 가지고 있는 구조체이다.
구조체의 형태는 아래와 같다.

[그림 2 - IMAGE_RESOURCE_DIRECTORY_ENTRY 구조체 형태]


 - Name : 만약 엔트리가 이름으로 구별되어질 경우 사용하는 멤버이다. 최상위 1비트가 1로 설정되어 있으며,
               나머지 31비트는 실제 이름스트링을 가리키는 오프셋(RVA)이다. 크기는 4바이트 이다.
* 참고 : 오프셋 위치는 IMAGE_RESOURCE_DIRECTORY부터 시작이다.
 

 - Id : 만약 엔트리가 아이디로 구별되어질 경우 사용하는 멤버이다. 최상위 1비트가 0으로 설정되어 있으며, 하위
         16비트가 정수로 Id를 뜻한다. 크기는 4바이트 이다.

 - OffsetToData : 만약 엔트리가 아이디를 사용하면, 최상위 1비트는 0으로 설정되며, 나머지는 실제 리소스의
                        오프셋이 된다. 만약 또 다른 엔트리를 가리킬 경우, 최상위 1비트는 1로 설정되며, 나머지는
                        오프셋이 되어 또 다른 엔트리를 가리킨다. 크기는 4바이트 이다.


[IMAGE_DIRECTORY_DATA_ENTRY]
해당 구조체는 실제 리소스들이 저장된 위치와 크기, 코드 페이지 등에 대한 정보를 가지고 있다.
아래는 해당 구조체의 형태이다.

[그림 3 - IMAGE_DIRECTORY_DATA_ENTRY 구조체 형태]

 - OffsetToData : 실제 리소스 데이터가 위치해 있는 주소의 RVA값을 가지고 있다. 크기는 4바이트 이다.

 - Size : 리소스 데이터의 크기이며, 단위는 바이트이다. 크기는 4바이트 이다.

 - CodePage : 리소스 데이터의 코드 페이지 값이다. 보통은 유니코드를 사용하며 값은 0으로 설정되어 있다.
                     크기는 4바이트 이다.

 - Reserved : 예약 영역이며, 0으로 채워져 있다. 크기는 4바이트 이다.


이제 각 구조체가 어떻게 트리형태로 구성되는지 알아볼 차례이다.

아래는 각 구조체와 노드가 어떤 형태로 트리구조를 형성하고 있는지 도식화 한 것이다.

[그림 4 - .rsrc 트리구조]


맨 위 루트노드는 각 하위 노드들을 찾는데에만 사용이 되며, 루트 하위 노드들은 각 리소스 타입을 대표하는 노드들로 사용이 된다. IMAGE_RESOURCE_DIRECTORY_ENTRY의 개수에 따라 해당 노드는 NumberOf[Name/ID]Entries의 값이 결정된다.
예를들면 루트 하위 노드들이 이름으로 구분지어 지면 루트노드의 NumberOfNameEntries의 값은 3이 되는 것이다.
* 참고:  .rsrc의 트리구조가 모두 위 이미지처럼 IMAGE_RESOURCE_DIRECTORY_ENTRY의 개수가
          일정한 것은 아니다.



 


'[+] Information > [-] RCE' 카테고리의 다른 글

ARE(Android Reverse Engineering) 환경 소개  (5) 2012.05.05
Oter : Android Revese Engineering Tool  (8) 2012.01.30
PE 구조 (8)  (0) 2012.01.01
PE 구조 (7)  (0) 2012.01.01
PE 구조 (6)  (0) 2011.12.31
이번에는 실행파일에서의 핵심구조인 섹션을 알아 볼 차례이다.

앞에서 알아본 PE 구조들은 실행파일들의 정보나 메모리에 로드될 때의 정보 등이었지만 지금 알아 볼 섹션은 실행파일의

동작에 관한 정보들이다. 

섹션에는 여러가지 섹션이 있는데, 대부분 .text, .data, .rdata, .rsrc, .edata, .idata, .reloc 섹션이 많이 사용된다.

각 섹션이 의미하는 바는 각 섹션을 분석할 때 설명할 것이다.

분석하고자 하는 파일의 섹션정보는 PE File Header를 보면 NumberOfSections에 섹션 개수가 나타나 있으며, 각 섹션의

위치 정보 등은 Section Header 영역에 보면 나와 있다.

아래는 notepad.exe 섹션정보를 Hex Viewer 등으로 본 이미지이다.

[그림 1 - NumberOfSections]

[그림 2 - 섹션헤더 영역의 섹션 이름]
 
notepad.exe에는 총 4가지의 섹션이 있으며, 섹션의 종류는 .text, .data, .rsrc, .reloc 이 있다.

이제부터 하나씩 상세히 알아보도록 하겠다.

[.text 섹션]
.text 섹션은 실행파일의 소스코드가 들어있는 섹션으로, 초기화되거나 초기화 되지 않은 변수, import와 export 테이블
정보를 제외한 나머지 소스코드들이 저장되어 있다. 해당 섹션의 기본 속성정보로는 아래와 같다.
 - IMAGE_SCN_CNT_CODE
 - IMAGE_SCN_MEM_EXCUTE
 - IMAGE_SCN_MEM_READ

섹션의 위치와 크기는 섹션헤더(PointerToRawData, SizeOfRawData)를 참고하면 알 수 있으며 아래는 .text 섹션
헤더에서의 PE 파일 내에서의 .text 섹션 위치와 크기를 알아 본 것이다.

* 참고 : 메모리상에서의 주소와 크기는 VirtualAddress, VirtualSize를 참조하면 된다.

[그림 3 - .text 섹션의 오프셋과 크기]


위 정보를 보면 PE 파일내에서의 주소는 주소는 "0x00000400", 크기는"0x0000A800" 이다.
.text 섹션의 마지막 오프셋은 주소와 크기를 더하게 되면 나오고 결과값은 "0x0000AC00" 가 된다.
이 정보를 토대로 가보면 아래와 같다. 

[그림 4 - .text 섹션의 모습]

섹션의 모습을 보면 어느정도 데이터가 있다가 나머지는 0으로 채워져 있다. 이러한 이유는 SizeOfRawData의 경우 FileAlignment(IMAGE_OPTIONAL_HEADER)의 배수가 되어야 하므로 실제 데이터의 크기를 가지고 있는 VirtualSize의 값을 FIleAlignment의 값의 배수로 올림하여 크기가 늘어나 채울 데이터가 없어 0으로 채운것이다.
실제 메모리에 .text 섹션이 올라갈때는 0을 제외하고 올라가게 된다. 


이러한 방법으로 모든 섹션의 영역을 찾을 수 있다.

이 방법을 계속 섹션마다 사용하여 영역을 찾는 것을 보여 줄 수는 없기 때문에 이후에 나오는 섹션들은 특징과 속성정보등만

소개하겠다.

[.data 섹션]
.data 섹션은 읽기/쓰기가 가능한 일반적인 데이터를 위한 섹션으로, 정적변수와 전역변수가 저장된다. 
해당 섹션의 기본 속성정보는 아래와 같다.
 - IMAGE_SCN_CNT_INITIALIZED_DATA
 - IMAGE_SCN_MEM_READ
 - IMAGE_SCN_MEM_WRITE 


[.rdata]
.rdata 섹션은 읽기전용 섹션으로 상수와 배열로 직접 정의된 문자열과 런타임 라이브러리에서 사용하는 에러 메시지 등이 저장된다. 가끔 debug섹션이나 DLL import 섹션이 크기가작고 읽기전용 속성을 가지면 .rdata 섹션으로 통합되는 경우가 있는데 이러한 현상이 일어나는 이유는 아직 밝혀지지 않았다. 
해당 섹션의 기본 속성정보는 아래와 같다.
 - IMAGE_SCN_CNT_INITIALIZED_DATA
 - IMAGE_SCN_MEM_READ 


[.idata, .edata 섹션]
.idata 섹션은 import table이 들어있으며, .edata 섹션은 export table이 의미한다. 이 섹션들은 실행하는데 꼭
필요한 섹션은 아니다.
.idata 섹션의 기본 속성정보는 아래와 같다.
 - IMAGE_SCN_CNT_INITIALIZED_DATA
 - IMAGE_SCN_MEM_READ
 - IMAGE_SCN_MEM_WRITE

.edata 섹션으 기본 속성정보는 아래와 같다.
 - IMAGE_SCN_CNT_INITIALIZED_DATA
 - IMAGE_MEM_READ 


[.reloc 섹션]
해당 섹션은 PE 파일이 메모리상에 로드 될 때 재배치에 관해 참조하는 정보가 들어있는 섹션이다.
실행파일의 경우 이 섹션은 필요하지 않을 수 있지만, DLL 파일의 경우 메모리에 로드 될때 재배치를 염두하고 있기 때문에 이 섹션이 없으면 실행이 되지 않을 수도 있다.
 - IMAGE_SCN_MEM_READ
 - IMAGE_SCN_CNT_INITIALIZED_DATA
 - IMAGE_SCN_TYPE_NOLOAD 


마지막으로 남은 .rsrc 섹션은 트리구조로 되어 있어 조금 내용이 많아 다음글에서 다루도록 하겠다.
 

'[+] Information > [-] RCE' 카테고리의 다른 글

Oter : Android Revese Engineering Tool  (8) 2012.01.30
PE 구조 (8)  (0) 2012.01.01
PE 구조 (7)  (0) 2012.01.01
PE 구조 (6)  (0) 2011.12.31
PE 구조 (5)  (0) 2011.12.31
이번에는 PE 헤더 영역에 3번째 부분인 PE File Optional Header 부분에 대해 알아 볼 차례이다.

[PE File Optional Header]
이 부분은 실행파일의 실행정보가 담긴 부분이며, 필수적인 부분이어서 PE File Header 부분보다 더 중요시 된다.
Option이라는 이름이 붙은 이유는 오브젝트가 이 영역을 선택적으로 가질 수 있기 때문인데, 정작 오브젝트에서는 별다른 기능을 발휘하지 않는다.
PE File Optional Header 부분은 IMAGE_OPTIONAL_HEADER 구조체로 되어 있으며, 크기가 유동적이고 앞서 보았던
IMAGE_NT_HEADER의 SizeOfOptionalHeader 구조체멤버에 의해 크기가 결정 되며, PE File Header 바로 뒤에 위치해 있다. IMAGE_OPTIONAL_HEADER 구조체는 Standard Fields, NT additional Fields, IMAGE_DATA_DIRECTORY로 구분이 된다. 이제부터 3가지에 대해서 상세히 알아 볼 것이다. 


[Standard Fields]
파일을 로드하고 실행하는것에 대한 정보가 들어있다.
아래는 IMAGE_OPTIONAL_HEADER안에 있는 Standard Fields 영역에 구조이다.

[그림 1 - Standard Fields]


아래 notepad.exe 파일의 Standard Fields 영역을 보면서 각 구조체 멤버에 대해 설명하겠다.

[그림 2 - Standard Fields 영역의 구조체 멤버들 표시]


 - Magic : 실행 파일의 상태를 나타내는 부호없는 정수 값을 가지고 있으며, 이 값이 "0x010B" 라면 일반적인 실행 파일을
               뜻하는 것이고, "0x0107" 이라면 롬이미지, "0x020B" 라면 64bit Executable 타입이라는 것을 의미한다.
               오프셋은 0x00 ~ 0x01이며, 크기는 2바이트이다.
               위 이미지에서는 "0x010B" 값을 가지고 있으므로 일반 실행파일을 뜻하는 것을 알 수 있다.

 - MajorLinkerVersion : 링커의 상위 버전넘버를 저장하는 멤버이다. 오프셋은 0x02이며, 크기는 1바이트 이다.
                                  위 이미지에서는 "0x09" 라는 값을 가지고 있다.

 - MinorLinkerVersion : 링커의 하위 버전넘버를 저장하는 멤버이다. 오프셋은 0x03이며 크기는 1바이트 이다.
                                  위 이미지에서는 "0x00" 이라는 값을 가지고 있다. 

 - SizeOfCode : 코드 섹션(.text)의 크기 정보를 가지고 있으며, 코드 섹션이 여러개라면 그것들의 합에 대한 값을
                       가지고 있다. 오프셋은 0x04 ~ 0x07이며, 크기는 4바이트 이다.
                       위 이미지에서는 "0x0000A800" 의 값을 가지고 있다. 이 값은 10진수로 변환하면  "43008" 이 되므로
                       43008바이트의 크기를 가지고 있는 것이 된다.

 - SizeOfInitializedData : 초기화된 데이터 섹션의 크기를 값으로 가지고 있으며, SizeOfCode 멤버와 마찬가지로 자신이
                                    담당하고 있는 섹션의 수가 여러개라면 그들의 합에 대한 값을 가진다. 오프셋은 0x08 ~ 0x11
                                    이며, 크기는 4바이트 이다.위 이미지에서는 "0x00022400" 값을 가지고 있으며 10진수로
                                    변환시 "140288" 이 되므로 140288바이트의 크기를 가지고 있는 것이 된다.

 - SizeOfUninitializedData : 초기화되지 않은 데이터 섹션의 크기를 값으로 가지고 있으며, 섹션이 여러개 일시 위의
                                       구조체 멤버와 동일한 성격을 지닌다. 오프셋은 0x12 ~ 0x15이며, 크기는 4바이트 이다.
                                       위 이미지에서는 "0x00000000" 이라는 값을 가지고 있으며 이는 "0"을 뜻한다. 즉 초기화
                                       되지 않은 데이터가 없다는 뜻이 된다.

 - AddressOfEntryPoint : 메모리에 맵핑된 상태에서의 실행 코드 주소를 가지고 있다. 이 주소는 절대적인 주소가 아닌
                                    상대적인 주소(RVA)이며, 보통 .text 섹션 내의 특정 주소를 가리키게 된다. 실행 파일에서의
                                    이 주소는 실행 코드의 시작 주소이며, 디바이스 드라이버에서는 초기화 함수의 주소가 된다.
                                    반면 DLL 파일은 이 값이 선택적이며, 이 값이 없다면 반드시 0으로 되어야 한다. 오프셋은
                                    0x16 ~ 0x19 이며 크기는 4바이트 이다. 위 이미지에서는 "0x003689"라는 값을 가지고
                                    있다.

 - BaseOfCode : 실행 파일이 메모리에 맵핑된 상태에서의 코드섹션(.text) 주소를 가지고 있다. 이 값은 상대적 주소인
                         RVA 값이다. 오프셋은 0x20 ~ 0x23이며, 크기는 4바이트 이다. 위 이미지에서는 "0x00001000"
                         이라는 값을 가지고 있다.

 - BaseOfData : 실행 파일이 메모리에 맵핑된 상태에서의 데이터 섹션(.data) 주소를 가지고 있다. 이 값은 상대적 주소인
                        RVA 값이다. 오프셋은 0x24 ~ 0x27이며, 크기는 4바이트 이다. 위 이미지에서는 "0x0000C000"
                        이라는 값을 가지고 있다.


 위에서 RVA 라는 단어가 많이 나온다. 이쯤에서 RAV란 무엇인지 알고 가는 것이 좋을 것 같다.

[RVA(Relative Virtual Address)]
실행파일이 프로세스를 만들고 실행파일의 코드와 데이터가 가상메모리에 맵핑이되면 메모리에 맵핑되는 지점의 시작 주소가 베이스 주소(Base Address)가 된다. RVA는 이 가상 메모리상의 베이스 주소를 기준으로 로드된 실행 파일의 상대적인 위치를 의미한다. 가상메모리에서의 가상주소는 아래와 같은 형식으로 구할 수 있다.

가상 주소 = 베이스 주소(Base Address) + RVA
RVA는 가상 메모리에 맵핑된 이후의 오프셋 값이므로 PE 파일상의 오프셋과 같다고 생각하면 안된다.
물론 PE 파일은 가상메모리에 그대로 맵핑이 되어 순서가 맵핑 되기전과 같지만, 가상메모리에 맵핑이 되면 섹션 사이에
패딩이 생겨 오프셋값이 달라진다. 


이번에는 NT Additional Fields 영역을 알아볼 차례이다.

[NT Additional Fields]
이 영역은 Standard Fields 바로 다음부터 시작되며, 많은 구조체 멤버로 이루어져 있다.
이 영역에서 제공되는 정보는 윈도우 링커와 로더가 사용하는 정보다.
아래는 해당 영역의 구조이다.

[그림 3 - NT Additional Fields]

링커와 로더가 사용하는 정보다 보니 32bit 실행 파일과 64bit 실행 파일의 오프셋이 조금 다르다.
아래 이미지는 32bit 실행 파일이므로 참고하기 바란다.(같은 구조체이기 때문에 오프셋은 계속 이어감)

[그림 4 - NT Additional Fields의 구조체 멤버들 표시]

 - ImageBase : 가상메모리에 로드된 실행 파일의 주소를 가지고 있다. 이 값은 반드시 64KB의 배수여야 한다. 오프셋은
                       0x28 ~ 0x 31이며, 크기는 4바이트 이다. 위 이미지에서는 "0x01000000" 이라는 값을 가지고 있다.
* 참고 : ImageBase 구조체 멤버값과 Standard Fields의 BaseOfCode값을 더하면 .text 가상메모리 주소다

 - SectionAlignment : 가상 주소에 맵핑 될 때 섹션이 할당 받을 가상 주소의 기준값을 가지고 있다. 섹션은 메모리에
                               맵핑 될 때 섹션별로 맵핑되기 때문이다. 섹션의 시작 주소는 항상 메모리 페이지의 배수여야 하므로
                               이 값은 FileAlignment와 같거나 커야 하며, 기본 값은 페이지의 크기와 같다. 오프셋은
                         0x32 ~ 0x35이며, 크기는 4바이트 이다. 위 이미지에서는 "0x00001000" 이라는 값을 가지고 있
                               다. 이 값이 BaseOfCode와 같은 것을 볼 수 있는데 이는 .text 섹션부터 메모리에 맵핑 된다는 것을
                               의미한다.

- FileAlignment : PE 파일 내에서 섹션들이 시작하는 주소의 기준 값이다. 따라서 PE 파일내에서의 섹션이 시작하는
                         주소는 항상 이 값의 배수가 된다. 이 값은 2에서 512사이에 있는 2의 멱승이거나 64KB가 되지만
                         기본값은 512이다. SectionAlignment의 값이 메모리 페이지 크기보다 작다면 FileAlignment의
                    값과 동일하여야 한다.
 오프셋은 0x36 ~ 39이며, 크기는 4바이트 이다. 위 이미지에서는
                    "0x00000200" 값을 가지고 있는데 이 값을 10진수로 변환하면 512가 된다. 기본 값을 가지고 있다는
                         뜻이 된다. 

 - MajorOperatingSystemVerison : 실행 파일을 실행하는데 필요한 OS의 최소 상위버전의 값을 가지고 있다.
                                                  오프셋은 0x40 ~ 0x41이며, 크기는 2바이트 이다. 위 이미지에서는 "0x0006"
                                                  이라는 값을 가지고 있다.

 - MinorOperatingSystemVersion : 실행 파일을 실행하는데 필요한 OS의 최소 하위버전의 값을 가지고 있다.
                                                  오프셋은 0x42 ~ 0x43이며, 크기는 2바이트 이다. 위 이미지에서는 "0x0001"
                                                  이라는 값을 가지고 있다.

 - MajorImageVersion : 실행파일의 상위버전의 값을 가지고 있다. 오프셋은 0x44 ~ 0x45이며, 크기는 2바이트 이다.
                                  위 이미지에서는 "0x0006" 이라는 값을 가지고 있다. 

 - MinorImageVersion :  실행파일의 하위버전의 값을 가지고 있다. 오프셋은 0x46 ~ 0x47이며, 크기는 2바이트 이다.
                                   위 이미지에서는 "0x0001" 이라는 값을 가지고 있다. 

 - MajorSubsystem : 실행 파일을 실행하는데 필요한 서브시스템의 상위버전의 값을 가지고 있다. 오프셋은
                               0x48 ~ 0x49이며, 크기는 2바이트 이다. 위 이미지에서는 "0x0006" 이라는 값을 가지고 있다.

 - MinorSubsystem : 실행 파일을 실행하는데 필요한 서브시스템의 상위버전의 값을 가지고 있다. 오프셋은 
                               0x50 ~ 0x51이며, 크기는 2바이트 이다. 위 이미지에서는 "0x0001" 이라는 값을 가지고 있다.

 - Win32VersionValue : 이 멤버는 VC++6.0 SDK까지는 예약 영역이었으며 7.0부터 지금의 이름으로 바뀌었다. 하지만
                                  여전히 사용하지 않아 보통 0으로 되어있다. 오프셋은 0x52 ~ 0x55이며, 크기는 4바이트 이다.
                                  위 이미지에서는 0의 값을 가지고 있다.

 - SizeOfImage : 메모리에 로드되었을 때 실행 파일의 크기 값을 가지고 있다. 이 값은 헤더를 포함했을 때의 크기이며,
                         반드시 SectionAlignment의 배수여야 한다. 이 값을 기준으로 해서 가상 메모리에서 실행 파일을
                         맵핑할 공간을 예약한다.
                         오프셋은 0x56 ~ 0x59이며, 크기는 4바이트 이다. 위 이미지에서는 "0x00030000" 이라는 값을
                         가지고 있다.

 - SizeOfHeader : DOS Stub, PE 헤더, 섹션 헤더의 합 값을 가지고 있다. 이 값은 무조건 FileAlignment의 배수여야
                          한다. 오프셋은 0x60 ~ 0x63이며, 크기는 4바이트 이다. 위 이미지에서는 "0x00000400" 값을
                          가지고 있다.

 - Checksum : 실행 파일의 체크섬 값을 가지고 있다. 체크섬 알고리즘은 IMAGEHELP.DLL 파일에 있으며 이 값은 모든
                      드라이버와 부팅시 로드된 DLL 파일, 중요한 윈도우 프로세스가 로드한 DLL 파일을 검증 할 때 사용된다.
                      오프셋은 0x64 ~ 0x67이며, 크기는 4바이트 이다. 위 이미지에서는 "0x00039741" 이라는 값을 가지고
                      있다.

 - Subsystem : 실행 파일을 실행하는데 필요한 서브 시스템의 값을 가진다. 오프셋은 0x68 ~ 0x69이며, 크기는
                       2바이트 이다. 위 이미지에서는 "0x0002" 라는 값을 가지고 있다. 목록표에 따르면 Windows GUI
                       서브시스템을 뜻한다. 아래는 Subsystem 값 목록표이다.

[그림 5 - Subsystem 값 목록표]

 - DllCharacteristics : PE 파일이 DLL 파일인 경우 파일의 속성 정보를 의미한다. 오프셋은 0x70 ~ 0x71이며, 크기는
                         2바이트 이다. 위 이미지에서는 "0x8140" 이라는 값을 가지고 있다.

 - SizeOfStackReserve : 예약할 스택의 크기 값을 가지고 있다. 오프셋은 0x72 ~ 0x75이며, 크기는 4바이트 이다.
                                   위 이미지에서는 "0x00040000" 이라는 값을 가지고 있다.

 - SizeOfStackCommit : 커밋할 스택의 크기 값을 가지고 있다. 오프셋은 0x76 ~ 0x79이며, 크기는 4바이트 이다.
                                   위 이미지에서는 "0x00011000"이라는 값을 가지고 있다.

 - SizeOfHeapReserve : 예약할 힙의 크기 값을 가지고 있다. 오프셋은 0x80 ~ 0x83이며, 크기는 4바이트 이다.
                                   위 이미지에서는 "0x00100000" 이라는 값을 가지고 있다. 

 - SizeOfHeapCommit : 커밋할 힙의 크기 값을 가지고 있다. 오프셋은 0x84 ~ 0x87이며, 크기는 4바이트 이다.
                                  위 이미지에서는 "0x00001000" 이라는 값을 가지고 있다.

 - LoaderFlags : 예약된 영역으로 0으로 채워져 있다. 오프셋은 0x88 ~ 0x91이며, 크기는 4바이트 이다.
                        위 이미지에서는 0 값을 가지고 있다. 

 - NumberOfRvaAndSize : Optional Header의 나머지 부분에 있는 데이터 디렉터리 엔트리의 숫자 값을 가지고 있다.
                                      오프셋은 0x92 ~ 0x95이며, 크기는 4바이트 이다. 위 이미지에서는 "0x00000010" 값을
                                      가지고 있다. 



글이 많이 길어진 관계로 나머지 한 부분인 IMAGE_DATA_DIRECTORY 구조체는 다음 글에서 다루도록 하겠다.

'[+] Information > [-] RCE' 카테고리의 다른 글

PE 구조 (6)  (0) 2011.12.31
PE 구조 (5)  (0) 2011.12.31
PE 구조 (4)  (0) 2011.12.30
PE 구조 (3)  (0) 2011.12.30
PE 구조 (2)  (0) 2011.12.29
이제부터 알아 볼 PE 영역은 PE 파일의 시작 부분이라고 할 수 있는 PE Header 영역이다.

PE Header 영역에는 PE File Signature, PE File Header, PE File Optional Header 영역이 있다.

PE Header 영역은 IMAGE_NT_HEADERS 구조체로 이루어져 있는데 구조체 정보는 다음과 같다.

[그림 1 - IMAGE_NT_HEADERS 구조체 정보]

위에 정의된 구조체는 64bit 구조체이며 아래는 32bit 구조체이다.

어느정도 직관적인 구조체 멤버이름을 통해서 왜 PE 헤더영역이 3가지로 나누어 졌는지 알 수 있다.

이제부터 PE 헤더 영역을 구성하고 3가지 영역에 대하여 알아 볼 것이다.

[PE File Signature]
이 영역은 DOS의 e_magic 구조체멤버처럼 PE 영역의 시작을 알리는 값을 가지고 있는 영역이다. 모든 파일에서 그 값은 항상 동일하며 그 값은 "PE/0/0(0x50/0x45/0x00/0x00)" 이다.
이 Signature 값 또한 메모리나 파일시스템 분석에서 삭제된 실행파일을 찾는데에 중요한 단서가 된다. 
아래는 notepad.exe 파일의 PE File Signature 값을 보여주는 이미지이다.

[그림 2 - PE File Signature 영역]

여기서 참고로 봐둘 점이 있다. 이전 글에서 설명했다 싶이 DOS MZ HEADER 영역의 e_lfanew 구조체멤버는 IMAGE_NT_HEADER의 주소를 가지고 있다고 설명하였는데 여기서 그 사실을 확인 할 수 있다.


[PE File Header]
이 영역은 실행 파일 자체의 메타데이터를 가지고 있으며, 길이는 20바이트이다.
구조체는 IMAGE_FILE_HEADER 구조체를 사용하며, 구조체 정보는 아래와 같다.

[그림 3 - IMAGE_FILE_HEADER 구조체 정보]


아래는 notepad.exe의 PE File Header 영역인데 이것을 가지고 각 구조체 멤버에 대해서 설명하겠다.

[그림 4 - PE File Header 영역]

 - Machine : 해당 구조체 멤버는 실행 파일이 사용하는 CPU를 나타내는 번호를 가지고 있다.
                   오프셋은 0이며, 크기는 2바이트이다. 위 이미지에서는 i386을 뜻하고 있는 "0x014C"를 가지고 있다.
 - NumberOfSections : 해당 구조체 멤버는 실행파일이 가지고 있는 섹션의 개수를 의미하며, 오프셋은 2이고, 크기는
                                 2바이트이다. 위 이미지에서는 "0x0004"를 가지고 있어 섹션의 개수가 4개라는 것을 알 수 있다.
                                 만약 섹션의 삭제, 추가를 하게 되면 이 구조체 멤버의 값 또한 변경해줘야 한다.
 - TimeDataStamp : 실행파일이 컴파일 된 시가으로 이 시간은 컴파일한 컴퓨터의 시스템 시간을 의미한다. 32비트
                             유닉스 포맷으로 GMT를 기준으로 한다. 위 이미지에서는 "0x4A5BC60F" 값을 가지고 있으며,
                             이 값을 10진수로 변환하였을 경우 "1247528463" 라는 숫자가 되며 이 숫자를 우리가 알아 볼 수
                             있는 날짜로 변환하면 아래와 같다.

[그림 5 - Python을 이용하여 변환]

 - PointerToSymbolTable : COFF 심볼 파일의 오프셋을 값으로 가지고 있다. 이 부분은 컴파일러에 의해 생성된 OBJ
                                       파일이나 디버그 모드로 만들어져서 COFF 디버그 정보를 가진 PE 파일에서만 사용된다.
                                       COFF 심볼 테이블은 이제 더 이상 사용하지 않아 이 값은 반드시 0으로 설정되어야 한다.
                                       위 이미지에에서는 설명과 동일하게 "0"으로 셋팅되어 있다.

 - NumberOfSymbols : 심볼 테이블에 있는 엔트리 개수를 나타내며, COFF 심볼 테이블은 더 이상 사용되지 않으므로
                                 반드시 0으로 설정되어야 한다. 위 이미지에서는 설명과 동일하게 "0"으로 셋팅되어 있다.

 - SizeOfOptionalHeader : Optional Header의 크기를 값으로 가지고 있다. 이 값은 실행파일에서만 필요하다. 일반적으로
                                     32bit 시스템은 E0의 값을 가진다.
 - Characteristics : 파일의 속성을 결정하는 값을 가지고 있다. 위 이미지에서는 32비트 실행파일의 의미를 지닌 "0x0102"
                            값이 셋팅되어 있는 것을 볼 수 있다. 


나머지 하나인 PE File Optional Header는 다음 글에서 알아 볼 것이다.

아직 PE File Header 에 대한 설명이 남았고 참고 할 표도 있어 글이 너무 길어지는 것을 방지하기 위해 다음 글에서

다루기로 한다.

이번에는 포렌식 관점에서의 중요한 구조체멤버들을 되짚어 보자.

[포렌식관점에서의 구조체멤버]
현재 영역에서 모든 정보를 파악 할 필요는 없다. 중요한 내용만 보면 되는 것이다.
Machine 멤버의 경우 라이브 리스폰스나 메모리 분석등 다른 방법으로도 수집할 수 있는 정보이면서 중복되는 정보이므로, 보지 않아도 되고, Symbol 테이블에 관련된 멤버도 요즘에는 사용되지 않는 멤버이므로 보지 않아도 된다.

- TimeDateStamp : 파일의 생성시간에 대해 정보를 제공한다. 하지만 이 시간은 조작가능성을 배제할 수 없고, 다른
                            증거와 연결지어야 할 필요가 있다.
- SizeOfOptionalHeader : 해당 파일이 어느 시스템에서 만들어졌는가의 대한 정보를 제공한다. 요즘 도구들은 32, 64bit
                                    시스템의 분석을 지원하긴 하지만, 간혹 지원하지 못하는 경우가 있을 수 있어 이럴 경우 해당
                                    시스템에 맞는 분석도구를 사용하여야 한다. 그렇기에 반드시 확인 해 볼 필요가 있다.
- Characterstics : 해당 파일의 속성이 어떤 것인지에 대한 정보를 제공한다. 특히 exe와 dll 파일을 구분 할 때 유용하다.
                          파일카빙을 하였을 경우 해당 파일이 어떤 파일인지 구분이 가지 않으므로, 이 부분을 확인하면 어떤
                          파일인지 알 수 있을 것이다.


[참고]
* Machine 멤버에서의 값 목록표

[그림 6 - Machine 값 목록표]

* Characterstics 속성 목록표

 [그림 7 - Characterstics 값 목록표]

참고로 위 notepad.exe에서 Characterstics 값이 0x0102 였는데 이건 IMAGE_FILE_32BIT_MACHINE의 값과

IMAGE_FILE_EXECUTABLE_IMAGE 값이 합쳐진 것이다. 

'[+] Information > [-] RCE' 카테고리의 다른 글

PE 구조 (5)  (0) 2011.12.31
PE 구조 (4)  (0) 2011.12.30
PE 구조 (3)  (0) 2011.12.30
PE 구조 (2)  (0) 2011.12.29
PE 구조 (1)  (0) 2011.12.29
이번 글에서 알아볼 PE 구조의 영역은 DOS 영역이다.

이 영역은 윈도우 실행 파일을 DOS 모드에서 실행하려고 할 때 사용자에게 에러 메시지를 보여주기 위해 존재한다.

실제로 이 영역은 윈도우 실행파일이 윈도우에서 실행할 때에는 아무런 영향을 주지 않는 부분이어서 볼만한 내용이 많지는

않다.

DOS MZ Header와 DOS Stub Program 영역으로 이루어져 있는 이 DOS 영역에 대해서 자세히 알아보자.

[DOS MZ Header]
이 영역은 WinNT.h 헤더파일에 정의되어 있으며, 영역의 구조부터 알아보면 아래와 같다.

[그림 1 - DOS MZ Header의 구조체 구조]

여기서 눈여겨 볼 구조체 멤버는 e_magic과 e_lfanew 구조체 멤버이다.
다른 구조체 멤버들은 사용하지 않거나 PE 파일포맷 내에서는 사실상 의미가 없는 것들이다.

 - e_magic : 이 구조체 멤버는 DOS MZ Header의 맨 앞(PE 파일 맨 앞)을 나타내며 16진수로는 "4D 5A" 값을 가지고
                   아스키코드로 변환하면 "MZ" 라는 값을 가진다. 참고로 MZ는 도스를 최초로 설계한 사람 중 한명인
                   Mark Zbikowksi의 이니셜이라고 한다. 모든 윈도우의 실행파일은 MZ로 시작하기 때문에 이 값을 이용해  
                   실행파일을 찾을 수도 있다. 참고로 오프셋은 0x00 ~ 0x01
- e_lfanew : 이 구조체 멤버는 PE 파일의 머리 격인 IMAGE_NT_HEADER를 가리키는 오프셋 값을 가지고 있다.
                  참고로 오프셋은 0x3C ~ 0x3F

아래 이미지는 notepad.exe의 DOS MZ HEADER 영역을 보여준다.

[그림 2 - DOS MZ HEADER 영역]

이 두값만 올바르다면, 프로그램은 실행하는데 문제가 없다.


[DOS Stub Program]
이 부분은 사용자가 DOS 모드에서 윈도우용 실행파일을 실행 했을시 아래와 같은 문구를 출력해주기 위한 코드가 있는 부분이다.

"This Program connot be run is DOS mode" 

이 부분은 오프셋 0x40 ~ 0x7F 까지 이다.

[그림 3 - DOS Stub Program 부분]


'[+] Information > [-] RCE' 카테고리의 다른 글

PE 구조 (4)  (0) 2011.12.30
PE 구조 (3)  (0) 2011.12.30
PE 구조 (2)  (0) 2011.12.29
PE 구조 (1)  (0) 2011.12.29
Lena's Tutorial 11 상세 분석  (0) 2011.10.13

+ Recent posts