Information Security

IAT(Import Address Table) 본문

Reverse Engineering

IAT(Import Address Table)

leeeeye321 2019. 6. 12. 15:31

IAT(Import Address Table)

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

 

DLL(Dynamic Linked Library, 동적 연결 라이브러리)이란 여러 프로그램에서 동시에 사용할 수 있는 코드와 데이터를 포함한 라이브러리이다.

DLL의 로딩 방식은 두 가지인데, 그 중 하나가  프로그램 시작할 때 같이 로딩되어 종료 시 메모리에서 해제되는 Implicit Linking 방식이다. IAT는 Implicit Linking에 대한 메커니즘을 제공한다.

 

 

 

 

 

CALL [1001104]

notepad.exe에서 kernel32.dll의 CreateFileW를 호출하는 명령어이다.

 

이 CALL 명령에서 호출하는 주소는 CreateFileW의 주소가 아니라 IAT 메모리 영역이다.

1001104 주소에는 7C810CD9라는 값이 저장되어 있는데, 이 값이 CreateFileW의 주소이다.

 

이렇게 CALL 7C810CD9 명령을 사용하지 않고, IAT 영역을 사용하는 이유는 두 가지가 있다.

1. 환경에 따라 kernel32.dll의 버전이 달라지고, 함수의 주소가 달라지기 때문이다.

모든 환경에서 함수 호출을 보장하기 위하여 컴파일러는 실제 주소가 저장될 위치와 CALL [위치] 명령어를 준비한다. 파일이 실행되는 순간 PE 로더가 그 위치에 실제 함수의 주소를 입력한다.

 

2. DLL Relocation

DLL이 ImageBase 값에 로딩되고, 또 다른 DLL도 같은 곳에 로딩을 시도하면 PE 로더는 다른 비어있는 공간에 로딩시켜 준다. 이렇게 재배치가 일어나기 때문에, 함수 주소로 하드코딩을 할 수가 없다.

 

이어서 PE로더가 어떤 방법으로 IAT에 함수 주소를 입력하는지 알아봐야 겠다. 

 

 

 

 

IMAGE_IMPORT_DESCRIPTOR(=Import Directory Table)

PE 파일은 자신이 어떤 라이브러리를 Import하고 있는지를 IID 구조체에 명시한다.

일반적 프로그램은 여러 라이브러리를 임포트하므로 라이브러리의 개수만큼 구조체 배열이 존재한다. (구조체 배열은 NULL 구조체로 끝난다.)

 

 

 

 OriginalFirstThunk

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

 Name

 라이브러리 이름 문자열의 주소(RVA)

 FirstThunk

 IAT의 주소(RVA)

 

* INT와 IAT는 long type(4바이트) 배열이고 NULL로 끝난다.

* INT에서 각 원소의 값은 IMAGE_IMPORT_BY_NAME 구조체 포인터이다.

* INT와 IAT의 크기는 같아야 한다.

 

PE 로더가 임포트 함수 주소를 IAT에 입력하는 순서는 다음과 같다.

 

1. IID의 Name 멤버를 읽어들여서 라이브러리의 이름 문자열을 얻는다.

2. 해당 라이브러리를 로딩한다.

3. 이번에는 OriginalFirstThunk에서 INT의 주소를 얻는다.

4. IMAGE_IMPORT_BT_NAME 구조체의 Hint 또는 Name 멤버를 이용하여 함수의 시작 주소를 얻는다.

5. IID의 FirstThunk에서 IAT의 주소를 얻는다.

6. IAT의 배열 값으로 INT에서 얻은 함수 주소를 입력한다.

7. INT가 NULL을 만날 때까지 4~7번을 반복한다.

 

 

 

 

PEview로 IID를 직접 확인해 볼 것이다. IID 구조체의 위치는 OPTIONAL 헤더의 DataDirectory[1].VirtualAddress(RVA)에 저장되어 있다. PEview로 확인한 결과 위치가 7604인 것을 알 수 있다.

 

7604를 RAW로 변환하면 7604 - 1000 + 400 = 6A04이다. HxD로 이 위치를 찾아가면 IID 구조체를 확인할 수 있다.

사이즈는 C8이기 때문에 6A04 ~ 6ACD까지 IID이다.

 

 

 

 

화살표로 표시한 부분이 IID 구조체 배열의 첫 번째 원소이다.

 

 Offset

 Member

 RVA

 RAW

 6A04

 OriginalFirstThunk (INT)

 00007990

 7990 - 1000 + 400 = 6D90

 6A10

 Name

 00007AAC

 7AAC - 1000 + 400 = 6EAC

 6A14

 FirstThunk (IAT)

 000012C4

 12C4 - 1000 + 400 = 6C4

멤버들의 정보를 정리한 것이다. RAW를 보고 각각 멤버들을 찾아간다. 

 

 

 

 

1. Name (라이브러리 이름)

 IID 구조체 배열 첫 번째 원소의 라이브러리 이름은 comdlg32.dll으로 확인

 

 

2. OriginalFirstThunk - INT(Import Name Table)

INT는 임포트하는 함수의 정보가 담긴 구조체 포인터 배열이다. 이를 통해서 함수의 시작 주소를 정확히 구할 수 있다.

주소 값이 각각 IMAGE_IMPROT_BY_NAME 구조체를 가리킨다.

 

 

3. IMAGE_IMPROT_BY_NAME

배열의 첫 번째 값 7A7A(RAW: 6E70)으로 가면 임포트하는 API 함수 이름 문자열이 있다.

Ordinal: 000F / Name: PageSetupDlgW

 

 

4. FirstThunk - IAT(Import Address Table)

comdlg32.dll 라이브러리에 해당하는 IAT 배열 영역이다. 파일이 로딩될 때 이 영역들이 정확한 함수 주소로 대체되는 것이다.

OllyDbg에서 IAT를 확인하기 위해 주소를 변환한다. 

12C4(RVA) + 1000000(ImageBase) = 10012C4

 

 

 

 

 

주소를 찾아가보니 763D4906을 가리키고 있다.

 

이는 comdlg32 라이브러리의 PageSetupDlgW 함수의 정확한 주소이다.

 

여기까지, IAT가 무엇인지 알아보고 직접 값을 확인도 해보았다. 다음에는 EAT에 대해서 알아보겠다. 

 

'Reverse Engineering' 카테고리의 다른 글

DLL Ejection  (0) 2019.06.21
DLL Injection - Remote Thread 생성 & 레지스트리 이용  (0) 2019.06.20
Windows Message Hooking  (0) 2019.06.17
EAT(Export Address Table)  (0) 2019.06.12
PE File Format  (0) 2019.06.12