Abstract
Windows는 보안을 위해 ASLR 기능을 지원한다. 물론 이외에도 DLL의 재배치 기능을 위해서 실행 파일을 가상 메모리 내 임의의 위치에 로드될 필요가 있다. .reloc 섹션은 이러한 재배치 기능을 위해 만들어진 섹션으로, OptionalHeader에 명시된 ImageBase가 아닌 다른 ImageBase에 PE 실행 파일이 로드될 때 참조 주소 값들을 새 ImageBase를 기준으로 다시 계산해 적용하기 위해 존재한다.
.reloc Section
.reloc
.reloc 섹션은 PE 파일이 메모리에 로드될 때 Optional 헤더의 ImageBase 값이 아닌 다른 위치에 로드될 경우 문자열 주소나 IAT 영역 위치 등의 주소를 재배치된 ImageBase에 맞게 고치기 위한 섹션이다. EXE 파일의 경우 자신만의 공간을 할당받기 때문에 ASLR을 사용하도록 빌드한 경우가 아니면 .reloc 섹션은 만들어지지 않는다. DLL의 경우 다른 프로세스도 사용할 수 있기 때문에 공용 공간에 DLL이 로드되므로 자신의 ImageBase가 아닌 다른 ImageBase를 할당받을 수도 있다. 이처럼 ImageBase 값이 변할 경우 이를 대처하기 위한 섹션이 .reloc 섹션이다.
Visual Studio에서는 프로젝트 속성에서 ASLR 옵션을 활성/비활성화 할 수 있다. 프로젝트 속성 중 링커 메뉴에서 임의 기준 주소 옵션을 활성화하면 된다. 기본 값은 활성이다.
ASLR을 활성화하고 빌드하면 .reloc 섹션이 생성된다.
IMAGE_BASE_RELOCATION
재배치를 고려해 빌드하게 되면 Optional 헤더의 Relocation Directory(DataDirectory[5])에 재배치와 관련된 데이터가 저장된 영역을 가리키는 값이 저장된다.
Relocation Directory가 가리키는 곳에는 IMAGE_BASE_RELOCATION 구조체 배열이 존재한다.
typedef struct _IMAGE_BASE_RELOCATION {
DWORD VirtualAddress;
DWORD SizeOfBlock;
// WORD TypeOffset[1];
} IMAGE_BASE_RELOCATION;
typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION;
- VirtualAddress: 재배치가 이루어질 기준 위치(RVA)
- SizeOfBlock: IMAGE_BASE_RELOCATION 구조체를 포함한 재배치 항목 데이터들의 전체 크기
IMAGE_BASE_RELOCATION 구조체는 재배치가 이루어져야 할 기준 위치와 재배치할 항목들을 포함한 전체 크기를 나타낸다. 아래 그림은 .reloc 섹션에서 나타난 첫번째 IMAGE_BASE_RELOCATION 구조체(붉은 박스)와 재배치가 이루어질 항목들(파란 박스)들을 나타내고 있다. 붉은 박스와 파란 박스를 합친 크기가 SizeOfBlock이 나타내고 있는 13Ch 바이트다.
- VirtualAddress: 1000h
- SizeOfBlock: 13Ch
IMAGE_BASE_RELOCATION 구조체가 나타나고 바로 뒤엔 2바이트 크기의 데이터 배열이 나타난다. 이들은 TypeOffset으로써, 2바이트는 아래와 같이 구성된다.
앞의 4비트는 재배치 타입을 의미한다. 종류는 winnt.h에 정의되어 있으며, 일반적으로 32비트 프로그램에선 3, 64비트 프로그램에선 10을 갖는다.
//
// Based relocation types.
//
#define IMAGE_REL_BASED_ABSOLUTE 0
#define IMAGE_REL_BASED_HIGH 1
#define IMAGE_REL_BASED_LOW 2
#define IMAGE_REL_BASED_HIGHLOW 3
#define IMAGE_REL_BASED_HIGHADJ 4
#define IMAGE_REL_BASED_MACHINE_SPECIFIC_5 5
#define IMAGE_REL_BASED_RESERVED 6
#define IMAGE_REL_BASED_MACHINE_SPECIFIC_7 7
#define IMAGE_REL_BASED_MACHINE_SPECIFIC_8 8
#define IMAGE_REL_BASED_MACHINE_SPECIFIC_9 9
#define IMAGE_REL_BASED_DIR64 10
뒤 12비트는 재배치할 오프셋이다. 최종적으로 계산되는 재배치 대상 오프셋은 아래와 같다.
- IMAGE_BASE_RELOCATION.VirtualAddress + TypeOffset.Offset
재배치 과정
첫번째 IMAGE_BASE_RELOCATION 바로 뒤에 나타난 첫번째 TypeOffset을 해석해보면 아래와 같다.
- IMAGE_BASE_RELOCATION.VirtualAddress(1000h) + TypeOffset.Offset(4) = 1004h
최종적으로 계산된 재배치 대상 오프셋 1004h를 Raw 주소로 변환하면 404h가 된다. PE 파일에서 404h로 가보면 4033A8h라는 주소값이 보인다. 이는 PE 파일의 Optional 헤더에 정의된 ImageBase를 기반으로 만들어진 절대 주소다. .reloc 섹션은 이렇게 절대 주소로 참조하는 파라메터들을 재배치된 ImageBase를 기반으로 다시 계산해 바꿔주는 데 사용하는 섹션인 셈이다.
메모리에 로드되고 나면 4033A8h로 되어있던 값이 새로 지정된 ImageBase 값에 따라 변한 것을 볼 수 있다. 새로운 ImageBase는 DE0000h이다. mov 명령에 의해 eax에 넘겨지는 값이 4033A8h에서 기존 ImageBase인 400000h을 빼고 새 ImageBase인 DE0000h을 더해 DE33A8h이 됐다.
'Malware Analysis > PE' 카테고리의 다른 글
#7 PE - Rich 헤더 (0) | 2021.08.01 |
---|---|
#5 PE - IAT (0) | 2021.08.01 |
#4 PE - Section Header (0) | 2021.08.01 |
#3 PE - Optional Header (1) | 2021.08.01 |
#2 PE - File Header (0) | 2021.08.01 |