Reversing
PE 파일은 어떤 라이브러리를 임포트하고 있는지 IMAGE_IMPORT_DESCRIPTOR 구조체에 명시하고 있다.
import : 라이브러리에게 서비스(함수를 제공받는 일)
Export : 라이브러리 입장에서 다른 PE 파일에게 서비스(함수)를 제공하는 일
IMAGE_IMPORT_DESCRIPTOR 주요 멤버(RVA) :
OriginalFirstThunk : INT(Import Name Table)의 주소(RVA)
Name : 라이브러리 이름 문자열의 주소(RVA)
FirstThunk : IAT(import address table)의 주소(RVA)
*table은 배열을 의미
NT header - IMAGE_OPTIOANL_HEADER32.DataDirectory[1].VirtualAddress = IMAGE_IMPORT_DESCRIPTOR 주소
IMAGE_OPTIOANL_HEADER32.DataDirectory [1]의 첫 번째 4바이트는 주소(RVA) , 뒤에 4바이트는 size이다.
첫 4바이트 주소를 RAW로 변환해서 가면 IMAGE_IMPORT_DESCRIPTOR 배열 행태로 존재
name 멤버에는 임포트된 함수가 소속된 라이브러리 파일 이름 문자열 포인터. 주소 raw로 가보면 like comdlg32.dll 이렇게 있음
OriginalFirstThunk( INT {import name table} ) : INT는 임포트 하는 함수의 정보(ordinal, name)담긴 구조체 배열
INT주소로 가보면 IMAGE_IMPORT_BY_NAME 구조체를 가리키고 있음(이름을 가리키고 있다는 말임)
첫번째 배열(4 바이트) 주소로 가보면 api함수 이름이 나타남 첫 2바이트 값은 Ordinal로 라이브러리에서 함수의 고유번호
FirstThunk - IAT를 통해 RAW로 가보면 comdlg32.dll 라이브러리에 해당하는 IAT배열 영역이 나온다. INT와 마찬가지로 구조체 포인터 배열 형태로 되어 있으며 배열은 NULL로 끝난다. IAT의 원소 값은 하드코딩되어있는데 의미 없으면 메모리에 파일이 로딩될 때 이 값은 정확한 주소 값으로 대체된다.
windows 시스템 dll파일들(kernel32 ,user32 , gdi32 등은 자신만의 고유한 ImageBase가 있어서 DLL Relocation이 발생하지 않습니다.
EAT(Export Address Table) 라이브러리 에서 제공하는 함수를 다른 프로그램에서 가져다 사용할 수 있도록 해준다.
EAT를 통해서만 해당 라이브러리에서 익스포트하는 함수의 시작 주소를 정확히 구할 수 있다. IMAGE_EXPORT_DIRECTORY 구조체는 하나만 존재한다.
dll파일 실행
NT header - IMAGE_OPTIOANL_HEADER32.DataDirectory[0].VirtualAddress = IMAGE_EXPORT_DESCRIPTOR 주소
IMAGE_EXPORT_DESCRIPTOR주요 멤버
NumberOfFunctions // 실제 Export 함수 개수
NumberOfNames // Export 함수중에서 이름을 가지는 함수 개수
AddressOfFunctions // Export 함수 주소 배열(EAT)
AddressOfNames // 함수 이름 주소 배열
AddressOfNameOrdinals // Ordinal 주소 배열
GetProcAdress( )동작 원리(API가 함수 이름을 가지고 함수 주소를 얻어내는 과정)
AddressOfNames에 가서 strcmp로 원하는 함수이름을 찾고 해당 인덱스 저장(name_index)
AddressOfNameOrdinals에 가서 name_index로 해당 Ordinal 찾음
AddressOfFunctions 멤버를 통해 EAT에 가서 ordinal 배열 인덱스로 원하는 함수의 시작 주소를 얻음.
ordinal로만 익스포트된 함수는 ordinal값에서 IMAGE_EXPORT_DIRECTORY.Base 멤버를 뺀 값을 AddressOfFunctions의 인덱스로 하여 함수 주소를 찾을 수 있음.
AddressOfNameOrdinals 멤버는 2바이트 크기의 배열임