이번 리버싱 스터디 6주차에는 16-17강을 듣고 내용을 정리한 후 어려웠던 부분을 공유하며 질문을 통해 해결하는 시간을 가졌다.
참고한 유튜브 영상:
https://www.youtube.com/playlist?list=PLY12b4RRLcSdsxgVvTW3mnNzMjVrd8JhO
<16강: IAT>
- IAT: 어떤 프로그램에 어떤 라이브러리에 어떤 함수를 사용하고 있는지 기술한 테이블, 배열이다.
- DLL (Dynamic Linked Library. 동적 연결 라이브러리)
- MS-DOS 시절: 16비트 DLL 없었고 라이브러리만 있었음단점: 메모리 낭비 큼, 효율 안 좋음, 같은 작업 반복
- ex. printf() → stdio.h 바이너리 코드(2진수) 코드를 긁어와서 필요한 프로그램에 삽입
- window는 멀티 태스킹 지원해서 그게 안됨.
- DLL은 동적으로 라이브러리 함수를 가져와서 연결 (파일 형태임)
- DLL 초기 구상
- 프로그램에 라이브러리 포함x. 별도의 파일(DLL)을 구상하여 필요할 때마다 호출
- 일단 한 번 로딩된 DLL의 코드 리소스를 메모리 매핑 기술로 다 같이 나누어 쓰자
- 라이브러리가 업데이트 했을 때 해당 DLL 파일만 교체하면 되어서 간편하다.
- DLL 로딩 방식 2가지
- explicit linking(명시적): 프로그램에서 사용되는 순간 연결(로딩)하고 사용 후 메모리에서 해제
- implicit linking(암시적): 프로그램이 실행될 때 같이 연결(로딩)되어 프로그램 종료 시 메모리에서 해제
- Kernel: OS admin 같은. 모든 것을 관리한다.
- DLL 재배치: 어떤 파일의 IB가 10000인데 로딩 하려고 보니 다른 파일이 그 자리를 차지하고 있다면 다른 빈공간을 찾아서 로딩한다.
<17강: IAT(2)>
- PE파일은 자신이 어떤 라이브러를 호출하고 있는지 IAT구조를 통해서 명시하고 있다.
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics;
DWORD OriginalFirstThunk;
// INT(Import Name Table) address (RVA)
};
DWORD TimeDateStamp;
DWORD ForwarderChain;
DWORD Name;
DWORD FirstThunk;
} IMAGE_IMPORT_DESCRIPTOR;
// library name string address (RVA)
// IAT(Import Address Table) address (R
typedef struct _IMAGE_IMPORT_BY_NAME {
WORD Hint; //함수의 고유번호
BYTE Name[1]; //함수의 이름
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
아래의 모든 주소는 RVA이다.
- OriginalFirstThunk = INT(Import Name Table) 주소
- Name = Libray 이름 문자열 주소
- FirstThunk = IAT 주소를 가리킴
INT 와 IAT는 LongType 배열이고 NULL로 끝난다. 둘의 값은 같아야 한다.
IAT 입력 순서
- IMAGE_IMPORT_DESCRIPTOR의 Name 멤버를 읽고 나서 library 이름 문자열(“Kernel32.dll”)을 읽는다
- 해당 라이브러리를 로딩한다 → LoadLibrary(“Kernel32.dll”)
- IMAGE_IMPORT_DESCRIPTOR의 OriginalFirstThunk 멤버를 읽어서 INT 주소를 얻는다.
- 얻은 주소를 INT에서 읽어서IMAGE_IMPORT_BY_NAME 주소(RVA)를 얻는다
- IMAGE_IMPORT_BY_NAME에서 Hint 또는 Name항목->함수의 시작주소를 얻는다 (GetProcAddress() 함수로)
- IAT 배열값에 4번의 함수주소를입력
- INT NULL 일 때까지 4-6 반복
IMAGE_OPTIONAL_HEADER32.DataDirectory[1].VirtualAddress-> IMAGE_IMPORT_DESCRIPTOR
- 라이브러리 이름(Name) Name항목은 임포트 함수가 라이브러리에 파일 이름 문자열 포인터이다.
⇒ IAT 입력순서 1 - OriginalFirstThunk - INT(Import Name Table) INT = 임포트 하는 함수의 정보(Ordinal)가 담긴 구조체 포인터 배열이다. 이 정보는 필요로 하는 프로세스 메모리에 로딩된 라이브러리에서 해당 함수의 시작주소를 정확히 구할 수 있다. → IMAGE_IMPORT_BY_NAME(INT의 구조체)
- Ordinal 고유번호. 함수들이 변수들을 구별하기 위한 번호이다. IMAGE_IMPORT_BY_NAME은 DLL에서 함수를 호출할 때 필요한 정보(이름, 고유번호)를 담고 있다. 그 정보를 토대로 주소를 서치한다.
⇒ IAT 입력 순서 2-5 - FirstThunk - IAT(Import Address Table) FirstThunk는 IAT를 가리키는 포인터이다.
최종 정리를 해보자면:
- OriginalFirstThunk는 INT를 가리킨다.
- INT와 IMAGE_IMPORT_BY_NAME의 차이점:
- INT - 함수 이름 & 고유번호를 담는다.
- IMAGE_IMPORT_BY_NAME - 해당 함수에 대한 자세한 정보를 담는다.
- NAME과 IMAGE_IMPORT_BY_NAME의 차이점:
- NAME - 가져와야하는(필요한) DLL 파일의 이름을 가리킨다.
- IMAGE_IMPORT_BY_NAME - DLL에서 내보내야하는 함수의 이름과 고유번호 값을 가지고 있는 구조체이다.
- IAT: 실행파일(ex. DLL)이 다른 모듈(exe)에서 사용하는 함수를 가리키는 포인터 배열이다. 즉, 모든 함수 주소들의 집합.
'2. Reversing (리버싱)' 카테고리의 다른 글
[2024.09.21] 리버씽씽이_1주차 활동 (5) | 2024.09.27 |
---|---|
[2024.05.25] 리버씽씽카 7주차 활동 (0) | 2024.05.24 |
[2024.05.11] 리버씽씽카 5주차 활동 (0) | 2024.05.13 |
[2024.04.06] 리버씽씽카 4주차 활동 (0) | 2024.05.04 |
[2024.03.30] 리버씽씽카 3주차 활동 (0) | 2024.03.30 |