이메일을 적으시면 보안관련 소식을 받을수 있습니다.
이메일:


작성자 : 청정산소
편집자: 엔시스 (sis@sis.pe.kr)


안녕하세요~!

1부 Packer의 종류와 활용편에서 많은 관심가져 주셔서 감사합니다.

오늘은 2부 PE Structure에 대하여 설명하겠습니다.


PE(Portable Excutable)은 1부에서 간단히 설명했듯이, Win32 플랫폼에서 사용되는 실행프로그램(EXE, DLL, OBJ 등)의 기본적인 파일 구조이다.

'이 PE구조로 된 PE파일들은 플랫폼에 상관없이 Win32 OS가 돌아가는 시스템이면 어디서든 실행가능하다.' 라는 의미에서 Portable Excutable이라는 이름을 붙인 것이다.


PE파일의 구조는 다음과 같은 구조로 이루어져 있다.


※ PE파일의 구조는 "WinNT.h" 파일에 정의되어있다. 참고하면서 읽으면 더욱 좋습니다.
C:\Program Files\Microsoft Platform SDK\include\WinNT.h 또는 비쥬얼 스튜디오\include\WinNT.h

※ 여기서는 PE구조의 모든 항목에 대해서 다루지 않고 중요한 요소에 대해서만 설명하겠습니다.

그림1. PE구조

1. DOS_MZ_HEADER

그림2. DOS_MZ_HEADER

  - 모든 PE파일은 0x00부분에 '4D5A'로 시작한다. 5A4D는 ACSII로 'MZ'라 하는데, 이것은 DOS를 설계한 사람
    중의 한명인 'Mark Zbikowski'의 이니셜을 딴 것이다.
    (왜 5A4D으로 읽을까? Little Endian방식이기 때문이다!)

  - 4D5A이후에 '00'으로 채워진 부분은 별의미없는 항목이니 넘어가도 된다.

  - 0x3c 부분에 '40 00 00 00' 부분은 다음 PE헤더의 옵셋을 지정해주는 항목이다.
    즉, PE헤더의 주소는 0x40 이 된다.


2. DOS Stub

그림3. DOS Stub

 - 저 위의 'This program cannot be run in Dos mode'라는 메세지는 도스나 윈도우3.1에서 Win32 PE파일을  
  실행하게 되면 이 문자열이 출력되고 프로그램이 종료된다. 지금 환경에서는 필요없는 항목이니 무시하자!


3. PE HEADER (IMAGE_NT_HEADERS)


그림4. IMAGE_NT_HEADER
※ 그림3과 주소가 중복되는데 무시하세요.(두개가 다른파일입니다.)


- PE HEADER = IMAGE_NT_HEADER = Signature + IMAGE_FILE_HEADER + IMAGE_OPTIONAL_HEADER 
                                                        +  IMAGE_DATA_DIRECTORY


- IMAGE_NT_HEADER는 DOS HEADER의 마지막부분에 나왔던 PE HEADER의 옵셋부터 시작됩니다.
  0x40부분에 '5045'는 Signature로서, 이것이 'PE파일이다!'를 나타내줍니다. PE파일은 꼭 '5045'로 시작해야합
  니다.


- Signature 다음으로 IMAGE_FILE_HEADER가 있습니다.
  '4C01'은 Machine 코드로 CPU ID를 나타낸다. Intel 386 CPU의 값은 '014C'이다.
  WinNT.h 에 정의 되어있습니다.

- '0200'은 NumberOfSections 로 섹션의 갯수를 지정해 주는 곳입니다. 여기서는 2개로 지정되어있군요.


- 'E000'은 SizeOfOptionalHeader 로 다음에 올 IMAGE_OPTIONAL_HEADER의 크기를 지정하는 곳입니다.
  32Bit PE경우 0xE0(224바이트), 64Bit PE경우 0xF0(240바이트)이다.


- '0200'은 Characteristics 로 이 PE파일의 특정 정보를 나타내는 플래그로서  WinNT.h 에 플래그가 정의되어 
   있다. 여기서 0200은 IMAGE_FILE_EXECUTABLE_IMAGE로 실행파일 이미지를 나타낸다.


- Characteristics으로 IMAGE_OPTIONAL_HEADER가 나온다.
  '0B01'은 IMAGE_OPTIONAL_HEADER를 나타내는 시그니쳐로서, 32Bit PE는 '0x010B' 64Bit PE는 '0x020B'로
  표현한다.


- '00100000'은 AddressOfEntryPoint로 프로그램의 시작점의 옵셋을 나타내준다.
   이 프로그램의 시작점은 '0x1000'이 된다.


- '00004000'은 ImageBase로 해당PE가 가상 주소 공간에 매핑될때 매핑시키고자하는 메모리상의 시작 주소를
  나타낸다. EXE파일의 기본 ImageBase는 '0x00400000'이고 DLL은 '0x10000000'이 된다.


- '00100000'은 SectionAlignment로 PE파일이 메모리에 매핑될때 각 섹션의 시작 주소는 언제나 이    
   SectionAlignment 필드에서 지정된 값의 배수가 되는 가상 주소가 된다. 보통 '0x1000'이 된다.


- '00200000'은 FileAlignment로 PE파일 내에서 섹션들의 정렬 단위를 나타낸다. 보통 '0x200'이나 '0x100'이다.
  즉, 처음섹션이  0x100부터 시작해서 0x110에서 끝났어도 두번째 섹션은 FileAlignment에서 설정한 값의 배수로 시작된다. 이 값이 0x100이라 하면, 두번째 섹션은 0x200에서 시작되는 것이다.


