적고보니 이해가 좀 되는 것 같다.. 결론은 IMAGE_NT_HEADERS의 필드였던 OptionalHeader의 필드인 DataDirectory 배열의 첫번째 DataDirectory[1]이고, 이게 가리키는게 IMAGE_IMPORT_DESCRIPTOR의 배열인것이다. 그리고 IMAGE_IMPROT_DESCRIPTOR의 INT를 보고 실제 함수의 주소를 찾아서 IAT에 쓰는 과정이 dll의 주소를 메모리에 올리는 과정이다.
0. IAT
0-0 설명
Import Address Table
IAT를 이해하기 위한 사전 지식.. 32bit Windows 환경으로 넘어오면서 메모리나 디스크 등의 자원 활용의 낭비를 막기 위해 DLL이 생겨났다. DOS 시절의 프로그램들은 특정 함수를 사용하기 위해 해당 라이브러리의 바이너리를 직접 프로그램에 박아버리는 방식으로 사용했기에 새로운 구조의 OS가 생성되면서 호환성 문제도 생기고, 앞서 말한 자원의 낭비가 생긴다.
이런 문제를 해결하기 위해 Dynamic Linked Library가 생긴 것이다. 프로그램에 직접 삽입하는 것이 아니라, 메모리에 라이브러리를 올려놓으면 그 라이브러리를 사용하는 여러 프로세스들이 공유를 할 수 있는 것이다.
0-1 DLL 로딩 방식
Explicit Linking
사용하는 순간에 로딩하고, 사용이 끝난 후에는 메모리에서 해제
Implicit Linkng
프로그램이 시작될때 같이 메모리에 올라가고 프로그램이 종료될때 같이 해제됨
IAT는 Implict Linking과 관련이 있다.
내가 밑에 실습에 썼던 바이너리를 ollydbg에 올려서 확인한 내용이다.
보면 CALL을 하는데 DS:[&KERNEL32.GetCommandLineA]에 있는 값을 호출한다. 직접 호출하는것이 아니라.. 그래서 아래 자세한 내용을 보면 실제 함수를 호출할때 참조하는 주소는 0x407000이고, 그 주소가 가리키는 값이 실제 GetCommandLineA의 주소(0x761E1EE0)이다.
결론은 앞서 말한 환경 종속성을 피하고 범용적으로 사용이 가능하도록 하기 위해 함수를 호출할 때 위와 같이 테이블을 참조하여 사용하게 한것이다. 실제 함수의 주소는(IAT의 경우) 프로그램이 시작될 때 dll도 메모리에 로딩이 되니까 그 시점에 호출할 함수의 주소가 결정이 된다. 이때 앞의 예처럼 0x407000 위치의 값에 함수의 주소를 넣으면 되는 것이다.
이렇게 실행중에 동적으로 라이브러리 함수들의 주소를 쫓아가야하고 그렇기 때문에 IAT나 EAT가 필요한 것이다.
1. IMAGE_IMPORT_DISCRIPTOR
1-0. 구조체 설명
앞에 적은 것 처럼 dll 같은 경우 프로그램이 어떤 라이브러리를 사용할지(import 할지) 프로그램이 로딩이 되어야 주소를 알 수 있다. 어떤 라이브러리를 쓰는지가 IMAGE_IMPORT_DESCRIPTOR에 명시되어있다.