안 쓰던 블로그

32bit EAT 로딩 과정 본문

CTF/Reversing

32bit EAT 로딩 과정

proqk 2020. 10. 5. 16:01
반응형

EAT(Export Address Table)는 라이브러리 파일에서 제공하는 함수를 다른 프로그램에서 가져다 사용할 수 있도록 해주는 핵심 메커니즘이다. 
( 라이브러리가 가진 함수를 다른 프로그램에서 사용할 수 있도록 하는 것)

 

IAT처럼 PE 파일 내의 특정 구조체인 IMAGE_EXPORT_DIRECTORY에 정보를 저장한다. 이 구조체는 PE 파일에 하나만 존재한다.

 

중요 멤버

NumberOfFunctions : 실제 Export 함수의 개수
NumberOfNames : Export 함수 중에서 이름을 가지는 함수 개수 (<=NumberOfFunctions)
AddressOfFunctions : Export 함수 주소 배열 (배열의 원소 개수 = NumberOfFunctions)
AddressOfNames : 함수 이름 주소 배열 (배열 원수 개수 = NumberOfNames)
AddressOfNamesOrdinals : Ordinal 배열 (배열의 원소 개수 = NumberOfNames)

 

EAT를 참조하여 특정 API주소를 구하는 실습을 진행한다

아래와 같은 과정을 통해 진행할 것이다

1. AddressOfNames 멤버를 이용해 '함수 이름 배열'로 이동
2. '함수 이름 배열'은 문자열 주소가 있으므로, 문자열 비교를 통하여 원하는 함수 이름을 찾는
다.(name_index)
3. AddrssOfNameOrdinals멤버를 이용하여 'ordinal' 배열로 이동
4. 'ordinal 배열'에서 name_index를 이용하여 해당 ordinal 값을 찾는다.
5. AddrssOfFunctions 멤버를 이용하여 함수 주소 배열(EAT)로 이동
6. EAT에서 ordinal을 배열 인덱스로 하여 원하는 함수의 시작주소를 얻는다.

 

Kernel32.dll을 이용한 실습

위에 1~6을 진행하기 전에 IMAGE_EXPORT_DIRECTORY 구조체 배열을 찾아야 한다

RVA, VA, PointerToRawData 값으로 RAW를 계산하고 넘어가는 식의 과정이 필요하다

실습은 PEview로 진행한다

 

RVA가 92250임을 확인한다

 

RVA로 RAW를 구하는 계산식은 RAW = RVA - VA + PointerToRawData (foxtrotin.tistory.com/330)

(파일의 임의 위치 = 메모리의 임의 위치 - 메모리의 해당 섹션 시작 위치 + 파일의 해당 섹션 시작 위치)

 

RVA가 속한 섹션의 VA와 Pointer To Raw 확인

 

VA(메모리 해당 섹션 시작 위치)는 80000

Pointer To Raw(파일 해당 섹션 위치)는 65000

 

RAW=92250-80000+65000=77250 (hex)

77250가 Export Directory의 시작 offset이다

 

77250+DA48(Size)=84C98 (hex)이 IMAGE_EXPORT_DIRECTORY 끝나는 부분이다

 

77250을 찾으면 위에서 말한 IMAGE_EXPORT_DIRECTORY 구조체 배열이 위치한다

 

필요한 중요멤버 값을 확인한다

NumberOfFunctions : 실제 Export 함수의 개수
NumberOfNames : Export 함수 중에서 이름을 가지는 함수 개수 (<=NumberOfFunctions) 
AddressOfFunctions : Export 함수 주소 배열 (배열의 원소 개수 = NumberOfFunctions) 
AddressOfNames : 함수 이름 주소 배열 (배열 원수 개수 = NumberOfNames) 
AddressOfNamesOrdinals : Ordinal 배열 (배열의 원소 개수 = NumberOfNames)

 

Member File Offset RVA RAW (RVA-80000+65000)
NumberOfFunctions  77264 00643 -
NumberOfNames  77268 00643 -
AddressOfFunctions  7726C 92278 77278
AddressOfNames  77270 93B84 78B84
AddressOfNamesOrdinals  77274 95490 7A490

여기까지 필요한 값을 다 구했다.

 

1. AddressOfNames 멤버를 이용해 '함수 이름 배열'로 이동

AddressOfNames의 RAW는 78B84

함수 이름 배열이 있는 것을 확인할 수 있다

이곳의 배열 원소 개수는 NumberOfNames만큼이니까 643이다

HxD에서 Offset 78B84를 찾으면 동일한 결과를 볼 수 있다

 

2. '함수 이름 배열'은 문자열 주소가 있으므로, 문자열 비교를 통하여 원하는 함수 이름을 찾는다.(name_index)

함수 이름 배열의 맨 첫번째 원소로 들어있는 AcquireSRWLockExclusive 문자열을 Names에서 찾아본다

RAW=96182-80000+65000=7B182

AcquireSRWLockExclusive문자열이 위치함을 확인할 수 있다

 

3~4. AddrssOfNameOrdinals멤버를 이용하여 'ordinal' 배열로 이동 후 'ordinal 배열'에서 name_index를 이용하여 해당 ordinal 값을 찾는다. 

RAW 7A490으로 이동하면 2바이트의 ordinal배열이 있다

아까 보았던 함수 이름 배열의 맨 첫번째 원소로 들어있는 AcquireSRWLockExclusive문자열은 AddressOfNamesOrdinals[0]이라고 할 수 있고, PEview에서 본 ordinal(0)의 데이터는 0003이므로 HxD에서 보면 03 00 이라고 표시될 것이다

 

5. AddrssOfFunctions 멤버를 이용하여 함수 주소 배열(EAT)로 이동

AddressOfFunctions값은 RAW 77278이다

이동하면 4바이트의 함수 주소 RVA 배열이 있다. 이 RVA 배열이 Export함수 주소들이다

위에서 찾은 AcquireSRWLockExclusive 문자열이 4번째에 위치한다

그 이유는 AcquireSRWLockExclusive의 ordinal값이 0003이었으므로 AddressOfFunctions[3]의

값이 해당 문자열이기 때문이다

 

6. EAT에서 ordinal을 배열 인덱스로 하여 원하는 함수의 시작주소를 얻는다.

AddressOfFunctions 함수의 시작 주소 VA는 ImageBase+RVA로 구할 수 있다

RVA는 바로 위의 사진에서 볼 수 있듯 9619A이다

 

 

헤더를 보면 ImageBase는 6B800000이다

 

AddressOfFunctions함수의 실제 주소(VA)는 6B800000+9619A=6B89619A

 

 

반응형
Comments