용어 설명
리버싱에서의 주소계산은 "파일"과 "메모리" 관점에서 이루어집니다. 파일 안에서 절대주소는 OFFSET이라고 합니다. 메모리 안에서의 절대주소는 VA라고 합니다. 또한, 파일이나 메모리에는 여러 종류의 공간이 존재합니다. 예를 들어 Header 같은 공간이나 Section 같은 공간들이 존재합니다. 이런 공간들은 용도에 따라 나뉘어져 있으며, 공간의 시작점은 파일에서는 "PointerToRawData" (OFFSET값), 메모리에서는 "VirtualAddress" (VA값)이라고 합니다. 또한, 공간 내 특정 주소를 지칭하는 용어도 있습니다. 파일에서는 "RAW" (OFFSET값), 메모리에서는 "RVA" (VA값)이라고 합니다. (이를 변환하는 것은 밑에서 다룹니다.) 정리하자면, 파일이나 메모리의 주소를 지칭하는 용어는 총 3가지가 있습니다. ""절대 주소에 대한 용어, 각 공간의 시작주소, 각 공간의 특정주소""로 나뉘게 됩니다. 혹시 이해가 잘 가지 않는다면, 하단의 정리된 내용과 사진을 보시기 바랍니다.
- 주소의 종류
- Offset: 파일에서의 절대 주소
- VA: 프로세스가 가상메모리에 로딩되었을 때의 절대주소
- 세션의 시작 주소
- PointerToRawData: 파일에서 공간의 시작위치 (Offset 값)
- VirtualAddress: 메모리에서 공간의 시작 위치 (VA값)
- 세션 내 특정 주소
- RAW: 파일에서 특정한 위치의 주소 (Offset 값)
- RVA: 메모리에서 특정한 위치의 장소 (VA 값)
- (참고: VA = RVA + ImageBase)
RAW/RVA 구하기
이 섹션에서는 RAW/RVA 구하는 방법에 대해 알아보겠습니다.
RAW 구하기
위에서 파일에서의 주소는 OFFSET이라고 했습니다. 그리고 특정 위치의 주소는 RAW라고 했습니다. 그럼 RAW는 어떻게 구할까요? RAW는 RVA에서 VirtualAddress를 뺀 값에 PointerToRawData를 더한 값입니다. 언뜻봐선 이해가 잘 안가실 겁니다. 저도 그랬으니깐요. 차근차근 설명드리겠습니다. 우선 RVA - VirtualAddress의 의미에 대해 생각을 해보겠습니다. RVA는 메모리에서의 특정 지점의 주소이고, VirtualAddress는 메모리에서의 특정 공간의 시작위치 입니다. 즉, 변위값을 메모리를 통해 얻어오는 것이 되겠습니다. 그리고 PointerToRawData를 더하는데, 메모리의 주소를 파일의 주소로 변환하는 과정이라고 생각하시면 되겠습니다. 어떠신가요? 이해가 되시나요? 혹시 이해가 안되신다면, 하단의 정리된 내용을 봐주시기 바랍니다.
- RAW = RVA - VitualAddress + PointerToRawData
RVA 구하기
위에서 메모리에서의 주소는 VA라고 했습니다. 그리고 특정 위치의 주소는 RVA라고 했습니다. 그럼 RVA는 어떻게 구할까요? 위의 내용을 이해하셨다면, 이 내용은 이해하기 쉬우실 겁니다. 위에서는 메모리를 대상으로 변위를 구했다면, 여기서는 파일을 대상으로 변위를 구하는 겁니다. 그래도 이해가 안 가시는 분이 계실 것 같아 자세히 설명하겠습니다. 우선, RAW - PointerToRawData의 의미에 대해 생각을 해봐야겠습니다. RAW는 파일에서의 특정 지점을 의미합니다. 그리고 PointerToRawData는 파일에서의 특정 공간의 시작 위치 입니다. 즉, 변위값을 파일을 통해 얻어오는 것이 되겠습니다. 그리고 VitualAddress를 더하는데, 파일의 주소(변위값)를 메모리의 주소로 변환하는 과정이라고 생각하시면 됩니다. 혹시 이해가 안되신다면, 하단에 정리되어 있는 내용을 봐 주시기 바랍니다.
- RVA = RAW - PointerToRawData + VitualAddress
결론
위와 같이 식을 세울 수 있는 이유는, 메모리나 파일로 주소 변환(로딩)을 하면서 공간의 전체적인 크기는 변하지 않기 때문입니다. "100-10"과 "10000-9910"은 모두 90으로 값이 같은 것과 같은 원리입니다. 다만, 파일이나 메모리는 주소체계가 다르기 때문에, 시작지점인 PointerToRawData나 VitualAddress를 더하게 되는 것입니다.
여기서 알 수 있는 것은, "RAW - PointerToRawData = RVA - VitualAddress"이 성립한다는 겁니다. 같은 공간안에 두 개의 지점(시작점, 특정지점)이 있을 때, 서로 뺀 값(변위)는 동일하다는 반증이 됩니다.
- RAW - PointerToRawData = RVA - VitualAddress
- RAW: 파일에서의 주소 / RVA: 메모리에서의 주소
(특정 지점에서 섹션의 시작 지점을 뺀 값은 동일함)
RVA에서 RAW로 변환하기
지금까지 메모리의 주소체계와 RAW나 RVA를 구하는 방법에 대해 알아봤습니다. 이를 기반으로 RVA에서 RAW로 변환할 수 있습니다. 자세한 내용은 하단에 정리된 내용을 참고해주시기 바랍니다.
- STEP 0. RVA가 위치한 섹션 찾기
- : RVA가 3000이므로, 1001000과 1054000 사이에 있는 .text 섹션에 위치함을 알 수 있다.
- STEP 1. VirtualAddress 구하기
- : VirtualAddress = 1001000 (섹션 시작주소; VA값) - 1000000 (ImageBase) = 1000
- STEP 2. PointerToRaw 구하기
- : PointerToRaw = 400 (.text 섹션의 시작 Offset 주소값)
- STEP 3. RAW 값 구하기
- : RAW = 3000 - 1000 + 400 = 2400
'정보보호 > 리버스엔지니어링' 카테고리의 다른 글
[리버싱] Ollydbg 단축어와 여러 가지 팁 정리 (1) | 2024.01.06 |
---|---|
[PWN] pwnable.kr collision 문제풀이 (0) | 2024.01.06 |
[PWN] pwnable.kr fd 문제풀이 (0) | 2024.01.06 |
[F-Security] Level1. 문제 풀이 (0) | 2021.05.09 |
STOS / STOSB / STOSW / STOSD 이야기 (0) | 2019.02.10 |