티스토리 뷰

[Reversing] DLL의 EAT에서 API 주소 얻기


1. AddressOfNames()을 이용하여 원하는 함수의 이름을 찾은 후, 함수 이름을 비교하여 인덱스를 구한다.

2. AddressOfNameOrdinals()을 이용하여 ordinal 배열에서 인덱스 값을 찾는다.

3. AddressOfFunction()을 이용하여 EAT에서 ordinal 값을 찾아 함수의 시작 주소를 가져온다.

 출처 : x64dbg 디버거를 활용한 리버싱과 시스템 해킹의 원리


간략하게 풀어서 말하면 EAT kernel32 API loading 절차

EXPORT Table 주소 > IMAGE_EXPORT_DIRECTORY 시작 주소 + 20 > EXPORT Name Pointer Table RVA 시작 주소  > 

필요 API 함수 이름의 주소얻음 > API 이름 주소에서 Kernel32 모듈 주소  > EXPORT Ordinal Table 시작 주소 얻음 > 

시작 주소에서 x번째 인덱스 확인(필요 API) > 인덱스 얻음 > EXPORT Address Table 시작 주소에서 인덱스 만큼 더하면 API 주소 얻음 


즉, EAT 자신이 가지고 있는 함수를 다른 파일에 제공해 주는 것으로 Export Directory 구조체를 통해 원하는 함수의 이름 주소를 얻은  ordinal table 시작 주소에서 찾고자하는 함수의 인덱스를 얻은  EAT에서 해당 인덱스를 통해 실제 API 주소를 얻을  . 


다음은 VB 분석시 해당하는 부분을 정리했다.

PEB 구조체의 LDR 멤버를 이용하여 DLL을 얻는 것을 알 수 있다. 이후 비교 구분을 통해 원하는 DLL을 얻었는지 확인 후 분기를 진행하는 것을 알 수 있다. 

 

그림 1  .dll loading 

(그림 2)을 살펴보면 EXPORT Table 주소를 얻은 후 [IMAGE_EXPORT_DIRECTORY 시작 주소 + 20]을 통해 Name Pointer Table RVA 즉, EXPORT Name Porint Table 시작 주소까지 얻는 것을 확인 할 수 있다. 

 

그림 2  API loading_1 

이후 반복 루틴을 통해 EXPORT Names에서 GetProcAddress()을 얻은 후 EDX에 저장하는 것은 확인 할 수 있다. 

 

그림 3  API loading_2 

GetProcAddress()의 이름을 얻은 후 (그림 4)을 살펴보면 먼저 ESI에서 Kernel32 모듈 주소를 빼게 되면 “B7A64” 즉, Kernel32 EXPORT Ordinal Table의 시작 주소인 걸 확인 할 수 있다. 

 

그림 4  API loading_3 

EXPORT Ordinal Table의 시작 주소에서 244번째 인덱스에 GetProcAddress()을 확인 할 수 있다.

 

그림 5  API loading_4 

EXPORT Address Table의 시작 주소를 가르키는 것을 확인 할 수 있다.