kj0on

[Definition] VA & RVA & RAW 본문

Reversing/Definition

[Definition] VA & RVA & RAW

kj0on 2025. 7. 6. 17:46
목차 접기

0. 참고사항


이 글은 VA, RVA, RAW의 개념에 대한 설명이므로 스왑 메모리 방식이나 페이징 기법은 개념 설명과는 목적이 다르기 때문에 여기서는 다루지 않는다.


1. 디스크와 메모리

[이미지1] Disk

디스크는 비휘발성 저장장치로 전원이 꺼져도 데이터가 그대로 유지된다. HDD(하드디스크)나 SSD 같은 장치들이 여기에 해당하며 프로그램 파일이나 문서 등이 이곳에 저장된다.
 

[이미지2] Memory

반면 메모리는 휘발성 저장장치로 전원이 꺼지면 저장된 데이터가 모두 사라진다. RAM 같은 장치가 여기에 해당하며 실행 중인 프로그램이나 작업 데이터가 일시적으로 저장된다.
 

[이미지3] PE-bear

운영체제는 프로그램 실행 시 디스크에 있는 파일을 메모리로 불러와 실행한다. PE 파일은 디스크에 저장될 때와 메모리에 로드될 때 구조와 주소 체계가 달라진다. 디스크에서는 파일의 시작을 기준으로 한 바이트 단위 오프셋인 RAW Offset이 사용되며 이는 실제 데이터가 존재하는 물리적 위치를 나타낸다. 반면 실행 중에는 운영체제가 파일을 메모리에 매핑하면서 가상 주소(VA, Virtual Address)를 사용하고 이때 ImageBase를 기준으로 한 상대 주소인 RVA(Relative Virtual Address)가 함께 쓰인다.


2. Offset

[이미지4] Offset

오프셋은 기준 위치로부터 떨어진 상대적인 거리를 의미한다.


3. RAW (RAW Offset)

[이미지5] HxD

RAW는 PE 파일에서 데이터가 디스크에 저장된 실제 물리적 위치인 파일 내부의 오프셋(offset)을 의미한다. 이는 파일이 메모리에 로드되기 전 디스크 상에서 코드나 데이터가 존재하는 위치를 바이트 단위로 나타낸 것이다. RAW에서 오프셋의 기준은 항상 파일의 시작이다.

 

3-1. 절대주소가 아닌 오프셋인 이유


RAW는 기준이 0이기 때문에 절대주소처럼 보일 수 있지만 정확히는 파일 내 상대 오프셋(offset)에 해당한다. 그 이유는 RAW 값이 디스크 전체에서의 물리적 주소를 의미하지 않기 때문이다. 다르게 얘기하자면 디스크 전체에서 특정 파일에 대한 오프셋이라고 할 수 있다. 


4. VA (Virtual Address)

[이미지6] Process Hacker 2

VA는 실행 중인 프로그램이 자신의 메모리 공간에서 사용하는 주소를 의미한다. 이는 물리 메모리 주소가 아닌 운영체제가 제공하는 가상의 주소 공간으로 각 프로세스는 독립된 VA 공간을 가진다.

 

4-1. VA는 절대주소?


VA(Virtual Address)는 해당 프로세스 내에서 항상 동일한 위치를 가리키므로 프로세스 관점에서는 절대주소처럼 동작한다. 하지만 실제로 이 주소는 논리주소이기 때문에 실제 물리 메모리(RAM)의 주소를 의미하진 않는다. 따라서 VA는 프로세스 내부 기준으로는 절대주소고 시스템 전체 기준으로는 가상주소에 해당한다.


5. RVA (Relative Virtual Address)

[이미지7] RVA

RVA는 ImageBase를 기준으로 한 상대 가상 주소를 의미한다. 실행 파일이 메모리에 로드될 때 기준 주소(ImageBase) 로부터 얼마나 떨어진 위치인지를 바이트 단위로 나타낸 값이다.

 

5-1. IMAGE_SECTION_HEADER.VirtualAddress

[이미지8] VirtualAddress

IMAGE_SECTION_HEADER의 VirtualAddress와 프로세스 내부 기준 절대 주소 VA(Virtual Address)는 이름이 같아 혼동하기 쉽지만 전혀 다른 개념이다.
 

[이미지8] IMAGE_SECTION_HEADER.VirtualAddress (https://learn.microsoft.com/ko-kr/windows/win32/api/winnt/ns-winnt-image_section_header)

IMAGE_SECTION_HEADER.VirtualAddress는 실행 파일이 메모리에 로드될 때 ImageBase를 기준으로 얼마나 떨어져 있는지(RVA)의 오프셋을 의미한다. 반면 VA(VirtualAddress)는 ImageBase에 해당 RVA를 더해 계산한 실제 가상 주소다. 두 용어는 표기가 완전히 동일하지만 실제 의미는 전혀 다른 개념이다.
 

[이미지9] VA & RVA

.text 섹션을 살펴보면 IMAGE_SECTION_HEADER.VirtualAddress(RVA) 값이 0x1000이다. 이는 프로그램을 실행했을 때 해당 섹션이 ImageBase로 부터 0x1000만큼 떨어져있다는 의미다. 그렇기 때문에 메모리에서 .text섹션은 ImageBase + 0x1000에 위치하게 된다. 그 결과 VA는 0x401000이 된다. 결과적으로 .text섹션의 VA는 VA를 의미하지 않는다.
 

[이미지10] .text Section

실제 메모리에서 확인해 보면 0x401000에 .text 섹션이 위치한다는 것을 알 수 있다.


6. 관계식

VA(VitualAddress) = ImageBase + RVA(Relative Virtual Address)

 
RVA는 PE 파일 실행 시 메모리 상에서의 상대적 위치이며 그 기준점이 ImageBase이기 때문에 위 관계식이 성립한다. 여기서 VA는 프로세스 내부 기준 절대 주소다. IMAGE_SECTION_HEADER의 VirtualAddress(RVA)를 의미하지 않는다.


7. EntryPoint

[이미지11] CFF Explorer

위의 관계식을 이용하면 EP를 구하는 것 또한 가능하다. 예제 파일에서 ImageBase는 0x400000, 엔트리포인트의RVA(AddressOfEntryPoint)는 0x12AA다. 따라서 위 관계식에 따라 EntryPoint의 VA는 0x4012AA가 된다.
 

[이미지12] EntryPoint

실제 실행한 뒤 EntryPoint를 확인해 보면 계산한 결과와 정확히 일치한다는 것을 알 수 있다. ImageBase는 실행 파일이 메모리에 로드될 기본 주소지만 이 값은 선호값이지 절대적이지 않다. ASLR, 주소 충돌, 수동 맵핑, 특수 환경 등 여러가지 요인으로 인해 실제 로딩 주소는 달라질 수 있다. 따라서 ImageBase는 기준일 뿐 실제 메모리 주소와 항상 일치하지는 않는다.