리버싱 엔지니어링/리버싱 핵심 원리
16 Base Relocation Table
흰싸라기
2022. 3. 27. 02:36
Base Relocation Table : PE 파일의 재배치(Relocation) 과정에 사용됨
PE 재배치
- PE 파일(EXE/DLL/SYS)이 프로세스 가상 메모리에 로딩될 때 PE 헤더의 ImageBase 주소에 로딩
- PE 파일 재배치
- DLL(SYS) 파일의 경우 ImageBase 위치에 이미 다른 DLL(SYS) 파일이 로딩되어 있다면 다른 비어 있는 주소 공간에 로딩
- ImageBase에 로딩되지 못하고 다른 주소에 로딩될 때 수행되는 일련의 작업들
DLL/SYS
- TEST.exe 프로세스에 A.DLL이 10000000 주소에 로딩
- B.DLL이 같은 주소 10000000에 로딩 시도 -> 비어 있는 주소(3C000000)에 로딩시킴
EXE
- 프로세스가 생성될 때 EXE 파일이 가장 먼저 메모리에 로딩되기 때문에 EXE는 재배치를 고려할 필요 없음
- 그러나, 보안 강화를 위해 ASLR 기능이 추가됨
- ASLR(Address Space Layout Randomization) : EXE 파일이 실행될 때마다 랜덤한 주소에 로딩
- 더 자세한 내용은 41장 참고
- DLL도 ASLR기능으로 인해 매 부팅 시마다 ImageBase가 달라짐
PE 재배치 발생시 수행되는 작업
: notepad.exe 프로그램을 통해 PE 재배치 확인
1) PEview를 통한 ImageBase 값 확인
- notepad.exe의 ImageBase는 01000000
2) OllyDbg를 통해 notepad.exe EP코드 살펴보기
- 재실행[Ctrl+F2]할 때마다 위 그림에 표시된 주소 값이 로딩 주소에 맞게 매번 결정됨
- 로딩주소 : 00130000
- GetStartupInfo : STARTUPINFO 구조체를 반환
- STARTUPINFO 구조체 : 프로세스 속성 지정
PE 재배치 동작 원리
- 기본 동작 원리
- 프로그램에서 하드코딩된 주소 위치를 찾는다.
- 값을 읽은 후 ImageBase만큼 뺀다(VA -> RVA)
- 실제 로딩 주소를 더한다(RVA -> VA)
- 이를 위해, PE 파일 내부에 Relocation Table이 존재
- Relocation Table : 하드코딩 주소들의 옵셋(위치)을 모아 놓은 목록
- 찾는 방법 : PE 헤더의 Base Relocation Table 항목을 따라감.
Base Relocation Table
- Base Relocation Table 주소 : PE 헤더의 DataDirectory 배열의 여섯번째 항목(Index 5)
- PEView에서 notepad.exe의 Base Relocation Table 주소 확인
- 주소 = RVA 2F000
- 하드코딩 주소들의 옵셋(위치)들이 나열되어있음.
IMAGE_BASE_RELOCATION 구조체
- 구조체 멤버
- VirtualAddress : 기준 주소(Base Address), RVA 값
- SizeOfBlock : 각 단위 블록의 크기
- (주석)TypeOffset : 해당 구조체 밑으로 WORD 타입의 배열이 따라온다는 의미. 이 배열이 하드코딩된 주소들의 옵셋
Base Relocation Table의 해석 방법
RVA | Data | Comment |
0002F000 | 00001000 | VirtualAddress |
0002F004 | 00000150 | SizeOfBlock |
0002F008 | 3420 | TypeOffset |
0002F00A | 342D | TypeOffset |
0002F00C | 3436 | TypeOffset |
… | … | … |
- VirtualAddress 값 : 1000, SizeOfBlock : 150
- 따라서, TypeOffset 배열의 기준(시작) 주소는 RVA 1000, 블록의 전체 크기는 150
- TypeOffset 크기는 2바이트(16비트), Type(4비트)와 Offset(12비트)가 합쳐진 형태
- ex) TypeOffset 값 : 3420, Type : 3, Offset : 420
- Type 일반 값은 3, 64비트에서는
- 하위 12비트가 진짜 Offset
- VirtualAddress(1000) + Offset(420) = 1420(RVA)
실습
: Notepad.exe
#1 프로그램에서 하드코딩된 주소 위치를 찾는다.
- 하드코딩 주소의 옵셋(위치) : 위에서 구한 RVA 1420
- PEView
- 하드코딩된 주소 010010C4
#2 값을 읽은 후 ImageBase만큼 뺀다(VA -> RVA)
010010C4 - 01000000 = 000010C4
#3 실제 로딩 주소를 더한다.
로딩 주소를 00AF0000으로 가정,
000010C4 + 00AF0000 = 00AF10C4
- PE 로더는 보정된 값(00AF10C4)에 덮어쓴다.
- 이 과정을 모든 TypeOffset에 대해 반복하면 PE 재배치 작업이 수행된 것