1. EAT(Export Address Table)
EAT(Export Address Table)는 라이브러리 파일에서 제공하는 함수를 다른 프로그램에서 가져다 사용할 수 있도록 해주는 핵심 메커니즘이다. 즉, EAT를 통해서만 해당 라이브러리에서 익스포트하는 함수의 시작 주소를 정확히 구할 수 있다.
IAT와 마찬가지로 PE 파일 내의 IMAGE_EXPORT_DIRECTORY
에 익스포트 정보를 저장하고 있다. IAT와는 달리 PE파일에 IMAGE_EXPORT_DIRECTORY
구조체는 하나만 존재한다.
[ PE파일에서 IMAGE_EXPORT_DIRECTORY 구조체의 위치 ]
IMAGE_OPTIONAL_HEADER32.DataDirectory[0].VirtualAddress
값이 실제 IMAGE_EXPORT_DIRECTORY
구조체 배열의 시작 주소이다.(RVA값)
1) IMAGE_EXPORT_DIRECTORY 구조체
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp ; // creation time date stamp
WORD MajorVersion;
WORD MinorVersion;
DWORD Name; // address of librar y file name
DWORD Base; // ordinal base
DWORD NumberOfFunctions; // number of functions
DWORD NumberOfNames; // number of names
DWORD AddressOfFunctions ; // address of function start address array
DWORD AddressOfNames; // address of function name stri ng array
DWORD AddressOfNameOrdinals; // add ress of ordinal array
} lMAGE_EXPORT_DIRECTORY, *PlMAGE_EXPORT_DIRECTORY;
[ 주요 멤버 설명 ]
NumberOfFunctions
: 실제 Export 함수 개수
NumberOfNames
: Export 함수 중에서 이름을 가지는 함수 개수(≤ NumberOfFunctions)
AddressOfFunctions
: Export 함수 주소 배열(배열의 원소 개수 = NumberOfFunctions)
AddressOfNames
: 함수 이름 주소 배열(배열의 원소 개수 = NumberOfNames)
AddressOfNameOrdinals
: Ordinal 주소 배열(배열의 원소 개수 = NumberOfNames)
라이브러리에서 함수 주소를 얻는 API는 GetProcAddress()
이며, 이 API함수가 바로 EAT를 참조해서 원하는 API의 주소를 구하나다.
[ GetProcAddress() 동작 원리 ]
① AddressOfNames
멤버를 이용해 '함수 이름 배열'로 간다.
② 문자열 비교(stcmp)를 통하여 원하는 함수 이름을 찾는다.(배열의 인덱스를 name_index)
③ AddressOfNameOrdinals
멤버를 이용해 ordinal 배열로 간다.
④ ordinal 배열에서 name_index로 해당 ordinal 값을 찾는다.
⑤ AddressOfFunctions
멤버를 이용해 '함수 주소 배열(EAT)'로 간다.
⑥ '함수 주소 배열(EAT)'에서 아까 구한 ordinal을 배열 인덱스로 하여 원하는 함수의 시작 주소를 얻는다.
참고로 위 과정은 이전에 Universal Shell Code
를 짜기 위한 루틴과 동일하다.
위와 같이 복잡한 작업을 하는 이유는 익스포트하는 함수 중에 이름이 존재하지 않을 수도 있으며(Ordinal로만 익스포트) AddressOfNamesOrdinals 배열의 값이 index ≠ ordinal인 경우도 있기 때문이다. 따라서, 위와 같은 순서를 거쳐야 정확한 함수 주소를 얻을 수 있다.
Uploaded by Notion2Tistory v1.1.0