PE파일 분석 도구 :
실행파일(Executable File)이란 명령(Operation Codes)에 따라 지시된 작업을 수행하도록 하는 파일을 말한다. 이 파일은 실행 코드, 전역 데이터, Import/Export 함수정보, 리소스 데이터 등으로 구성된다. 포맷 종류는 PE(Windows), ELF(Linux, Unix), Mach-O(OS X,iOS), DEX(Android), MZ(Dos)등이 있다.
이때 PE(Portable Executable)파일은 Windows 3.1부터 지원되는 실행파일 형식이다. 이는 유닉스의 COFF(Common Object File Format)를 기반으로 하고 파일 종류는 실행파일(EXE, SCR), 라이브러리(DLL, OCX), 드라이버(SYS), 오브젝트파일(OBJ) 등이 있다.
프로그램이 프로세스가 되면 관련 데이터가 메모리에 올라가게 된다. 운영체제는 가상 메모리를 사용하기 때문에 우리는 실제 주소로 데이터 및 코드를 참조하지 않는다. 페이징 기법으로 인해 물리 메모리는 프레임으로 나누어져 있고 논리 메모리는 페이지로 구분된다. 세그멘테이션 기법은 프로그램을 코드, 데이터, 리소스등을 분리해서 저장하는 방식이다.
메모리 상의 주소 표현방식은 다음과 같다.
- VA(Virtual Address): 가상 메모리상의 절대주소
- RVA(Relative Virtual Address): 기준(ImageBase) 위치에서의 상대주소
- PE 파일 내부데이터는 RVA 형식으로 메모리위치가 지정됨
- VA = ImageBase+ RVA
- RAW: PE 파일내에서의오프셋(offset)
PE파일이 메모리에 올라가면 헤더는 동일하나 바디부분은 참조 위치가 조금 변하게 된다. 아래 그림은 PE 파일 구조와 메모리에 올라갔을 때의 구조를 표현한 그림이다.
- Dos Header, Dos Stub : DOS 시절 사용 (현재 사용 안 함)
- NTHeader :
- 메모리에 올리기 위해 필요한 정보
- 파일 속성 정보
- Section Header : 세션에 관한 읽기, 쓰기 정책
- 세션에 관한 읽기, 쓰기 정책
- 세션 크기 및 기타 정보
- Section : 세션에 대한 내용
- 섹션의 종류는 아래 표와 같다.
종류 |
이름 |
설명 |
Code | .text | 프로그램 실행을 위한 코드 |
Data |
.data |
초기화된 전역변수 (읽기,쓰기 가능) |
.rdata |
읽기 전용 변수 (문자열, C++가상함수) |
|
.bss |
초기화 되지 않은 전역변수(.data에병합) |
|
Import API |
.idata |
Import할 DLL과 그 API에 대한 정보 (IAT) (.rdata에 병합) |
.didat |
Delay-loading importDLL 정보 (프로그램 실행 후 DLL 사용시에만 연결) (릴리즈 모드 시 다른 섹션에 병합) |
|
Export API |
.edata |
Export할 API 정보 (주로 DLL에서 사용) (.text또는 .rdata에 합병) |
Resource |
.rsrc |
리소스 관련 데이터 |
재배치정보 |
.reloc |
기본 재배치 정보(주로 DLL에서 사용) |
TLS |
.tls |
(__declspec(thread) 지시어와 함께 선언되는 스레드 지역 저장소 |
Debugging |
.debug$p |
미리 컴파일된 헤더 사용시에만 존재 |
1. IMAGE_DOS_HEADER (64바이트)
- e_magic : DOS signature -> MZ
- MZ : Mark Zbikowski
- DOS실행파일을 설계한 사람 이니셜
-e_lfanew : NT header RVA형태의 주소값
- 꼭 40이상의 크기를 가질 필요 없음
- 변종 PE를 가능하게함
2. MS-DOS Stub Program (가변적)
- DOS용 실행코드와 데이터로 구성
- 16비트 형태
- 고정되지 않은 크기
- 없어도 됨
3. IMAGE_NT_HEADER (248바이트)
정의 |
값 |
정보 |
IMAGE_FILE_RELOCS_STRIPPED |
0x0001 |
재배치 정보가 없음 |
IMAGE_FILE_EXECUTABLE_IMAGE |
0x0002 |
실행 file image |
IMAGE_FILE_LINE_NUMS_STRIPPED |
0x0004 |
Line 정보가 없음 |
IMAGE_FILE_LOCAL_SYMS_STRIPPED |
0x0008 |
Local 심볼이 없음 |
IMAGE_FILE_AGGRESIVE_WS_TRIM |
0x0010 |
OS가 적극적으로 working set처리 |
IMAGE_FILE_LARGE_ADDRESS_AWARE |
0x0020 |
어플리케이션이 2g이상의 주소를 제어 |
IMAGE_FILE_BYTES_REVERSED_LO |
0x0080 |
Bytes of machine word are reversed. |
IMAGE_FILE_32BIT_MACHINE |
0x0100 |
32비트 워드 머신 필요 |
IMAGE_FILE_DEBUG_STRIPPED |
0x0200 |
디버깅 정보가 .dbg파일에 존재 |
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP |
0x0400 |
이동장치에 존재시swap파일로 고정 디스크에 복사후 실행 |
IMAGE_FILE_NET_RUN_FROM_SWAP |
0x0800 |
네트워크에 존재시swap파일로 고정 디스크에 복사후 실행 |
IMAGE_FILE_SYSTEM |
0x1000 |
System File. |
IMAGE_FILE_DLL |
0x2000 |
File is a DLL. |
IMAGE_FILE_UP_SYSTEM_ONLY |
0x4000 |
하나의 processor 장착 기기에만 실행 |
IMAGE_FILE_BYTES_REVERSED_HI |
0x8000 |
Bytes of machine word are reversed. |
3) IMAGE_OPTIONAL_HEADER(224바이트)
- Magic : 32bit -> 10Bh or 64bit -> 20Bh
- SizeOfCode : 실행 코드가 포함된 섹션의 크기 (보통 .text)
- AddressOfEntryPoint : EP(Entry Point)의 RVA 주소값
- 실제 EP 주소 값 : AddressOfEntryPoint+ImageBase
- 이 값을 통해 패킹 여부를 알 수 있음
- ImageBase : PE파일이 맵핑 되는 시작 주소
- 메모리(가상주소공간) 내에 PE 파일이 로딩되는 시작주소
- EXE 기본 ImageBase: 0x00400000
- DLL 기본 ImageBase: 0x01000000
- 링크시 옵션 /BASE를 사용하여 변경 가능
- SectionAlignment : 메모리에서 섹션의 최소 저장 단위
- Memory Mapped File의성질에 의해 메모리페이지의 배수가 사용됨
- 섹션 크기는 최소 저장 단위의 배수가 되어야하며, 나머지는 NULL 값으로 채워짐
- FileAlignment : 파일에서 섹션의 최소 저장 단위
- 일반적으로 섹터크기(512바이트)
- 섹션 크기는 최소 저장 단위의 배수가 되어야하며, 나머지는 NULL 값으로 채워짐
- NULL padding : 4,5번의 최소단위를 맞추기 위해 section들이 끝나면 NULL값을 집어넣음
- SizeOfImage : PE구조의 크기(메모리)
- 반드시 SectionAlignment의 배수가 되어야함
- SizeOfHeader : PE header의 크기
- DOS Header, NT Header, Section Table을 모두 합한 크기
- 반드시 SectionAlignment의 배수가 되어야함
- Subsystem :
- 드라이브 파일 SYS,VXD
- GUI 파일
- CLI 파일
- NumberOfRvaAndSizes :
- 바로 밑의 구조체 배열 IMAGE_DATA_DIRECTORY 구조체 배열의 원소 개수
- 항상 16의 값을 가짐(0x00000010)
- 여기까지 96바이트
- IMAGE_DATA_DIRECTORY DataDirectory[16]
순서 |
이름 |
설명 |
0 |
EXPORT |
IMAGE_DIRECTORY_ENTRY_EXPORT 구조체를 가리킴 |
1 |
IMPORT |
IMAGE_IMPORT_DESCRIPTOR 구조체를 가리킴 |
2 |
RESOURCE |
IMAGE_RESOURCE_DIRECTORY 구조체를 가리킴 |
3 |
EXECPTION |
IMAGE_RUNTIME_FUNCTION_ENTRY 구조체를 가리킴(예외 핸들러 테이블) |
4 |
SECURITY |
WIN_CERTIFICATE 구조체를 가리킴, PE 파일 상에서 offset을 가리킴 |
5 |
BASERELOC |
ImageBase 필드에 지정된 가상 주소 공간에 위치시키지 못했을 때, 코드 상의 포인터 연산과 관련된 주소를 다시 갱신 |
6 |
DEBUG |
IMAGE_DEBUG_DIRECTORY 구조체 배열을 기리키며, 디버그 관련 정보가 있음 |
7 |
ARCHITECTURE |
IMAGE_ARCHITECTURE_HEADER 구조체를 가리킴 |
8 |
GLOBALPTR |
IMAGE_DATA_DIRECTORY 엔트리의 VirtualAddress 필드는 글로벌 포인터로 사용되는 RVA., IA-64 계열에서 사용됨, SIZE는 사용되지 않음 |
9 |
TLS |
스레드 지역 저장소 초기화 세션에 대한 포인터, _declspec(thread)라는 지시어를 통해 변수를 선언하면 TLS에 들어가게되며, 링커는 별도의 TLS 섹션을 만듬 |
10 |
LOAD_CONFIG |
IMAGE_LOAD_CONFIG_DIRECTORY 구조체에 대한 포인터 |
11 |
BOUND_IMPORT |
IMAGE_BOUND_IMPORT_DESCRIPTOR 구조체의 배열을 가리키는 포인터 DLL 바인딩과 관련된 정보를 담고 있음 |
12 |
IAT |
IAT의 시작번지를 가리킴 |
13 |
DELAY_IMPORT |
DELAYIMP.h 헤더에 정의되어 있는 ImgDelayDescr 구조체의 배열을 가리키는 지연 로딩 정보에 대한 포인터 |
14 |
COM_DESCRIPTOR |
.NET 프로그램이나 DLL용 PE를 위한 것 |
15 |
RESERVED |
예약된 영역 |
4. IMAGE_SECTION_HEADER (1개 섹션 크기당 40바이트)
섹션의 수는 Image File Header의 NumberOfSections필드에 명시됨
- Name : 섹션이름(단순참고정보,최대8 바이트)
- VirtualSize : 메모리에서 섹션 데이터의 실제바이트수
- VirtualAddress : 메모리에서 해당 섹션이 시작하는 주소(RVA)
- SizeOfRawData : 파일에서 섹션이 차지하는 크기
- PointerToRawData : 파일에서 섹션의 시작 위치(RVA)
- Characteristics : Section의 속성
- 아래 표 참고(이것보다 더 정의됨 winnt.h 참고)
정의 |
값 |
정보 |
IMAGE_SCN_CNT_CODE |
0x00000020 |
Section contains code. |
IMAGE_SCN_CNT_INITIALIZED_DATA |
0x00000040 |
Section contains initialized data. |
IMAGE_SCN_CNT_UNINITIALIZED_DATA |
0x00000080 |
Section contains uninitialized data. |
IMAGE_SCN_MEM_EXECUTE |
0x20000000 |
Section is executable. |
IMAGE_SCN_MEM_READ |
0x40000000 |
Section is readable. |
IMAGE_SCN_MEM_WRITE | 0x80000000 | Section is writeable. |
'리버싱 > 리버싱기초' 카테고리의 다른 글
DLL(Dynamic-link library) 동적 분석 방법 (2) | 2016.03.07 |
---|---|
리버싱 예제 2 (정적분석 vs 동적분석) (0) | 2015.10.14 |
PE파일 데이터 암호화 (0) | 2015.10.05 |
리버싱 예제 1 (라이센스 우회) (1) | 2015.09.15 |
리버싱 백그라운드(x86) (0) | 2015.09.15 |