실제로 notepad.exe를 대상으로 하나씩 살펴보자. 어떤곳에 IMAGE_IMPORT.DESCRIPTOR 구조체 배열은 PE파일의 어느곳에 존재하는가
바로 PE헤더가 아닌 PE바디에 위치한다. 그곳에 찾아가기 위한 정보는 역시 PE헤더에 있는데 IMAGE_OPTIONAL_HEADER32.DataDirectory[1].VirtualAddress 값이 실제 IMAGE_IMPORT_DESCRIPTOR 구조체 배열의 시작 주소이다(RVA 값). IMAGE_IMPORT_DESCRIPTOR 구조체 배열을 다른 용어로는 IMPORT Directory Table이라고 한다.
IMAGE_OPTIONAL_HEADER32.DataDirectory[1] 구조체는 다음 그림과 같다(첫번째 4바이트가 VirtualAddress,두 번째 4바이트가 Size맴버이다.)
다음은 notepad.exe의 IMAGE_OPTIONAL_HEADER32.DataDirectory[1]이다.
offesets |
value |
description |
00000158 |
00000000 |
RVA of EXPORT Directory |
0000015C |
00000000 |
size of EXPORT Directory |
00000160 |
00007604 |
RVA of IMPORT Directory |
00000164 |
000000C8 |
size of IMPORT Directory |
00000168 |
0000B000 |
RVA of RESOURCE Directory |
0000016C |
00008304 |
size of RESOURCE Directory |
위를 보면 RVA가 7604이므로 RVA to RAW 공식을 사용해서 7604-1000+400을 하면 File Offset은 6A04가 나오고 파일에서 6A04를 참고
notepad.exe의 IMAGE_IMPORT_DESCRIPTOR 구조체 배열
위의그림에서 음영으로 표시된 부분이 전부 IMAGE_IMPORT_DESCRIPTOR 구조체 배열이고 박스로 되어ㅓ 있는 부분은 구조체 배열의 첫번째 원소이다. (참고로 배열의 마지막 NULL 구조체로 되어 있는것도 확인할 수 있다.) 박스 부분의 IMAGE_IMPORT_DESCRIPTOR 구조체를 살펴보자
File Offset |
Member |
RVA |
RAW |
6A04 |
OriginalFirstThunk(INT) |
00007990 |
00006D90 |
6A08 |
TimeDateStamp |
FFFFFFFF |
- |
6A0C |
ForwarderChain |
FFFFFFFF |
- |
6A10 |
Name |
00007AAC |
00006EAC |
6A14 |
FirstThunk |
000012C4 |
000006C4 |
IAT를 공부하는 입장에서 하나하나따라가도록 해보자.
1. 라이브러리 이름(Name)
Name 항목은 임포트 함수가 소속된 라이브러리 파일의 이름 문자열 포인터이다. RVA: 7AAC -> RAW : 6EAC 파일 오프셋 6EAC에 "comdlg32.dll"이 보인다.
2. OriginalFirstThunk -INT(Import Name Table)
INT는 임포트하는 함수의 정보(Ordinal, Name)가 담긴 구조체 포인터 배열이다. 이 정보를 얻어야 프로세스 메모리에 로딩된 라이브러리에서 해당 함수의 시작 주소를 정확히 구할수 있다. (이후 나올 EAT를 참고)
OriginalFirstThunk 맴버를 따라간다.(RVA:7990 -> RAW: 6D90)
위의 사진이 INT이다. 주소 배열 형태로 되어 있다.(배열의 끝은 NULL로 되어있다).
주소 값 하나하나가 각각의 IMAGE_IMPORT_BY_NAME 구조체를 가리키고 있다.
배열의 첫번째 값인 7A7A(RVA)를 따라가보면 임포트 하는 API 함수 이름 문자열이 나타날것이다.
3. IMAGE_IMPORT_BY_NAME
RVA: 7A7A는 RAW : 6E7A이다.
파일 오프셋 6E7A의 최초 2바이트 값(000F)은 Oridinal로, 라이브러리에서 함수의 고유 번호이다. Ordinal 뒤로 'PageSetupDigW' 함수 이름 문자열이 보인다.(문자열의 마지막은 C언어와 마찬가지로 Terminating NULL['\0']로 끝난다.)
여기까지 정리하면 INT는 IMAGE_IMPORT_BY_NAME 구조체 포인터 배열이다. 배열의 첫 번째 원소가 가리키는 함수의 Ordinal 값은 000F이고 함수의 이름은 'PageSetupDigW'이다.
4.FirstThunk-IAT(Import Address Table)
IAT의 RVA: 12C4는 RAW: 6C04이다.
위의 그림에서 파일 오프셋이 6C04~6E0B 영역이 'comdlg32.dll' 라이브러리에 해당하는 IAT 배열 영역이다. I NT와 마찬가지로 구조체 포인터 배열 형태로 되어 있으며 배열은 NULL로 끝난다.
IAT의 첫 번째 원소 값은 이미 76324906로 하드코딩 되어있다. 이 값은 의미 없는 값으로, notepad.exe 파일이 메모리에 로딩될 때 이 값은 정확한 주소값으로 대체된다.
'리버스 엔지니어링' 카테고리의 다른 글
PE재배치 동작 원리 (0) | 2018.05.14 |
---|---|
PE 재배치 -1 (0) | 2018.05.14 |
Lenas_Reversing_for_Newbies를 크랙해보자 (0) | 2018.05.06 |
IAT란? -2 IMAGE_IMPORT_DESCRIPTOR (0) | 2018.01.19 |
IAT란? -1 DLL (0) | 2018.01.18 |