- '0400'은 MajorSubsystemVersion으로 본 PE를 실행하는데 필요한 서브시스템의 최소 버전을 의미한다.
  이 값은 0x4로 고정되어있다.


- '00300000'은 SizeOfImage로 ImageBase필드가 가르키는 주소 값으로부터 이 PE의 마지막 섹션의 끝까지의 
  크기이다. 섹션의 갯수와 크기에 따라 달라질수 있다.


- '00400000'은 SizeOfHeader로 모든 헤더와 섹션테이블의 크기를 모두 합친 바이트수이다.
  이 값도 프로그램에 따라 다르다.


- '0200'은 Subsystem으로 이 PE파일이 Win32 CUI환경이면 '0x03'값을 가지고, Win32 GUI환경이면 '0x02'를 가지게 된다. 이 프로그램은 Windows GUI 어플리케이션이다.


- '00001000' '00100000' '00001000' '00100000' 는    SizeofStackReserve, SizeofStackCommit, 
   SizeofHeapReserve, SizeofHeapCommit으로 스택과 힙의 크기와 속성에 관계된 설정인데 디폴트 값이다.

- '02000000' 은 NumberOfRvaAndSizes로 다음에 올 IMAGE_DATA_DIRECTORY 구조체 배열의 원소 갯수를 
  의미한다. 보통은 '0x10'으로 16개의 갯수를 가지지만, PE의 목적에 따라 갯수를 조정해서 쓸수있다.


- 다음은 128byte의 IMAGE_DATA_DIRECTORY 구조체의 배열이 온다.
  여기서는 Export, Import, Resource, Exception, Security Directory등의 시작주소와 그 크기를 가르키는 RVA
  값을 가진다.


※ RVA란?
  RVA(Relative Virtual Adress)로 PE파일이 메모리상에 로드되었을때 ImageBase로 부터 가르키는 옵셋의 상
  대적인 주소를 말한다.


4. Section Table(IMAGE_SECTION_HEADER)

그림5. IMAGE_SECTION_HEADER



 - IMAGE_DATA_DIRECTORY 구조체 다음에 바로 IMAGE_SECTION_HEADER가 위치하게 됩니다.

 - 처음 '46756E6374696F6E'는 섹션의 이름으로 자기가 섹션의 목적에 맞게 넣어주면 됩니다.

 - '00100000' 은 VirtualSize로 파일 바이트 정렬 단위와 관계없이 섹션의 실제 바이트수를 나타낸다.

 - '00100000' 은 VirtualAddress로 해당 섹션을 매핑시켜야할 가상주소 공간상의 RVA를 가지고 있다.

 - '00200000' 은 SizeofRawData로 VirtualSize 필드값에 대한 파일정렬값의 배수로 라운드없 된 값이다.
 
 - '00020000' 은 PointerToRawData로 해당 섹션의 PE파일 상에서 시작하는 실제 파일의 옵셋값이다.
    쉽게 섹션의 시작주소라고 생각하면 된다.

 - '20000060' 은 Characteristics로 해당 섹션의 속성을 나타내는 플래그의 집합니다. 플래그 정의는 WinNT.h에
   있다.


5. Section


그림6. SECTION


 - 위의 섹션헤더에서 PointerToRawData의 옵셋부터 시작한다.
   프로그램에 맞게 코드나 데이터들이 들어가게 된다.



대략적인 PE구조는 이렇습니다.

더 자세히 쓰려면 너무 길어져서 PE파일에 필수요소들만 설명했습니다.
여기서 설명안한부분은 다 '00'으로 채워놓으셔도 실행하는데는 지장이없습니다.

# IMAGE_OPTIONAL_HEADER에서 IMAGE_DATA_DIRECTORY 안에 Import Directory라는 것이 있습니다.
  Import Directory, Import Section은 나중에 OEP(Original Entry Point)를 찾고 덤프를 떠 Unpacking을 할때 중
  요한 내용이라 다음장에서 자세히 다루도록 하겠습니다.


그럼 2장은 여기서 마치겠습니다~!





****************************************************************************************************

본 포스팅의 저작권은 보안인닷컴과 작성자에 있으며 상업적 이용을 배제하며 콘텐츠 이용시에는 반드시 출처와 링크를 이용해 주시기 바랍니다. 무단도용은 저작권법에 저촉을 받습니다..

****************************************************************************************************

Posted by 비회원

댓글을 달아 주세요

  1. Favicon of https://whoaru.tistory.com BlogIcon 후아유! 2009.03.26 00:08 신고  댓글주소  수정/삭제  댓글쓰기

    PE구조 두번째까지 나왔네요^^
    어렵게 공부하던부분이라^^ 감사합니다^^

  2. 기초없이그냥 2009.05.28 10:44  댓글주소  수정/삭제  댓글쓰기

    해외여행 잘 다녀왔습니다. 이나라는 도무지 알수 없는 나라네요. 그래도 감사합니다

  3. Favicon of https://memocontrol.tistory.com BlogIcon 하얀어둠 2009.06.23 17:37 신고  댓글주소  수정/삭제  댓글쓰기

    으음~2편은 조금 어렵네요 ㅎㅎ 그리고 숫자 00 이거 배열된걸 뭐라고 부르나요?
    원래 명칭이요~ 예전에 어릴 때 게임잡지 부록에 있는 프린세스메이커 1,2 CD에서
    에디터 프로그램이라고 설명해주던, 울트라에디터가 생각나요 ㅋㅋ
    저 숫자 나열된걸 보니... 다시 차근히 공부해봐야겠어요~~