본문 바로가기

Reversing/Theory

Chapter 8. PE Header III - IAT & EAT

Chapter 8. PE Header III - IAT & EAT

1. IAT(Import Address Table)
 - IAT
  · Windows의 Program이 어떤 Library에서 어떤 함수를 사용하고 있는지를 기술한 Table

  · PE File 내의 특정 구조체인 'IMAGE_IMPORT_DESCRIPTOR'에 Import에 관한 정보를 저장한다.
  · PE Header에서 Table은 배열을 의미한다.

  · 각 Section마다 존재한다.
  · IAT의 구조체 : IMAGE_IMPORT_DESCRIPTOR

  ◦ PE File은 자신이 어떤 library에게 함수를 제공(Import)받는지 IMAGE_IMPORT_DESCRIPTOR 구조체에 명시한다.
  ◦ IMAGE_IMPORT_DESCRIPTOR의 주요 Member
   ▹ OriginalFirstThunk : IAT(Import Name Table)
    ▸  INT(Import Name Table)의 주소(RVA)
    ▸  구조체에서는 OriginalFirstThunk로, PEView에서는 Import Name Table(INT)로 명시된다.
   ▹ Name
    ▸  Library 이름 문자열의 주소(RVA)
   ▹ FirstThunk
    ▸  IAT(Import Address Table)의 주소
    ▸  구조체에서는 FirstThunk로 PEView에서는 Import Address Table(IAT)로 명시된다.
  · IAT(Import Address Table) & INT(Import Name Table)

  ◦ INT(Import Name Table:OriginalFirstThunk)의 원소 값은 IMAGE_IMPORT_BY_NAME의 구조체 Pointer로 주소 값이 명시된다.
  ◦ INT(Import Name Table:OriginalFirstThunk)와 IAT(Import Address Table:FirstThunk)의 실제 크기는 같아야하며 Member의 내용 및 개수도 같다.
  ◦ IAT(Import Name Table:OriginalFirstThunk)는 Memory 상의 실제주소가 입력되고 INT는 IAT(Import Address Table:FirstThunk) Memeber의 Pointer 주소가 입력된다.
  ◦ INT(Import Name Table:OriginalFirstThunk)와 IAT(Import Address Table:FirstThunk)는 long Type의 배열이고 크기가 따로 명시되어있지 않아 문자열과 같이 NULL로 끝난다.
  · IMAGE_IMPORT_DESCRIPTOR의 구조 및 IAT 입력 순서

  ◦  PE Loader가 Import 함수 주소를 IAT에 입력하는 순서
   ▹   : IMAGE_IMPORT_DESCRIPTOR의 Name Member를 읽어 Library의 이름 문자열 kernel32.dll을 얻는다.
   ▹   : 해당 Library를 LoadLibrary 함수를 이용해 Process 내에 불러온다.
   ▹  ③ : IMAGE_IMPORT_DESCRIPTOR의 OriginalFirstThunk(INT) Member를 읽어들여 INT(Import Name Table)의 주소를 얻는다.
   ▹   : INT(Import Name Table)에서 배열의 값을 하나씩 읽어 해당 배열에 해당하는 IMAGE_IMPORT_BY_NAME 주소를 얻는다.
   ▹   : IMAGE_IMPORT_BY_NAME의 Hint를 이용해 해당 함수의 시작 주소를 얻는다.
   ▹   : IMAGE_IMPORT_DESCRIPTOR의 FirstThunk(IAT : Import Address Table) Member를 읽어 IAT의 주소를 얻는다.
   ▹   : IAT 배열 값을 위에서 함수를 이용해 구한 주소 값으로 덮어쓴다.
   ▹   : INT내에서 NULL 구조체를 만날 때까지 ④ ~ ⑦ 과정을 반복한다.


2. EAT(Export Address Table)
 - EAT

  · Library FIle에서 제공하는 함수를 다른 Program에서 가져다 사용할 수 있도록 해주는 Table
  · EAT를 통해서만 해당 Library에서 Export하는 함수의 시작 주소를 정확히 구할 수 있다.
  · IAT와 동일하게 PE File 내의 특정 구조체인 'IMAGE_EXPORT_DIRECTORY'에 Export에 관한 정보를 저장한다.
  · 각 Section마다 존재하는 IAT와는 달리 EAT는 PE File내에 하나만 존재한다.
  · IMAGE_EXPORT_DIRECTORY의 위치

  ◦  PEView를 이용해 살펴보면 IMAGE_EXPORT_DIRECTORY 구조체가 존재하지 않는다는 것을 알 수 있으며 IMAGE_OPTIONAL_HEADER 부분에 'Loader Flags' 부분부터 구조체 배열의 시작 주소가 된다.
  ◦ 구조체 배열이 시작되는 부분은 'IMAGE_OPRIONAL_HEADER32.DataDirectory[0]'이라고 한다.
  ◦ IMAGE_OPRIONAL_HEADER32.DataDirectory 구조체 배열의 Member
   ▹ Loader Flags
   ▹ Number of Data Diectories
   ▹ RVA of Export Directory
   ▹ Size of Export Directory
   ▹ RVA of Import Directory
   ▹ Size of Import Directory
  · 실제 IMAGE_EXPORT_DIRECTORY 구조체

  ◦ IMAGE_EXPORT_DIRECTORY의 주요 Member
   ▹ NumberOfFunction
    ▸  실제 Export 함수의 개수
   ▹ NumberOfNames
    ▸  Export 함수 중 이름을 가지는 함수의 개수
    ▸  'NumberOfFunction'와 값보다 작거나 같다.
   ▹ AddressOfFunction
    ▸  Export 함수 주소 배열
    ▸  배열의 Index(배열의 원소 개수)와 'NumberOfFunctions' 값이 같다.
   ▹ AddressOfNames
    ▸  함수 이름 주소 배열
    ▸  배열의 Index(배열의 원소 개수)와 'NumberOfNames' 값이 같다.
   ▹ AddressOfNameOrdinals
    ▸  함수 이름의 Ordinal(서수) 주소 배열
    ▸  배열의 Index(배열의 원소 개수)와 'NumberOfNames' 값이 같다.
  · GetPorcAddress() API와 EAT를 이용해 원하는 API의 주소를 얻어내는 과정

  ◦ 'GetProcAddress()'라는 함수는 Library에서 함수 주소를 얻는 API로 EAT를 참조해 원하는 API의 주소를 구한다.
  ◦ GetProcAddress() 함수의 동작 과정
   ▹ ① : AddressOfNames Member를 이용해 함수 이름 배열(Function Name Table)을 찾아간다.
   ▹ ② : 함수 이름 배열에는 문자열 주소가 저장되어 있으며 strcmp 함수를 이용해 원하는 함수의 이름을 찾아 해당 함수가 위치한 배열의 Index(Index Of Name)를 찾는다.
   ▹ ③ : AddressOfNameOrdinals Member를 이용해 'Ordinal 배열'을 찾는다.
   ▹ ④ : Ordinal 배열에서 ②단계에서 찾아낸 Index Of Name을 이용해 Ordinal 값을 찾는다.
   ▹  : AddressOfFunctions Member를 이용해 EAT(Export Address Table)로 간다.
   ▹ ⑥ : EAT에서 ④단계에서 찾은 Ordinal을 배열 Index로 하여 원하는 함수의 시작주소를 얻는다.