안 쓰던 블로그
32bit EAT 로딩 과정 본문
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
'CTF > Reversing' 카테고리의 다른 글
윈도우10 DLL 인젝션 구현 (CreateRemoteThread 사용) (0) | 2020.11.16 |
---|---|
[리버싱] DLL과 32bit IAT 로딩 과정 (0) | 2020.10.08 |
32bit IAT 로딩 과정 2 (0) | 2020.10.05 |
UPX 패킹된 프로그램 분석 및 툴없이 언패킹하기 (0) | 2020.10.01 |
VA, RVA, RAW 개념 (1) | 2020.09.29 |