Tuuna Computer Science

[Reversing] PE Format IMAGE_IMPORT_DESCRIPTOR 분석 본문

Reversing

[Reversing] PE Format IMAGE_IMPORT_DESCRIPTOR 분석

GuTTe 2019. 4. 24. 09:21

IMAGE_IMPORT_DESCRIPTOR를 엄청나게 헷갈려했기에 정리하는 겸  배운만큼 써볼려함. 

일단 IMAGE_IMPORT_DESCRIPTOR은 

typedef struct _IMAGE_IMPORT_DESCRIPTOR {
    union {
        DWORD   Characteristics;            
        DWORD   OriginalFirstThunk;       // INT(Import Name Table) address (RVA)
    };
    DWORD   TimeDateStamp;
    DWORD   ForwarderChain;
    DWORD   Name;                         // library name string address (RVA)
    DWORD   FirstThunk;                   // IAT(Import Address Table) address (RVA)
} IMAGE_IMPORT_DESCRIPTOR;


typedef struct _IMAGE_IMPORT_BY_NAME {
    WORD    Hint;                         // ordinal
    BYTE    Name[1];                      // function name string
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

위와 같은 구조체형태를 지닌다.

IMAGE_IMPORT_DESCRIPTOR구조체에서 가장 중요한 3가지는 

DWORD OriginalFirstThunk

DWORD Name

DWORD FirstThunk 

이 3가지이다. 

 

일단 OriginalFirstThunk는 INT의 RVA 값을 가지고 있다. 

Name은 라이브러리의 문자열의 RVA를 지니며 

FirstThunk는 IAT의 RVA 값을 지니고 있다. 

위 사진처럼 OriginalFirstThunk는 INT의 RVA의 값을 가지며 INT는 하나의 배열을 이룬다. 

이 INT 배열에는 특정 라이브러리에 해당하는 함수의 이름의 주소가 배열형식으로 들어있다. 

그리고 Name에는 라이브러리 이름의 주소가 있으며 

FirstThunk에는 IAT의 주소가 있으며 IAT배열에는 각 종 라이브러리에 해당하는 함수들의 주소가 들어있다. 

그리고 이 IMAGE_IMPORT_DESCRIPTOR구조체는 실행파일을 만들면서 PE Loader가 아래의 순서대로 채워 넣는다. 


1. IID의 Name멤버를 읽어서 라이브러리의 이름 문자열을 얻는다. (kernel32.dll)
2. 해당 라이브러리를 로딩
3. IID의 OriginalFirstThunk 멤버를 읽어서 INT 주소를 얻는다.
4. INT에서 배열의 값을 하나씩 읽어 해당 IMAGE_IMPORT_BY_NAME의 주소를 얻는다.
5. IMAGE_IMPORT_BY_NAME의 Hint or Name항목을 이용하여 해당함수의 시작 주소를 얻는다.
6. IID의 FirstThunk를 읽어 IAT의 주소를 얻는다.
7. 해당 IAT배열에 위에서 구한 함수의 주소를 대입

그리고 이 디스크립터 뒤에는 널 디스크립터가 들어가며 INT 배열의 크기와 IAT 배열의 크기는 같아야함을 보여줌.

Comments