1. IAT(Import Address Table)

 

→ 프로그램이 어떤 라이브러리에서 어떤 함수를 사용하고 있는지 기술한 테이블

 

▶ DLL (Dynamic Linked Library)

 

→ '동적 연결 라이브러리'

→ 32bit Windows 환경을 제대로 지원하기 위해서는 기본적으로 매우 많은 라이브러리 함수를 사용해야 한다.

→ 여러 프로그램이 동시에 실행되어야 하는 상황에서 모든 프로그램마다 위와 같이 동일한 라이브러리가 포함되어 실행된다면 심각한 메모리 낭비를 불러오게 된다.

 

▷ DLL 로딩 방식

 

1) Explicit Linking

: 프로그램 내에서 사용되는 순간에 로딩하고, 사용이 끝나면 메모리에서 해제시키는 방법

2) Implicit Linking

: 프로그램을 시작할 때 같이 로딩되어 프로그램을 종료할 때 메모리에서 해제되는 방법

 

★ IAT는 Implicit Linking에 대한 메커니즘을 제공하는 역할을 한다.

 

▷ DLL 장점

 

- 프로그램 내에 라이브러리를 포함시키지 않고 별도의 파일로 구성하여 필요할 때마다 불러 사용할 수 있다.

- 일단 한 번 로딩된 DLL의 코드와 리소스는 Memory Mapping 기술로 여러 프로세스에서 공유하여 사용할 수 있다.

- 라이브러리가 업데이트 되었을 때 해당 DLL 파일만 교체하면 되기 때문에 쉽고 편하다.

 

 

▶ IAT(Import Address Table)

 

▷ VA, RVA, RAW

1) VA(Virtual Address)

: 프로세스 가상 메모리의 절대주소, 즉 실제 메모리에 로딩되는 주소

2) RVA(Relative Virtual Address)

: ImageBase로부터의 상대 주소(메모리에 로딩된 상태)

3) RAW 

: 디스크 상의 파일에서의 주소, 즉 PE 파일이 로딩되기 전 File Offset

 

★ RAW = RVA - VirtualAddress + PointerToRawData

 

▷ IID(IMAGE_IMPORT_DESCRIPTOR) 구조체

 

출처 : Microsoft Platform SDK - winnt.h

 

☆ 구조체 중요 멤버

 

1) OriginalFirstThunk

: INT(Import Name Table)의 주소(RVA)

2) Name

: Library 이름 문자열의 주소(RVA)

3) FirstThunk

: IAT(Import Address Table)의 주소(RVA)

 

▷ notepad.exe의 kernel32.dll에 대한 IMAGE_IMPORT_DESCRIPTOR 구조

 

출처 : https://foxtrotin.tistory.com/331

 

▷ PE Loader가 Import 함수 주소를 IAT에 입력하는 순서

 

1) IID의 Name 멤버를 읽어서 라이브러리의 이름 문자열("kernel32.dll")을 얻는다.

2) 해당 라이브러리("kernel32.dll")를 로딩한다.

3) IID의 OriginalFirstThunk 멤버를 읽어서 INT 주소를 얻는다.

4) INT에서 배열의 값을 하나씩 읽어 해당 IMAGE_IMPORT_BY_NAME주소(RVA)를 얻는다.

5) IMAGE_IMPORT_BY_NAME 의 Hint(ordinal) 또는 Name 항목을 이용하여 해당 함수("GetCurrentThreadId")의 시작 주소를 얻는다.

6) IID의 FirstThunk(IAT) 멤버를 읽어서 IAT의 주소를 얻는다.

7) 해당 IAT 배열 값에 위에서 구한 함수 주소를 입력한다.

8) INT가 끝날 때까지 (NULL을 만날때 까지) 4~7의 과정을 반복한다.

 

 

▶ notepad.exe를 이용한 IAT(Import Address Table) 실습

 

먼저 IMAGE_OPTIONAL_HEADER의 DataDirectory 구조체의 배열 정보를 확인해야 한다.

 

 

위에서 볼 수 있듯이 RVA 주소는 32B9B0, Size는 190임을 확인할 수 있다.

 

 

실제 해당 주소에 가 보면 RVA와 Size 값을 볼 수 있다.

 

이제 RVA 값을 알기 때문에 RWA(offset)을 구할 수 있다.

RAW = RVA - VirtualAddress + PointToRawData 이므로

RAW = 32B9B0 - 1000 + 0400 = 32ADB0

 

 

위 그림에서 블록 부분이 IID의 구조체 배열이다. (.text)

 

1) Name

 

 

2E746578 - 1000 + 0400 = 2E745B78

 

2. EAT(Export Address Table)

 

→ DLL 자신이 서비스하는 함수에 대한 정보를 기술해 놓은 테이블

→ 라이브러리 파일에서 제공하는 함수를 다른 프로그램에서 가져다 사용할 수 있도록 해주는 핵심 메커니즘

→ 즉, 라이브러리가 가진 함수를 다른 프로그램에서 사용할 수 있도록 하는 것

 

▶ EAT(Export Address Table)

 

notepad.exe의 kernel32.dll에 대한 IMAGE_EXPORT_DIRECTORY 구조

 

 

▷ IMAGE_EXPORT_DIRECTORY 구조체

 

출처 : Microsoft Platform SDK - winnt.h

 

☆ 구조체 중요 멤버

 

1) NumberOfFunctions 

: 실제 Export 함수 개수

2) NumberOfNames 

: Export 함수 중에서 이름을 가지는 함수 개수 (NumberOfFunctions)

3) AddressOfFunctions

: Export 함수 주소 배열 (배열의 원소 개수 = NumberOfFunctions)

4) AddressOfNames

: 함수 이름 주소 배열 (배열의 원소 개수 = NumberOfNames)

5) AddressOfNameOrdinals

: Ordinal 주소 배열 (배열의 원소 개수 = NumberOfNames)

 

▷ EAT 동작 원리

 

1) AddressOfNames 멤버를 이용해 ‘함수 이름 배열’로 이동한다.

2) ‘함수 이름 배열'은 문자열 주소가 저장되어 있어 문자열 비교를 통해 원하는 함수 이름을 찾는다.

3) IID의 OriginalFirstThunk 멤버를 읽어 INT 주소를 얻는다.

4) INT에서 배열의 값을 하나씩 읽어 해당 IMAGE_IMPORT_BY_NAME 주소(RVA)를 얻는다.

5) IMAGE_IMPORT_BY_NAME의 Hint(ordinal) 또는 Name 항목을 이용해 해당 함수의 시작 주소를 얻는다

→ GetProcAddress(“GetCurrentThreadld”)

6) IID의 FirstThunk(IAT) 멤버를 읽어 IAT 주소를 얻는다.

7) 해당 IAT 배열 값에 위에서 구한 함수 주소를 입력한다.

8) INT가 끝날 때까지(NULL을 만날 때까지) 위에서 4~7 과정을 반복한다.

 

 

▶ notepad.exe를 이용한 EAT(Export Address Table) 실습

 

 

 

 

 

 

+ Recent posts