윈도우 실행파일 포맷인 PE(Portable Executable)의 기본적인 구조 이해
● 기본 개념
- 실행파인은 재배치 될 수 있음(로드될 때마다 다른 가상 메모리 주소에 로드될 수 있음)
- OS는 각 프로세서마다 고유한 주소 공간을 제공하지만 주소 공간에는 여러 개의 실행 바이너리들이 로드됨
- 프로그램은 자신의 주소 공간에 실행파일뿐만 아니라 DLL과 같은 추가적인 실행 모듈들을 로드함
- 기존에 사용하고 있는 주소에 다른 프로그램이 해당 주소를 사용하려고 하는 경우 다른 주소에 로딩해야 되는데 이때 재배치 작업을 수행함
MOV EAX, DWORD PTR [pGlobalVariable] |
위 코드는 전역변수에 접근하는 전형적인 코드 컴파일러와 링커가 pGlobalVariable에 대한 주소로 어떤 값을 사용해야 하는가? →일반적으로 파일의 시작 지점으로부터의 상대주소를 생각할 수 있다. 이 주소를 사용할 경우 어느 주소로 로드되는지 걱정할 필요가 없다. 그러나… 위의 코드는 프로세서가 직접 실행하는 코드이다. 따라서 로더는 코드상의 모든 주소를 정확한 위치를 가리키는 절대주소로 변환한다. |
# 재배치가 중요한 이유
- 실행모듈헤더에서는 절대주소가 사용되지 않고 코드에서만 절대주소가 사용되기 때문
- 실행 모듈 헤더에서는 항상 상대가상주소(RVA, Relative Virtual Address : 단순 offset값)를 상요함
- 실행 모듈이 로드되고 가상주소를 할당받을 때 로더는 실제 가상주소를 계산함
(모듈의 Based Address + RVA = 실제 가상주소)
● 이미지 섹션
- 실행이미지는 여러가지 섹션으로 나누어 짐
- 코드(text)섹션 : 실행모듈의 코드 포함
- 데이터섹션 : 데이터 포함
- 실행 모듈 로딩 시 메모리 관리자는 섹션 헤더의 설정 내용에 따라 각 섹션에 해당하는 메모리 페이지에 대한 접근 권한 설정함
Char szMessage[] = “Welcome to my program!”; |
위의 코드에서 컴파일러는 실행 이미지의 어딘가에 정의된 문자열을 저장해야 함 위의 문자열은 초기화된 데이터이며 따라서 해당 문자열과 그것을 가리키는 변수는 초기화된 데이터 섹션에 저당됨 |
● 섹션 정렬
- 메모리에 로드되는 섹션의 크기는 일반적으로 페이지 크기의 배수
- 반대로 실행 이미지를 페이지 크기 단뒤로 디스크에 저장하면 실제 필요한 용량보다 훨씬 큰 용량을 차지함(디스크 낭비)
→ 위의 이유로 인해 PE헤더는 섹션정렬을 위한 두개의 필드가 존재함
섹션정렬 필드 : 실행 이미지를 메모리에 로드할 때 사용
파일정렬 필드 : 파일을 디스크에 저장할 때 사용
● 동적 링크 라이브러리(DLL)
- 동적 링크 라이브러리의 개념
프로그램은 하나 이상의 실행 파일로 분리될 수 있고, 각 실행 파일은 프로그램 기능의 일부분이나 일부 기능을 수행하는 것
장점 : 필요한 기능을 제공하는 실행 모듈만 로드해서 사용함(메모리 낭비를 줄임)
프로그램의 기능 변경시 해당 모듈만 변경하거나 추가하면 됨
● 정적 라이브러리(.lib)
- 실행 모듈에 영구히 링크됨
- 프로그램이 빌드될 때 .lib파일안의 코드를 원래 소스코드의 일부분인 것처럼 실행 모듈에 정적으로 링크시킴
- 실행 모듈이 로드될 때 OS는 로드된 실행 모듈안에 정적라이브러리가 있다는 것을 알지 못함. 이는 같은 정정적라이브러리가 포함된 A, B프로그램이 있다면 정정라이브러리가 중복되서 로드될 것임(메모리 낭비가 발생할 수 있음)
● 윈도우 프로그램 실행 시 DLL로드 방법
(1) 정적링크
- 실행 이미지의 임포트 테이블 안에 다른 실행모듈에 대한 정보를 포함시키는 과정
- 실행 이미지가 사용하는 모듈들도 같이 로드함
- 해당 모듈들에 대한 모든 외부 레퍼런스 정보를 올바르게 맞춤
(2) 동적링크
- 실행 이미지가 런타임 시에 다른 실행 모듈에 대한 로드여부를 판단함
- 런타임 시에 모듈을 직접 로드하고 로드한 모듈 이미지의 헤더를 검색해서 호출하고자 하는 함수를 찾아야만 함
# 리버싱 관점에서 볼 때 정적 링크 방법은 어떤 모듈의 어떤 함수를 사용하는지 전부 할 수 있으므로 좀더 다루기 쉽다
● 헤더(Header)
- PE파일은 DOS헤더로 시작함
- 하위 호환을 위한 부분으로 DOS시스템에서 PE파일이 실행될 때 에러처리를 하기 위함
(ex: “This program connot be run in DOS mode”라는 메시지가 나타나는 경우가 있는데, DOS상에서 PE실행 이미지를 실행 시킬 수 없다는 의미 → 이 메시지를 출력하기 위해서 PE실행 이미지에는 작은 16bit DOS 프로그램을 포함)
- 헤더 안의 모든 포인터는 절대주소가 아닌 RAV값임
- 유용한 정보들은 PE헤더 안의 추가적인 데이터 구조체 배열인 DataDirectory 구조체 안에 포함됨
(1) DOS 헤더
- e_lfanew : 실제 PE 헤더를 가리키는 포인터
(2) PE헤더
- DOS헤더가 확장된 것임
● 임포트와 익스포트
- 실행 이미지의 동적링크를 가능하게 해주는 메커니즘
- 컴파일러와 링커는 임포트하는 함수의 실제 주소를 알지 못함 → 실행 시에만 알 수 있음
(임포트 테이블 : 실행 이미지가 사용하는 각 모듈목록과 그 모듈에서 사용하는 함수 목록의 정보가 저장되어 있음)
- 모듈이 모드될 때 로더는 임포트 테이블에 명시된 모든 모듈을 로드 함
- 로드한 각 모듈의 함수 목록에 있는 함수들의 주소를 산출
- 함수 주소는 임포트한 모듈의 익스포트 테이블을 통해 산출
(익스포트 테이블 : 해당 모듈이 익스포트하는 모든 함수의 이름과 RVA를 가지고 있음)
● 디렉토리
- 데이터 구조체
이름 |
설명 |
관련 구조체 |
export table |
모듈의 모든 익스포트 함수 이름과 RVA를 포함 |
IMAGE_EXPORT_DIRECTORY |
import table |
·임포트하는 모듈과 함수 이름을 포함함 ·함수별로 함수 이름 문자열(또는 서수)과 함수의 임포트 어드레스 테이블 엔트리를 가리키는 RVA를 포함 ·모듈이 로드될 때 임포트한 함수의 실제 주소를 전달받는 시작점이 됨 |
IMAGE_IMPORT_DESCRIPTOR |
resource table |
·실행 모듈의 리소스 디렉토리 포인터 ·리소스 디렉토리는 문자열, 대화상자 레이아웃, 메뉴와 같은 다양한 사용자 인터페이스 요소와 정적인 요소를 정의함 |
IMAGE_RESOURCE_DIRECTORY |
Base Relocation table |
모듈이 빌드되면서 설정된 로드 주소가 아닌 다른 주소로 로드되어야 할 때 재배치되어야 하는 주소들의 목록 |
IMAGE_BASE_RELOCATION |
Debugging Information |
·실행 모듈을 위한 디버깅 정보 ·일반적으로 실질적인 디버깅 정보를 담고 있는 외부 심볼 파일에 대한 링크 정보를 제공함 |
IMAGE_DEBUG_DIRECTORY |
Thread Local Storage table |
·쓰레드 로컬 변수를 포함할 수 있는 실행 모듈의 쓰레드 로컬 섹션에 대한 포인터 ·이 기능은 로더가 실행 모듈을 로드할 때 사용함 |
IMAGE_TLS_DIRECTORY |
Load Configuration table |
·LOCK prefix테이블(단일 프로세서 시스템이나 멀티 프로세스 시스템에 맞게 실행 모듈이 로드될 때 실행 모듈 이미지를 변경 가능)과 같은 다양한 이미지 설정 요소를 포함 ·모듈의 예외 핸들러 목록 포함(악의적인 코드가 예외 핸들러를 설치하는 것을 방지하기 위함) |
IMAGE_LOAD_CONFIG_DIRECTORY |
Bound Import table |
·바운드 임포트 엔트리 정보를 담고 있는 추가적인 임포트 테이블 ·임포트한 실행 모듈의 실제 주소가 포함되어 있다는 것을 의미함(그 주소가 여전이 유효한지 확인하기 위함) |
IMAGE_BOUND_IMPORT_DESCIPTOR |
Import Address table(IAT) |
·임포트된 각 함수의 목록을 포함 ·실행 모듈이 로드될 때 각 임포트 함수의 엔트리가 해당 함수에 대한 실제 주소로 초기화 됨 |
32bit 포인터 목록 |
Delay Import Descriptor |
·임포트한 함수를 처음 호출할 때 해당 함수의 실제 주소가 매핑되는 지연 임포트 로딩 메커니즘을 구현하기 위해 사용됨 ·이 메커니즘은 OS가 제공하는 것이 아니라 C런타임 라이브러리에 의해서 구현됨 |
ImgDelayDescr |
'Security > Reverse Engineering' 카테고리의 다른 글
[Reversing]구조화된 예외 처리(SEH) (0) | 2010.05.10 |
---|---|
[Reversing]Input and Output (0) | 2010.05.10 |
[Reversing]API (0) | 2010.05.04 |
[Reversing]프로세스 동기화, 초기화 과정 (0) | 2010.05.04 |
[Reversing]프로세스와 쓰레드 (0) | 2010.05.04 |