망각에 재주 있는 나를 위해 기록하는 곳.

[리버싱] IAT 본문

리버싱

[리버싱] IAT

baobabtree 2022. 5. 3. 04:53

윈도우에서는 DLL(Dynamic Linking Library)이라는 개념을 사용하고 있다. 말 그대로 프로그램에서 필요한 라이브러리를 사용 시점에 동적으로 연결한다는 얘기다. 예전에는 프로그램이 컴파일 시점에 모든 필요한 기능을 실행 파일 안에 집어넣었지만, 시스템에 지원하는 기능이 다양해지고 부피가 커짐에 따라서 이러한 방식은 비효율적인 것이 되었다.

 

IAT(Import Address Table)는 실행 파일(PE 파일) 안에 라이브러리에서 어떤 함수를 가져다 쓰는지 기록해놓은 정보이다. 로더는 PE 파일을 메모리로 로딩할 때 IAT에 기록된 API 이름을 참조해서 프로그램이 사용할 수 있는 주소를 찾아 IAT 안에 API를 가리키는 주소를 적어 놓는다. 코드에서 라이브러리를 참조하는 부분은 IAT 내부에 있는 함수 주소를 사용하고 있다.

 

앞에서 봤듯이 IAT는 'IMAGE_NT_HEADERS' -> 'IMAGE_OPTIONAL_HEADERS' -> 'IMPORT Table'에서부터 시작한다. IMPORT Table 내부에는 IMPORT Directory Table이 어디에 있는지 주소를 가지고 있다. IMAGE_IMPORT_DEXCRIPTOR 구조체 배열로 이루어진 IMPORT Directory Table은 내부에 IAT에 대한 정보가 저장되어 있다.

 

IMPORT Directory Table

IMPORT Directory Table을 구성하는 IMAGE_IMPORT_DESCRIPTOR 구조체의 개수는 참조하는 DLL의 개수와 같다. abexcm1.exe 파일은 KERNEL32.dll과 USER32.dll 두 개의 DLL을 참조하고 있기 때문에 2개의 값이 들어 있는 IMAGE_IMPORT_DESCRIPTOR 구조체와 1개의 NULL로 채워진 구조체로 이루어져 있다. PE 헤더에 IMPORT Directory Table의 크기가 명시되어 있지 않기 때문에 NULL로 채워진 구조체를 보고 IMPORT Directory Table의 마지막인지 판단할 수 있다.

 

IAT와 INT

IMPORT Directory Table은 INT(Import Name Table)와 IAT(Import Address Table)에 대한 정보를 가지고 있다. INT와 IAT는 PE 파일에서 사용하는 외부 라이브러리를 기록한 핵심 영역이다. INT와 IAT는 동일하게 IMAGE_THUNK_DATA32 구조체로 이루어져 있으며, PE 파일 상태에서는 INT와 IAT에 같이 데이터가 들어가 있다. 위 그림에서 볼 수 있듯이 참조하는 함수 이름을 가리키고 있다.

 

참조하는 함수 이름

위 그림에서 보면 IAT 테이블에 주소 '0000307C', '0000308C', '0000309A'가 들어 있는 것을 확인할 수 있고, INT 테이블에서도 같은 내용을 확인할 수 있다. 이제 해당 주소가 실제로 어떤 데이터를 가리키고 있는지 확인해보면, IMPORT Hint/Names 영역을 살펴보면 실제 참조하는 함수의 이름의 ASCII 코드 값이 들어가 있다. 함수 이름이 알파벳으로 들어가 있고 이름이 끝나는 지점은 NULL(00)로 표시하고 있다.

 

*메모리 로딩 후 IAT 상태(사진첨부)

PE 파일 상태에서는 IAT와 INT가 같은 값을 가지고 있지만, 로더가 PE 파일을 메모리로 로딩할 때 실제 참조해야 하는 함수의 주솟값을 가지고 와서 IAT에 저장한다. PE 파일 내부에 있는 함수 이름을 가리키던 IAT 내부의 값은 함수를 자리키는 주솟값으로 변경된다.

 

위 그림에서 IAT의 RVA 값은 Image Base값(40000000)과 결합해서 디버거의 메모리 영역에서 어떤 값이 저장되어 있는지 확인할 수 있다. 주소 '00003050'에는 주소 '758AEF5D'가 저장되어 있고 주소 '0003054'에는 주소 '758979D8'이 저장되어 있다. 마지막으로 주소 '0000305C'에는 주소 '76ECFDE6'이 저장되어 있다.

 

반면에 INT에는 PE 파일에 저장된 값이 그대로 저장된 것을 확인할 수 있다.

*코드에서 참조하는 외우 라이브러리(사진첨부)

 

실제 코드에서 참조하는 라이브러리 값도 확인할 수 있다. 디버거 코드 영역에서 주소 '00401055'를 보면 코드 'JMP DWORD PTR DS:[<KERNEL32.GetDriveType]'을 확인할 수 있는데, 외부 라이브러리를 참조하는 코드이다. 리버싱 과정에서 메모리 덤프를 사용하는 경우가 많은데, 그때 IAT가 많이 손상되고 IAT를 복구하려면 코드에서 실제 참조하는 외부 라이브러리 주소를 확인해야 하는 경우가 많다. 그때 코드에서 'FF25'를 검색하면 쉽게 찾을 수 있다.

 

IAT 구조 정리

IAT를 다시 한번 정리하면, PE 헤더에 'IMAGE_NT_HEADERS' -> 'IMAGE_OPTIONAL_HEADER' -> 'IMPORT Table' 부분에 IMPORT Address Table 정보를 담은 IMPORT Directory Table 위치를 가리키는 주소가 들어 있다. IMPORT Directory Table에서 IMPORT Address Table과 IMPORT Name Table의 주소를 찾을 수 있다. IMPORT Address Table과 IMPORT Name Table에는 같은 정보, 참조하는 API 이름이 들어가 있지만, PE 파일이 메모리로 로딩되는 시점에 로더는 참조하는 API의 주소를 찾아서 IMPORT Address Table에 넣어준다.

'리버싱' 카테고리의 다른 글

[리버싱] 어셈블리 기초 정리  (0) 2022.05.06
[리버싱] 섹션 헤더, 섹션 데이터  (0) 2022.05.03