PC리버싱/PE구조

IAT/EAT 정리

Lamed_Dhhd 2020. 5. 23. 00:09
반응형

1 개요

자 이제 IAT와 EAT에 관해서 알아 볼 것이다. 앞 장에서 자세히 설명하지 않고 넘어간 NT Header -> Optional Header -> DataDirectory 멤버의 구조체에서 EXPORT Directory와 IMPORT Directory와 관련된 부분이다. API후킹 방법 중 하나로 활용되므로 꼭 숙지하길 바란다.

IAT(Import Address Table)로 쉽게 말해서 프로그램이 어떤 라이브러리에서, 어떠한 함수를 사용하는지 적은 메모장이라 생각하면 된다.

IAT의 원리를 알기 위해선 DLL에 대한 개념이 필수적이다. DLL이란, 여러 프로세스에서 공유하면서 쓰는 라이브러리인데 멀티태스킹 환경에서는 각 프로세스마다 라이브러리를 가지고 그 용량을 차지하는 것 보다, 메모리에 한번 로딩시켜 프로세스마다 공유시키면 메모리를 더 효율적으로 사용 할 수 있기 때문에 DLL이 탄생하였다.

<출처 http://www.hanbit.co.kr/network/view.html?bi_id=1326>

예를 들어, 위의 프로세스 A의 Page 1이 Frame 5를 가리키고, 프로세스 B의 Page 7도 마찬가지로 Frame 5를 가리킨다. 이것은, DLL을 한번 메모리에 로드 시키고, 그 영역을 프로세스 별로 공유한다는 것을 뜻한다. 여기서 주의할 점은, DLL이 메모리에 어느 곳에 로딩되어 있는지 프로그래밍 할 당시에 확인할 방법이 없다는 것이다. 그래서, IAT라는 공간을 만들어 두고, PE Loader가 이 공간에 DLL이 메모리상 어디에 위치 되어 있는지 쓰는 과정을 거치게 된다.

여기서 또 알 수 있는 점은 DLL이 올라 갈 때, 메모리상에 바로 올라 가는 것이 아니라 프로세스 가상메모리에 먼저 올라 가고, 페이지 테이블에서 물리 메모리에 지정된다는 것이다. IAT와 EAT를 배우면 이 과정이 좀더 자세하게 그림이 그려질 것이다.

2 IAT

자, IMAGE_IMPORT_DESCRIPTOR구조체의 FirstThunk라는 멤버가 IAT를 가리킨다. 그럼, IMAGE_IMPORT_DESCRIPTOR는 어디에서 확인할까? 바로 NT Header-> Optioinal Header-> DataDirectory 에서의 2번째 변수 값이 가리키는 위치에 존재한다. 그럼, IMAGE_IMPORT_DESCRIPTOR 구조체가 어떤 멤버로 구성되어 있는지 확인해 보자.

보통 하나의 프로그램에서 여러 개의 라이브러리를 갖기 때문에, IID는 배열의 형식으로 나타나게 된다. 이 멤버들 중 우리에게 중요한 부분은 주석으로 달린 부분들 이다. OriginalFirstThunk같은 경우는 라이브러리의 함수들의 주소를 가리키고 있는 부분들이다. Name멤버는, 라이브러리의 이름을 뜻한다. FirstThunk멤버는 IAT의 주소값을 가리킨다.

자 이제 어떠한 방식으로 IAT에 함수 주소들이 로딩되는지 알아 볼 텐데 꾀나 복잡하다. 하지만 상식적으로 생각하면 쉽게 와 닿는다. 프로그램에서 라이브러리를 사용 할 경우, 먼저 라이브러리를 로딩시켜야 하지 않겠나? 그럼 필요한 것이 라이브러리의 이름이다.(Name 멤버) 그 다음 필요한 것이 무엇 이겠는가? 우린 지금 라이브러리에 존재하는 함수들의 위치를 IAT에 적으려 하고 있다. 그렇다면 필요한 것은 바로 라이브러리에 존재하는 함수들의 이름이다(INT멤버) 그럼 필요한 것은 모두 구했다. 이제 이 값을 이용해 FirstThunk 를 이용하여 IAT에 함수 주소를 입력하면 끝이다. 이 순서를 좀 더 자세히 표현한 것은 다음과 같다.

