본문 바로가기

Kitri_NCS3기 보안과정/시스템 해킹

[Reverse Engineering]PE-Section Table

참고 : http://zesrever.tistory.com


※ PE 파일이란 ?


 윈도우즈 환경의 실행파일 포맷을 PE 라고 하며, Portable Executable의 약자. 굳이 EXE 파일만 일컫는것이 아니라 SCR,SYS,DLL,OCX등도 포함됨. PE의 이해는 API후킹, 압축실행파일 등과 같은 고급 리버싱기법의 기본 바탕이된다.


PE파일은 디스크상의 모습과 메모리상의 모습이 거의 같다, 실행시 하드에 저장되어 있던 파일의 형태 그대로 메모리에 올라가는 모습을 보인다.

PE를 파악하기위해서는 PE파일의 구성요소와 그 구성요소들의 시작점을 찾는 방법을 잘 숙지해야함.


실행파일 분석기를 만들어보는것이 PE를 연구하는데 가장 효과적인방법...


PE구성요소 

- DOS header

- DOS stub code

- PE header

- Section table

- Section (1~n)


각 구성요소의 시작위치 계산법 

 시작위치

설명 

DOS header

PE 파일은 DOS header로 시작. 디스크상에서의 위치와 메모리상에서의 위치가 다르다.

디스크 : 파일의 첫부분이 DOS header

메모리 : ImageBase에서 시작

DOS stub code

디스크상이나 메모리 상에서  DOS의 스텁 코드는 시작점(Dos header)으로부터 64byte만큼 떨어진곳.


프로그램을 도스모드에서 실행시켯을때 실행되는 코드이며 DOS header 다음에 위치한다. 필수 구성요소가 아니기 때문에 없어도 실행하는데는 지장이 없으며, 크기는 가변적이다.

PE header

e_lfanew에는 4byte의 크기로 DOS header의 마지막에 위치하며  파일의 시작점에서부터 PE 헤더까지의 오프셋 값이 저장되어있음. e_lfanew의 값을 시작주소로 찾으보면 PE헤더를 찾을 수 있다.

Section table

PE의 헤더 시작주소에서 PE 헤더 사이즈를 더해주면 된다. 

PE 헤더 사이즈 (PE signature + File Header + Optional Header)로 구성되어 있습니다.

Section (1~n) 

각 섹션 테이블에 저장된 섹션 헤더를 통해서 확인 가능합니다.

PointerToRawData는 디스크상의 섹션의 위치

VirtualAddress는 메모리상에서의 section의 위치를 가르키는 offset




섹션 : 동일한 성질의 데이터가 저장되어있는 영역


섹션을 왜 쓰나 ?


윈도우의 경우 메모리 프로텍션의 최소단위가 페이지 이다. (PE는 윈도우 실행파일임을 상기하자)

(페이지 단위로 PAGE_EXCUTE_READ,PAGE_EXCUTE_READWRITE, PAGE_EXCUTE_READONLY, PAGE_EXCUTE_READWRITE같은 속성을 설정)


속성에 위배되는 오퍼레이션을 시도 → Access violation 발생 → 메모리 보호 


의 방식으로 진행되는데 이말은 READWRITE + READONLY 처럼 여러개의 속성을 부분적으로 동시에 사용할 수 없다는걸 말한다.

그렇다 보니 프로그램에 포함된 데이터들 중 읽기와 실행이 가능해야 하는 데이터 (실행코드)읽고 쓰기가 가능한 데이터, 읽기만 가능한 데이터구분하기 위해 섹션이라는 개념을 두어 실행파일 생성단계에서 구분해놓도록 하는것.



Section Table 에는 섹션헤더가 있다. 섹션헤더에는 로더가 각 섹션을 메모리에 로드하고 속성을 설정하는데 필요한 정보가 담겨져 있다.


섹션 헤더의 구성


- 섹션의 이름

- 섹션의 파일상의 위치 및 크기

- 메모리상의 위치 및 크기 

- 메모리상에서의 속성값


#define IMAGE_SIZEOF_SHORT_NAME 8


typedef struct _IMAGE_SECTION_HEADER {


BYTE Name[IMAGE_SIZEOF_SHORT_NAME];


union {


DWORD PhysicalAddress;


DWORD VirtualSize;


} Misc;


DWORD VirtualAddress;


DWORD SizeOfRawData;


DWORD PointerToRawData;


DWORD PointerToRelocations;


DWORD PointerToLinenumbers;


WORD NumberOfRelocations;


WORD NumberOfLinenumbers;


DWORD Characteristics;


} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;


#define IMAGE_SIZEOF_SECTION_HEADER

 00

01 

02 

03 

04 

05 

06 

07 

08 

09 

10 

11 

12 

13 

14 

15 

 NAME

Physical Address 

Virtual Size 

 Virtual Size 

Virtual Address 

SizeOfRawData 

 SizeOfRawData 

PointerToRawData

PointerToRelocations 

 PointerToRelocations

 PointerToLinenumbers

NumberOfRelocations 

 NumberOfLinenumbers

Characteristics 

 



Name : 섹션의 이름 . 최대사이즈는 8Byte로 로딩과는 아무 상관없는 

VirtualAddress : 섹션이 로드될 가상주소를 나타내는 필드, RVA 값

SizeOfRawData : 파일상태에서의 섹션의 사이즈 값을 가지고 있다.  file alignment * n

PointerToRawData : 파일상태에서의 섹션이 시작위치

Characteristics : 섹션의 속성 값, 메모리 프로텍션과 관련된 것들로 excute, read, write 등이있다.


로더는 PointerToRawData가 저장한곳에서부터 SizeOfRawData 만큼의 데이터를 읽어들여 Virtual Address에 맵핑한 후에 Characteristics에 설정된 속성정보를 이용하여 페이지 프로텍션을 적용하는것이다.