PE relocation
PE 파일은 프로세스 가상 메모리에 로딩되어질 때 PE 헤더의 'ImageBase'에 로딩되어짐.
그런데 ImageBase에 이미 다른 파일이 배치되어있을 경우에는 같은 주소 공간에 두개의 다른 파일을 로딩할 수는 없음.
따라서 PE 재배치를 통해 다른 주소에 로딩되게 함.
- 이전 EXE의 경우 가장 먼저 메모리에 올라갔기 때문에 재배치 고려를 하지 않았지만 현재쓰고있는 윈도우 버전의 경우엔 'ASLR' 기능이 추가되어서 EXE가 실행 되어질 때마다 랜덤한 주소에 로딩되어짐.
* 실제 재배치 작업 동작 원리
#1. 프로그램의 하드코딩된 주소를 써치
Base reloaction table을 통해서 찾는다. RVA가 1420일경웨 PE View를 통해 해당 주소의 내용을 확인한다.
1420의 하드코딩된 주소 08C28309 값이 들어있다.
#2. 값을 읽은 후 ImageBase만큼 뺀다(VA -> RVA)
08C28309 - 0100000 = 07C28309
#3. 실제 로딩 주소를 더한다.(RVA -> VA)
07C28309 + 00AF0000 (실제 로딩된 주소) = 08718309
PE 로더는 하드코딩된 주소 08C28309를 위와 같은 과정을 거쳐 보정된 값(08718309)을 같은 위치에 덮어씀!
이 과정을 하나의 Image_Base_reloaction 구조체의 모든 옵셋에 반복해서 적용하면 RVA 1000~2000 주소 영역에 해당하는 모든 하드코딩 주소에 대해서 PE 재배치 작업이 수행되어지게 되는것임!
.reloc 섹션
exe 파일에서 base_relocation_table은 필수적이지 않음. 그러나 dll,sys는 거의 필수적임.
.reloc는 VC++에서 생성한 PE의 맨 마지막에 위치한다고 함.
reloc.exe의 .reloc 섹션을 제거하기 위해서 다음의 4가지 단계를 거쳐야 함.
1. .reloc 섹션 헤더 정리
2. .reloc 섹션 제거
3. Image_file_header 수정
4. Image_optional_header 수정
가즈아!
#1. .reloc 섹션 헤더 정리
.reloc은 offset 270에서 시작함. 해당 부분을 0으로 덮어씁니다.
#2. reloc 섹션 제거
위 그림을 살펴보면 reloc 섹션의 시작 옵셋은 C000 입니다. 이 부분부터 파일의 끝까지 삭제합니다.
#3. Image_file_header 수정
섹션을 하나 삭제 했기 때문에 헤더에 섹션 개수를 나타내주는 Number_of_sections 항목을 수정합니다.
#4. Image_optional_header 수정
섹션을 삭제해 그 크기만큼 이미지 크기가 줄어들었으므로 이미지 크기도 조절해줘야함.
현재 size_of_image값 11000에서 얼마만큼 빼야하냐면 삭제한 섹션(.reloc)의 Virtual Size는 E40이였음 이걸
Section Alignment에 맞게 확장하면 1000임 따라서 1000을 빼줘야함.
다음으로는 자신의 섹션을 추가해보는 연습을 해볼 것.
의문점 ? Size of Raw Data랑 Virtual Size의 값이 다른거는 알겠다. 실제 옵셋이랑 메모리에 로딩되었을 때랑 일반적으로 다르다고 하니까. 그런데 vitual size값은 어떻게 결정되는거지
위에사진에 디스크에서 200의 size인데 메모리에 올라간 경우 1B4라는 값을 가지는데 어떻게 계산되는지 모르겠당