1. IDD의 Name멤버를 이용해 라이브러리의 이름을 얻는다.
2. 라이브러리를 로딩시킨다(Loadlibrary).
3. INT의 값을 읽어 IMAGE_IMPORT_BY_NAME구조체들의 주소(RVA)를 얻는다.
4. IMAGE_IMPORT_BY_NAME 의 멤버를 이용하여 함수의 시작주소를 얻는다.
5. FirstThunk멤버를 이용해 IAT에 함수의 시작 주소값을 입력한다.
6. OriginalFirstThunk가 끝날 때 까지 3~5의 과정을 반복한다.

여기서 다루지 않은 부분이 IMAGE_IMPORT_BY_NAME구조체 부분이다.

참고로 INT와 IAT는 NULL로 끝나고 둘의 크기는 반드시 같아야 한다.

3 EAT

EAT(Export Address Table)란 라이브러리 파일에서 제공하는 함수를 다른 프로그램에서 가져다 사용할 수 있도록 해주는 과정에서 중요한 역할을 한다. IAT를 공부 할 때, LoadLibrary 함수를 이용해 라이브러리를 로딩시키는 과정에서 일어나는 과정을 설명할 것이다. 우선 IMAGE_EXPORT_DIRECTORY의 구조체를 살펴 보자. 이 구조체 위치는 OptionalHeader->DataDirectory[0]이 가리킨다.

중요한 멤버들은 주석으로 표시를 하였다.
그렇다면 이제 어떤 과정으로 라이브러리의 함수들이 로딩 되는지 살펴 보겠다.

1. AddressOfNames 멤버(RVA값)를 이용해 '함수 이름 배열' 로 간다. 즉, 함수들의 이름을 적어놓은 공간이라 생각하면 된다.
2. '함수 이름 배열'은 문자열 주소가 저장되어 있다. 문자열 비교를 통해 원하는 함수의 이름을 찾는다. 그리고 이 때의 인덱스 값을 구한다.
3. AddressOfNameOrdinals 멤버(RVA)값 을 이용해 'ordinal'배열로 간다.
4. 'ordinal'배열에서 2번에서 구한 인덱스 값을 이용해 ordinal값을 찾는다.
5. AddressOfFunctions을 이용해 EAT로 간다.
6. EAT에서 4번에서 구한 ordinal을 배열 인덱스로 하여 원하는 함수의 시작 주소를 얻는다.

4 정리

EAT와 IAT의 과정을 묶어서 이해 할 필요가 있습니다. 어떤 순서로 되는지 짚어 보겠습니다.

-------------------------<IAT 과정>-------------------------

1. IDD의 Name멤버를 이용해 라이브러리의 이름을 얻는다.
2. 라이브러리를 로딩시킨다(Loadlibrary).
3. INT의 값을 읽어 IMAGE_IMPORT_BY_NAME구조체들의 주소(RVA)를 얻는다.
4. IMAGE_IMPORT_BY_NAME 의 멤버를 이용하여 함수의 시작주소를 얻는다.

-------------------------<EAT 과정>-------------------------

4-1. AddressOfNames 멤버(RVA값)를 이용해 '함수 이름 배열' 로 간다. 즉, 함수들의 이름을 적어놓은 공간이라 생각하면 된다.
4-2. '함수 이름 배열'은 문자열 주소가 저장되어 있다. 문자열 비교를 통해 원하는 함수의 이름을 찾는다. 그리고 이 때의 인덱스 값을 구한다.
4-3. AddressOfNameOrdinals 멤버(RVA)값 을 이용해 'ordinal'배열로 간다.
4-4. 'ordinal'배열에서 2번에서 구한 인덱스 값을 이용해 ordinal값을 찾는다.
4-5. AddressOfFunctions을 이용해 EAT로 간다.
4-6. EAT에서 4번에서 구한 ordinal을 배열 인덱스로 하여 원하는 함수의 시작 주소를 얻는다.
-----------------------------------------------------------------
5. FirstThunk멤버를 이용해 IAT에 함수의 시작 주소값을 입력한다.
6. OriginalFirstThunk가 끝날 때 까지 3~5의 과정을 반복한다.

 



출처: https://flack3r.tistory.com/entry/IAT와-EAT [Be myself]

반응형

'PC리버싱 > PE구조' 카테고리의 다른 글

더미다 OEP찻는방법중 하나(API이용)  (0) 2020.08.08
CTF Exploer  (0) 2020.05.24
PE구조 총정리 사진  (0) 2020.05.22
PE공부 사이트추천  (0) 2020.05.22
언패킹예제 UPX MUP(언패킹)  (3) 2020.05.21