학사 나부랭이
Reversing - Portable Executable - PE header - Section header 본문
Reversing - Portable Executable - PE header - Section header
태양왕 해킹 (14세) 2021. 6. 4. 23:58
PE header - Section header
섹션은 실제 파일의 내용이 존재하는 부분으로, 각 섹션의 속성을 정의한 것이에요.
PE 파일을 여러 섹션으로 나누었을 때 장점은, 프로그램의 안정성을 확보할 수 있다는 점인데요. 코드와 데이터가 하나의 섹션으로 되어있고, 섞여있다면, 구현이 가능하긴 하지만 복잡성은 둘째 치더라도 데이터에 값을 쓰다가 오버플로우로 인해 코드를 오염시켜 뻗어버리는 등 안정성에 문제가 생길 수 있어요. 그래서 각각 성격(특징, 액세스 권한)에 따라 나누게 되었죠.
1. 코드 - 실행, 읽기 권한
.text: 파일을 열었을 때, 실행될 코드 저장
2. 데이터 - 비실행, 읽기, 쓰기 권한
.data: 초기화된 전역 변수, static 변수 저장
.rdata: const 변수, 문자열 상수 저장
.bss: 초기화되지 않은 전역 변수, static 변수, 문자열, 기타 상수 저장, 초기화 시, data 영역으로 이동
.edata: EAT와 관련된 정보 저장
.idata: IAT와 관련된 정보 저장
3. 리소스 - 비실행, 읽기 권한
.rsrc: 리소스 저장
이렇게 PE 파일 포맷 설계자들은 비슷한 성격의 자료를 섹션이라 명명한 곳에 각각 모아두고 그 섹션의 성격을 섹션 헤더에 적어놓았어요.
Section header는 각 섹션 별로 IMAGE_SECTION_HEADER이라는 구조체의 배열로 이루어져 있어요.
이 구조체에서 잘 사용되지 않는 멤버를 제외한 주요 멤버는 아래와 같아요.
PE header - Section header - Name
섹션의 이름, 여기서 값은 ⓐ, ".text"이며, 코드를 저장하는 섹션이라고 알려주네요.
그런데 이름을 짓는데 명시적인 규칙이 없기에 ".purachina"나 심지어 NULL로 넣어도 돼요. 그리고 개발 도구에 따라 섹션의 이름/개수도 달라지고요. 그러니 섹션의 Name은 어디까지나 참고용이에요.
PE header - Section header - VirtualSize, SizeOfRawData
각각 메모리/파일에서 섹션이 차지하는 크기, 여기서는 ⓑ, ⓓ이며, 각각 071108h, 071200h이네요.
당연히 이전에 설명한 OptionalHeader의 SectionAlignment, FileAlignment의 배수이죠.
PE header - Section header - VirtualAddress, PointerToRawData
각각 메모리(RVA)/파일에서 섹션이 시작하는 위치, 여기서 ⓒ, ⓔ이며, ImageBase가 0이었으니 메모리에서 실제 주소는 VA와 동일하겠죠?
마찬가지로 OptionalHeader의 SectionAlignment, FileAlignment에 맞춰 결정되죠.
PE header - Section header - Characteristics
FileHeader의 Characteristics와 비슷한 기능(bit OR 조합)을 해요. 섹션이 읽기, 쓰기, 실행 가능한지, 초기화 된 섹션인지 등을 나타내죠. 여기서는 ⓕ, 60500060h 그러니까 40000000h(읽기 가능한) + 20000000h(실행 가능한) + 500000h(기본 정렬) + 40h(초기화된 데이터 포함) + 20h(코드 포함)이죠.
현재까지 프로그램 요약
이름 | 용도 | 현재 프로그램에서 값 |
DOS header | PE 구조 사용 여부 | 5A4Dh (MZ) |
DOS stub | DOS 시스템에서 실행할 때 동작 | WriteString() ("This program cannot...") Exit() |
NT header | ||
Machine | 프로그램이 동작될 CPU | 8664h (AMD64) |
NumberOfSections | 섹션의 수 | 0x11h (17개) |
TimeDataStamp | 만들어진 시간 | 약 2021/02/14 |
PointerToSymbolTable, NumberOfSymbols |
COFF 심벌 테이블이 있을 때, 이를 향한 포인터 해당 테이블에 있는 심벌의 개수 |
|
SizeOfOptionalHeader | OptionalHeader의 크기 | 0xF0h (240바이트) |
Characteristics | 파일의 속성 | 0x27 (64비트 실행파일) |
OptionalHeader | ||
Magic | OptionalHeader의 종류 | 020Bh (64비트) |
SizeOfCode | 코드 섹션의 크기 | 0x071200h |
AddressOfEntryPoint | 처음 실행되는 코드의 주소 | 0x1500h + ImageBase |
BaseOfCode | 코드 섹션의 주소 | 0x1000h + ImageBase |
ImageBase | RVA의 기준점 | 0 |
SectionAlignment, FileAlignment |
섹션의 메모리/파일에서 단위 | 0x1000h 0x2000h |
SizeOfImage | 메모리에 매핑되었을 때 크기 | 0x100000h |
SizeOfHeader | 파일에서 PE 헤더의 총 크기 | 0x0600h |
SubSystem | 파일의 종류 | 0x03h (CLI) |
NumberOfRvaAndSizes | DataDirectory 배열의 개수 | 0x10h (16개) |
DataDirectory | IMAGE_DATA_DIRECTORY 구조체의 배열 | |
SectionHeader(e.g. .text section header) | ||
Name | 섹션의 종류 | 0x747865742E (.text) |
VirtualSize, SizeOfRawData |
섹션의 메모리/파일에서 크기 | 071108h + ImageBase 071200h |
VirtualAddress PointerToRawData |
섹션의 메모리/파일에서 시작 위치 | 0x1000h + ImageBase 0x0600h |
Characteristics | 섹션의 속성 | 0500060h (읽기, 실행 가능, 기본 정렬, 초기화된 데이터, 코드 포함) |
RVA to RAW
PE 파일이 메모리를 할당받을 때, 각 섹션에 있는 메모리의 주소(RVA)와 파일 오프셋을 잘 매핑할 수 있어야 해요. 이런 매핑 방식을 RVA to RAW라고 하는데, 방법은 아래와 같아요.
1. RVA가 속해 있는 섹션을 찾아요.
2. 간단한 비례식을 사용해 파일 오프셋(RAW)을 계산해요.
IMAGE_SECTION_HEADER 구조체에 의하면 비례식은 다음과 같아요.
RAW - PointerToRawData = RVA - VirtualAddress
RAW = RVA - VirtualAddress + PointerToRawData
'Dot-Gabi > Reversing' 카테고리의 다른 글
The basic of Assembly language & Debugger (0) | 2021.07.08 |
---|---|
Reversing - Portable Executable - PE header - NT header (0) | 2021.06.01 |
Reversing - Portable Executable - PE header - DOS header, stub (0) | 2021.06.01 |
Reversing - Portable Executable - Opening (0) | 2021.06.01 |
Reversing - Register, Stack Frame (0) | 2021.05.30 |