목차
IAT 로딩 과정
1. IID의 Name 멤버를 읽어서 라이브러리의 이름 문자열을 얻는다 2. 해당 라이브러리를 로딩한다. 3. IID의 OriginalFirstThunk 멤버를 읽어서 INT 주소를 얻는다. 4. INT에서 배열의 값을 하나씩 읽어서 해당 IMAGE_IMPORT_BY_NAME주소(RVA)를 얻는다. 5. IMAGE_IMPORT_BY_NAME의 Hint or Name을 이용해 해당 함수의 시작 주소를 얻는다. 6. IID의 FirstThunk 멤버를 읽어서 IAT의 주소를 얻는다. 7. 해당 IAT 배열 값에 위에서 구한 함수 주소를 입력한다. 8. INT가 끝날 때까지(NULL을 만날 때까지) 4~7 과정을 반복한다. |
IMAGE_OPTIONAL_HEADER(NT HEADER의 구조체 멤버)에서 Import Directory의 RVA 값을 얻었다.
RVA 값은 1A3B0, 크기는 1A4다.
비례식을 이용해서 RAW를 구해보자
비례식 : RAW=RVA-VA+PointerToRawData
RAW = 1A3B0-1A000+16000 = 163B0 => Import Directory 시작 offset
163B0 + 1A4 = 16554 ⇒ image_import_descriptor 끝나는 부분
163B0으로 가면 이런 값들이 있다. 이 값들은 IMAGE_IMPORT_DESCRIPTOR 구조체 배열로 이루어진 IMPORT Directory Table이다.
File Offset | Member | RVA | RWA |
163B0 | OriginalFirstThunk(INT) | 1A554 | 16554 |
163B4 | TimeDataStamp | ||
163B8 | ForwarderChain | ||
163BC | Name | 1A982 | 16982 |
163C0 | FirstThunk(IAT) | 1A000 | 16000 |
Name
=> 1. IID의 Name 멤버를 읽어서 라이브러리의 이름 문자열을 얻는다
INT
=> 3. IID의 OriginalFirstThunk 멤버를 읽어서 INT 주소를 얻는다.
INT의 주소인 16554는 위의 표를 통해서 얻었다.
16554에 가보니 value값이 함수의 이름으로 보인다.
1A91E의 raw값은 1691E다.
해당 주소로 가보니 함수의 이름을 확인할 수 있다.
=> 4. INT에서 배열의 값을 하나씩 읽어서 해당 IMAGE_IMPORT_BY_NAME주소(RVA)를 얻는다.
, 5. IMAGE_IMPORT_BY_NAME의 Hint or Name을 이용해 해당 함수의 시작 주소를 얻는다.
위에서 구한 표를 보면 IAT의 RAW값이 16000이다.
=> 6. IID의 FirstThunk 멤버를 읽어서 IAT의 주소를 얻는다.
EAT 로딩 과정
1. AddressOfNames 멤버를 이용해 '함수 이름 배열'로 이동한다. 2. '함수 이름 배열'은 문자열 주소가 있으므로, 문자열 비교를 통하여 원하는 함수의 이름을 찾는다. 3. AddressOfNAmeOrdinals멤버를 이용하여 'ordinal' 배열로 이동한다. 4. 'ordinal 배열'에서 name_index를 이용하여 해당 ordinal 값을 찾는다. 5. AddressOfFunctions 멤버를 이용하여 함수 주소 배열(EAT)로 이동한다. 6. EAT에서 ordinal을 배열 인덱스로 해 원하는 함수의 시작 주소를 얻는다. |
kernel32.dll을 이용해 실습을 진행했다.
RVA는 92250
RAW = 92250 - 80000 + 65000 = 77250
77250에 가면 IMAGE_EXPORT_DIRECTORY 구조체 배열이 있다.
File Offset | Member | RVA | RWA |
7726C | AddressOfFunctions | 92278 | 77278 |
77270 | AddressOfNames | 93B84 | 78B84 |
77274 | AddressOfNameOrdinals | 95490 | 7A490 |
1. AddressOfNames 멤버를 이용해 '함수 이름 배열'로 이동한다.
78B84로 이동하니 함수 이름들이 있는 것을 볼 수 있다.
저기서 96182 => raw로 7B182인 주소로 가보자.
표에서 확인한 함수의 이름이 있는 것을 확인할 수 있다.
=> 2. '함수 이름 배열'은 문자열 주소가 있으므로, 문자열 비교를 통하여 원하는 함수의 이름을 찾는다.
3. AddressOfNAmeOrdinals멤버를 이용하여 'ordinal' 배열로 이동한다.
미리 얻은 RWA인 7A490으로 가보자.
가보면 이런 값들이 나온다.
4. 'ordinal 배열'에서 name_index를 이용하여 해당 ordinal 값을 찾는다.
현재 함수는 인덱스가 0이라서 ordinal 값은 3이다.
5. AddressOfFunctions 멤버를 이용하여 함수 주소 배열(EAT)로 이동한다.
AddressOfFunctions의 RAW는 77278이다.
6. EAT에서 ordinal을 배열 인덱스로 해 원하는 함수의 시작 주소를 얻는다.
4번과정에서 얻은 ordinal 값을 배열 인덱스로 사용하면 RVA는 9619A다.
'Study > 리버싱' 카테고리의 다른 글
[3] UPX 패킹과 언패킹 (0) | 2020.11.01 |
---|---|
[3] ㄷㄹㅎ 4,5 (0) | 2020.10.25 |
[2] 2주차 과제 (0) | 2020.09.20 |
[1] 32bit와 64bit의 함수 호출 규약 (1) | 2020.09.14 |
[0] 32bit 레지스터와 스택 구조, 스택 프레임 (0) | 2020.09.14 |