PE IAT 실습

notepad.exe를 이용하여 PE 구조를 파악한다.

notepad.exe
0.06MB

먼저 IMAGE_OPTIONAL_HEADER의 DataDirectory 구조체의 배열 정보를 확인합니다.

RVA = 7604 인걸 알 수 있쥬?

실제 해당주소에 들어가 보면 앞쪽이 IMPORT Table의 RVA 뒤쪽이 Size입니다.

 

 

이후에 RVA를 알기 때문에 offset(RAW)을 구합니다.

7604 - 1000 + 0400 = 6A04 (text 섹션임)

파일에서 6A04을 보면 다음과 같습니다.

IID의 구조체 배열

블록으로 잡힌 부분이 전부 IID의 구조체 배열입니다.

RAW 값을 구해보면 다음과 같아집니다.

Description RAW
INT 00006D90
Time Date Stamp -
Forwarder Chain -
Name 00006EAC
IAT 000006C4

그럼 이제 하나씩 따라가 보자!

 

#1. Name 00006EAC

comdlg32.dll 문자열이 보인다!

 

#2. INT 00006D90

INT는 임포트 하는 함수의 정보가 담긴 구조체 포인터 배열입니다. 이 정보로 프로세스 메모리에 로딩된 라이브러리에서 해당 함수의 시작 주소를 알아낼 수 있습니다.

주소 값 하나하나가 각각의 IMAGE_IMPORT_BY_NAME 구조체를 가리키고 있습니다.

제일 첫 번째 배열 값인 7A7A를 따라가 봅시다.

 

#3. IMAGE_IMPORT_BY_NAME

RVA:7A7A를 RAW로 변환합시다.

7A7A+1000-0400 = 6E7A

 

제일 앞의 '..'(000F)는 라이브러리에서 함수의 고유번호라고 합니다. 이 Ordinal 뒤로 함수 이름 문자열이 보이죠?

여기까지 봤을 때 INT는 IMAGE_IMPORT_BY_NAME 구조체의 포인터 배열임을 알 수 있습니다.6

함수의 이름은 'PageSetupDlg\(?)' 이네요.

 

#4. IAT 000006C4

다음 그림에서의 블록영역이 'comdlg32.dll' 라이브러리에 해당하는 IAT 배열 영역입니다.

IAT의 첫 번째 원소값인 '76324906'은 의미 없는 값이고 메모리에 로딩될 시 정확한 주소값으로 대체됩니다.

 

그래서 ImageBase 01000000 + 000006C4 = 010006C4를 디버거로 열어보면

pagesetup 함수 시작이 나타나게 됩니다. 그값은 94269677 인데 실행과정에서 이값이 왜바뀌는지는 잘모르겠습니다.

=> OS에 따라서 바뀐다고 함.

 

아무튼 디버깅 실행후에 값을 010012C4에 값을 살펴보면 77962694 이고,

77962694로 바꼈음

77962694로 이동을 했을 시

짜잔!

이렇게 PageSetupdlg 함수의 시작부분을 확인할 수 있습니다.

 

헥사값이 바뀌는건 OS때문에 바뀌는거라고 생각됩니다...

어찌됐건 함수의 시작부분을 찾았다 !

 

PE EAT 실습

 

IAT를 실습했으니 이번엔 EAT를 실습해보자!

Windows OS에서 라이브러리는 다른 프로그램에서 불러 쓸 수 있도록 관련 함수를 모아놓은 파일을 의미.(SYS/DLL)

그 중 kernel32.dll 파일이 가장 핵심적인 라이브러리 파일이라고 할 수 있습니다.

 

EAT는 저번에도 봤었다시피 라이브러리에서 제공하는 함수를 다른 프로그램에서 가져다가 쓸 수 있도록 해주는 핵심 메커니즘 입니다. => EAT를 통해서만 해당 라이브러리에서 익스포트하는 함수의 시작 주소를 정확히 구별할 수 있음

 

앞의 IAT와 마찬가지로 IMAGE_OPTIONAL_HEADER의 DataDirectory에서 Export 정보를 저장해놓고 있음. 

 

kernel32.dll
1.17MB

해당 주소로 이동해보자. 00000168

IAT와 같이 앞쪽 4바이트가 RVA 뒤쪽 4바이트가 Size의 멤버임을 볼 수 있음.

 

RVA값이 262C 이므로 RAW를 계산해보면,

262C - 1000 + 0400 = '1A2C' 입니다.

 

다음으로 IMAGE_EXPORT_DIRECTORY의 구조체는 다음과 같습니다.

typedef struct _IMAGE_EXPORT_DIRECTORY {

DWORD Characteristics

DWORD TimeDateStamp

WORD MajorVersion

WORD MinorVersion

DWORD Name

DWORD Base

DWORD NumberOfFunctions

DWORD NumberOfNames

DWORD AddressOfFunctions // 함수 주소 배열(EAT)

DWORD AddressOfNames //함수명 배열

DWORD AddressOfNameOrdinals // 함수 서수 배열

} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY

그럼 중요한 멤버들을 정리해보면,

항목 의미
NumberOfFunctions 실제 Export 함수 개수
NumberOfNames Export 함수 중에서 이름을 가지는 함수 개수 (<=NOF)
AddressOfFunctions Export 함수 주소 배열 (배열 원소 개수 = NOF)
AddressOfNames 함수 이름 주소 배열 (배열 원소 개수 = NON)
AddressOfNameOrdinals Ordinal 배열 (배열 원소 개수 = NON)

그렇쥬 ??

 

라이브러리에서 함수 주소를 얻는 API는 GetProcAddress() 입니다. 이 api가 EAT를 참조해서 원하는 API 주소를 획득함.

그럼 EAT를 정복하러 가즈아!

 

GetProcAddress() 동작 원리

1. AddressOfNames 멤버를 이용해 '함수 이름 배열'로 갑니다.

2. '함수 이름 배열'은 문자열 주소가 저장되어 있고, strcmp를 통하여 원하는 함수 이름을 찾습니다. (name_index)

3. AddressOfNameOrdinal 멤버를 통해 'ordinal 배열'로 갑니다.

4. 'ordinal 배열'에서 name_index로 해당 ordinal 값을 써치합니다.

5. AddressOfFunctions 멤버를 이용해 '함수 주소 배열(EAT)'로 갑니다.

6. '함수 주소 배열(EAT)'에서 아까 구한 ordinal을 배열 인덱스로 하여 원하는 함수의 시작주소를 얻습니다.

 

이 순서 그대로 실습 해보겠습니다.

 

#1. 함수 이름 배열

AddOfNames 멤버의 RVA = 3538

RAW = 3538 -1000+0400 = 2938 이를 Hex Editor로 살펴보면 다음과 같습니다.

 

 

#2. 원하는 함수 이름 써치

 

이 부분들이 이제 4바이트의 RVA로 이루어진 배열입니다. 배열 원소의 개수는 NumberOfName(3B9) 겠죠??

저 모든 RVA 값들을 하나하나 따라가면 함수 이름 문자열이 나오게 됩니다.

 

3번째 원소값을 볼까요? (4BB3 -> RAW : 3FB3)

보이시죠 AddAtom ㅎㅎ

* OS에 따라서 나뭇잎책과 값이 다를순 있으나 실습은 똑같음

 

'AddAtom'은 AddOfNames의 RVA들 중 3번째에 속해있고 배열 인덱스로는 '2'가 됩니다.

 

#3. Oridnal 배열

 

이제 'AddAtom' 함수의 Oridnal 값을 알아냅니다. AddressOfOrdinals 멤버값은 441C -> RAW : 381C 입니다.

다음과 같이 2바이트의 ordinal로 이루어진 배열이 나타나게 됩니다. 

 

#4. ordinal

 

아까 구했던 인덱스 '2'를 위의 Ordinal 배열에 적용시키면 Oridianl(2)를 구할 수 있습니다.

AddressOfNameOrdinal[index] = ordinal ( index = 2, ordinal = 2)

 

#5. 함수 주소 배열 - EAT

이제 마지막으로 AddAtom의 실제 함수 주소로 찾아갈 수 있습니다. AddressOfFunctions의 값은 2654 -> RAW : 1A54 입니다.

 

해당 주소를 보면 다음과 같이 4바이트 RVA 배열이 나타나게 됩니다. 이게 바로 함수의 주소들 입니다.

 

#6. AddAtom 함수 주소

 

함수 주소를 얻기위해 Ordinal을 index로 적용하면, 다음과 같이 RVA = 326D9를 얻을 수 있습니다.

현재 저의 kernel32.dll의 imagebase = 7C800000 이기 때문에 실제주소 VA = '7C8326D9' 입니다

이 값을 디버거에서 확인해보면 'AddAtom'이 잇겠지 ??

없다고 한다...

 

 

없어서 imagebase부터 살펴보니 pe viewer로 봤을때와 디버거에 올라갔을때 imagebase가 틀려짐을 확인했다.

 

틀려짐... kernel32.dll의 imagebase = 76FF0000 으로 바뀌었다.

여기에 RVA를 더해도 찾을수가 없었다.... 왜죠 ?

왜 여기가있죠????

모르겠다능  775e26d9

'Reversing' 카테고리의 다른 글

리버싱 8  (0) 2019.04.09
리버싱 7  (0) 2019.04.05
PE file(3)  (0) 2019.04.03
PE File(2)  (0) 2019.04.03
PE File(1)  (0) 2019.04.02

 앙 규무링^^ 

 

 

PE file(3)

이번에는 직접 실습을 통해서 PE file의 IAT 입력 순서를 볼 예정입니다 :3

PE file(1), (2)에 이어서 봐야 이해됨 그럼 출바아알

 

IMAGE_IMPORT_DESCRIPTOR

PE file은 자신이 어떠한 라이브러리를 IMPORT하고 있는지 위의 구조체에 명시하고 있습니더.

구조체의 코드는 다음과 같습니다.

 

typedef struct _IMAGE_IMPORT_DESCRIPTOR {

    union {

        DWORD   Characteristics;            

        DWORD   OriginalFirstThunk;       // INT(Import Name Table) address (RVA)

    };

    DWORD   TimeDateStamp;

    DWORD   ForwarderChain; 

    DWORD   Name;                         // library name string address (RVA)

    DWORD   FirstThunk;                   // IAT(Import Address Table) address (RVA)

} IMAGE_IMPORT_DESCRIPTOR;



typedef struct _IMAGE_IMPORT_BY_NAME {

    WORD    Hint;                         // ordinal

    BYTE    Name[1];                      // function name string

} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; 

일반적으로 여러 개의 라이브러리를 임포트하기 때문에 라이브러리 개수만큼 위 구조체의 배열 형식으로 존재하며, 구조체 배열의 마지막은 null로 끝납니다.

ㄹㅇ임

- 구조체 중요 멤버들(주소들은 RVA 값임)

항목 의미
OriginalFirstThunk INT(Import Name Table)의 주소
Name Library 이름 문자열의 주소
FirstThunk IAT(Import Address Table)의 주소

그렇다면 이제 PE 로더가 임포트 함수 주소를 IAT에 입력하는 기본적인 순서!

 

IAT 입력 순서 :3

1. IID의 Name 멤버를 읽어서 라이브러리의 이름 문자열을 찾아냄 (ex : 'KERNEL32.dll')

2. 해당 라이브러리를 LoadLibrary() 함수를 써서 로딩함. 

-> LoadLibrary('KERNEL32.dll')

3. IID의 OriginalFirstThunk 멤버를 읽어서 INT 주소를 얻음.

4. 그 INT 주소에서 배열의 값을 한개씩 읽어들이면서 해당 IMPORT_BY_NAME 주소를 얻어냄

5. IMPORT_BY_NAME의 hint/name 항목을 이용해 해당 함수의 시작주소를 얻음

-> GetProcAddress('GetCurrentThreadId')

6. IID의 FisrtThunk(IAT)를 읽어서 IAT의 주소를 얻어낸다.

7. 해당 IAT 배열 값에 위에서 구한 함수 주소를 입력.

8. INT가 NULL을 만날 때까지 위의 4~7 과정을 반복함.

 

자... 무슨말이냐... Name을 읽어 dll 이름을 획득 -> 그 이름을 LoadLibrary() 함수 안에 넣어서 dll 핸들 획득 -> IID에서 INT를 획득하고 거기서 하나씩 읽어내면서 IBN 획득 -> IBN의 hint/name과 dll핸들(아까획득)을 이용해 함수를 돌림

GetProcAddress() 여기서 내가 원하는 함수의 시작주소를 얻게됨 -> IID에서 IAT 주소를 획득 -> 끝으로 IAT 배열값 위에서 구해놨던 함수의 시작주소를 입력함 -> 이렇게 NULL을 만날때까지 모든 dll에 대해서 수행

 

휴... 끝

 

notepad.exe를 이용한 실습을 진행해보자.

-

 

 

'Reversing' 카테고리의 다른 글

리버싱 7  (0) 2019.04.05
리버싱 6  (2) 2019.04.04
PE File(2)  (0) 2019.04.03
PE File(1)  (0) 2019.04.02
리버싱 5  (0) 2019.04.02

 앙 귬모띠~ 

 

 

PE File(2)

어제에 이어서 PE File 공부를 마저해보자!

어제는 NT Header에 대해서 안에 멤버들을 들여보다가 Image File Header 까지 봤었다.

오늘은 Image Optional Header로 가자

 

우선 까먹었을것 같으니 

가즈아

 

어제껄 복습한다.

다음의 블록이 NT Heaer - image file header 부분

 

offset		value		desc
---------------------------------------
000000DC	014c		machine
000000DE	0004		numeber of sections
000000E0	559EA6FF	time date stamp
000000E4	00000000	offset to symbol table
000000E8	00000000	number of symbols
000000EC	00E0		sie of optional header
000000EE	0102		characteristic
						IMAGE_FILE_EXECUTABLE_IMAGE
						IMAGE_FILE_32BIT_MACHINE

view 확인결과 실제와 동일 ㅋ

NT Header - image file header까지 보았다.

이제 구조체중에 가장 큰 NT Header - Optional Header를 살펴보자.

 

[IMAGE_OPTIONAL_HEADER32]

typedef struct _IMAGE_OPTIONAL_HEADER {  
 
   /* Standard fields */
   WORD  Magic; /* 0x10b or 0x107 */ /* 0x00 */
   BYTE  MajorLinkerVersion;
   BYTE  MinorLinkerVersion;
   DWORD SizeOfCode;
   DWORD SizeOfInitializedData;
   DWORD SizeOfUninitializedData;
   DWORD AddressOfEntryPoint;        /* 0x10 */
   DWORD BaseOfCode;
   DWORD BaseOfData;
 
   /* NT additional fields */
   DWORD ImageBase;
   DWORD SectionAlignment;       /* 0x20 */
   DWORD FileAlignment;
   WORD  MajorOperatingSystemVersion;
   WORD  MinorOperatingSystemVersion;
   WORD  MajorImageVersion;
   WORD  MinorImageVersion;
   WORD  MajorSubsystemVersion;      /* 0x30 */
   WORD  MinorSubsystemVersion;
   DWORD Win32VersionValue;
   DWORD SizeOfImage;
   DWORD SizeOfHeaders;
   DWORD CheckSum;           /* 0x40 */
   WORD  Subsystem;
   WORD  DllCharacteristics;
   DWORD SizeOfStackReserve;
   DWORD SizeOfStackCommit;
   DWORD SizeOfHeapReserve;      /* 0x50 */
   DWORD SizeOfHeapCommit;
   DWORD LoaderFlags;
   DWORD NumberOfRvaAndSizes;
   IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; /* 0x60 */
 } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

그렇다면 몇가지 중요한(?) 멤버들에 대해서 살펴봅시다.

 

#1. Magic

Magic은 32비트인지 64비트인지 구분할 때 쓰인다고 한다

 

- IMAGE_OPTIONAL_HEADER32 : 10B

- IMAGE_OPTIONAL_HEADER64 : 20B

 

#2. AddressOfEntryPoint

AddressOfEntryPoint는 EP의 RVA 값을 가지고 있습니다.

최초로 프로그램이 실행되는 코드의 시작주소로 ★매우 중요한 값★을 가지고 있음.

 

#3. ImageBase('중요')

메모리에서 PE파일이 어디에 로딩이 되는지 메모리에 로딩되는 시작 주소를 알려주는 부분.

exe, dll은 user memory 영역인 0~7FFFFFFF 범위에 로딩되어지며, sys 파일은 kernal memory 영역인 80000000~FFFFFFFF에 로딩되어진다고 합니다.

- 일반적으로 개발도구들이 만들어내는 .exe은 00400000이고, .dll은 100000000 입니다.

 

#4. SectionAlignment, FileAlignment

PE file의 Body는 섹션으로 나뉘어져 있다. file에서의 섹션의 최소단위가 filealignment이고 메모리에서의 섹션의 최소단위가 sectionalignment이다. 이 둘은 같을 수도 다를수도 있습니다.(읍읍;;) 파일/메모리의 섹션 크기는 반드시 sectionalignment / filealignment의 배수가 되어야 합니다.

 

#5. SizeOfImage

SizeofImage는 PE가 메모리에 로딩되었을 때에 가상메모리에서 PE image가 차지하는 크기를 말합니다.

실행되기 전과 후가 다르다고 하네요!

 

#6. SizeOfHeader

SizeofHeader는 PE Header의 전체 크기를 나타냅니다. 이 값또한 filealignment의 배수여야 하며, 파일시작에서 SizeOfHeader의 옵셋만큼 떨어진 위치에 첫번째 섹션에 존재

(DoS + NT + Section Header)

#7. Subsystem

이걸 보고서 .sys인지 .exe인지 .dll인지 구분할수 있다고 함.

참고.

#8. NumberOfRvaAndSizes

NumberOfRvaAndSizes는 IMAEG_OPTIONAL_HEADER32 구조체의 마지막 멤버인 DataDictionary 배열의 개수를 나타냄. 이값을 보고 PE 로더가 배열의 크기를 인식함 (꼭 16이 아닐수 있음. 16은 구조체 정의에 명시된 숫자)

 

#9. DataDirectory

DataDirectory는 IMAGE_DATA_DIRECTORY 구조체의 배열로, 각 항목마다 정의된 값을 가짐.

#define IMAGE_DIRECTORY_ENTRY_EXPORT        0
#define IMAGE_DIRECTORY_ENTRY_IMPORT        1
#define IMAGE_DIRECTORY_ENTRY_RESOURCE      2
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION     3
#define IMAGE_DIRECTORY_ENTRY_SECURITY      4
#define IMAGE_DIRECTORY_ENTRY_BASERELOC     5
#define IMAGE_DIRECTORY_ENTRY_DEBUG         6
#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT     7
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR     8   /* (MIPS GP) */
#define IMAGE_DIRECTORY_ENTRY_TLS           9
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG   10
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT  11
#define IMAGE_DIRECTORY_ENTRY_IAT           12  /* Import Address Table */
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT  13
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR    14
#define IMAGE_DIRECTORY_ENTRY Reserved Directory 15

EXPORT, IMPORT, RESOURCE, TLS를 기억할 것.

IAT와 EAT의 개념에 대해서 잠깐 정리를 해보면 

 

IAT : 내가 프로그램에서 어떠한 함수를 사용할지를 모아둠

EAT : 내가 라이브러리가 되어서 다른 프로그램에 제공하는 함수목록을 모아둠.

 

여기까지가 IMAGE_OPTIONAL_HEADER 입니다.

VIEW 밑에 짤렸;

NT Header 끝!!

 

섹션 헤더로 출발!

섹션 헤더

- 각 섹션의 속성을 정의한 것이 섹션 헤더라고 합니다.

PE 파일은 code, data, resouce 등을 각각의 섹션으로 나뉘어서 저장되어 집니다.

이유 ? 프로그램의 안정성을 위해서. 안나뉘어 있으면 데이터 쓰다가 overflow나면 code영역을 침범함 ㅋㅋ

 

섹션의 속성에는 file/memory에서의 시작 위치, 크기, 엑세스 권한 등이 있어야겠고, 각각의 섹션마다 특성, 접근권한을 다르게 설정할 필요가 있어짐.

종류 엑세스 권한
code 실행, 읽기 권한
data 비실행, 읽기, 쓰기 권한
resource 비실행, 읽기 권한

IMAGE_SECTION_HEADER

섹션 헤더는 각 섹션별 IMAGE_SECTION_HEADER 구조체의 배열로 되어 있음.

typedef struct _IMAGE_SECTION_HEADER {
  BYTE  Name[IMAGE_SIZEOF_SHORT_NAME];
  union {
    DWORD PhysicalAddress;
    DWORD VirtualSize;
  } Misc;
  DWORD VirtualAddress;
  DWORD SizeOfRawData;
  DWORD PointerToRawData;
  DWORD PointerToRelocations;
  DWORD PointerToLinenumbers;
  WORD  NumberOfRelocations;
  WORD  NumberOfLinenumbers;
  DWORD Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

리얼

여기서 알아야 할 중요 멤버들은 다음과 같습니다.

항목 의미
VirtualSize 메모리에서 섹션이 차지하는 크기
VirtualAddress 메모리에서 섹션의 시작 주소(RVA)
SizeOfRawData 파일에서 섹션이 차지하는 크기
PointerToRawData 파일에서 섹션의 시작 위치
Characteristics 섹션의 속성(bit OR)

VirtualAddress와 PointerToRawData는 아무 값이나 가질 수 없고, 위에서 정의된 Sectionalignment와 Filealignment에 맞게 설정되어짐.

VirtualSize와 SizeOfRawData는 일반적으로 서로 다른 값을 가짐.

즉 파일에서의 섹션크기와 메모리에 로딩되는 섹션의 크기는 서로 다릅니다!

 

해당 부분이 IMAGE_SECTION_HEADER 구조체 배열!

그리고 각각의 .text, .data, .rsrc의 멤버들의 내용은 같습니다.

 

* 여기서 잠깐 이미지란 ?

- PE 파일이 메모리에 로딩되어질 때 파일이 그대로 올라가는게 아니라 섹션 헤더에 정의된 대로 섹션 시작 주소, 섹션 크기 등에 맞춰서 올라가게 됨. 따라서 PE와 메모리에서의 PE는 서로 다른 형태이고, 메모리에 로딩된 상태의 PE를 '이미지' 라고 부는 것임.

 

RVA, RAW

프로그램이 시작되기전의 주소를 offset 또는 'RAW'라고 부릅니다.

빨강네모!

 

실행되기전의 주소를 말할때는 이 부분을 참고하면 됩니당.

아무튼 다음에 알아볼건 'RVA' 입니다.

RVA는 얼마만큼 떨어져 있는지를 의미합니다 기준점은 어디서요? VA에서요 ^^

 

VA(Virtual Address)는 메모리의 어딘가의 주소이기 때문에 offset과는 전혀다른 개념이에요

window도 memory map file을 사용하기 때문에 파일을 실행하게 되면 가상 메모리 공간에 프로그램이 올라가게 되는데 이 과정을 'mapping'이라고 하는듯.

 

그런데 이 mapping이 되는 위치가 바로 NT Header 중에서 IMAGE_OPTIONAL_HEADER32구조체 안에있는 ImageBase를 의미함. VA는 ImageBase를 기준으로 생성된다고 봐도 무관할 것 같다. 실제 메모리에서는 이 VA주소를 보고 프로그램을 실행시키게 된다.

 

* PE의 대부분 주소가 RVA인 이유 ?

- 프로그램은 하나만 실행되지 않는다. 동시에 여러개의 프로그램을 실행할 때 이미 해당주소에 프로그램이 있을경우 하나의 주소에 두개의 프로그램이 실행될 순 없고, window os는 ASLR을 쓰기 때문에 실행마다 주소가 변경된다 따라서 변경된 주소에서 '얼마만큼 떨어져 있느냐' RVA를 통해 시작주소가 바뀌어도 프로그램은 정상적으로 구동된다.

이를 PE relocation 이라고 한다.

 

* 퀴즈 :-3

RVA = 5000일 때, RAW = ?

 

일단 RVA - VA = RAW - PointerToRawData 이다. (매핑과정에서 주소가 바꼈더라도 떨어진 거리는 같으므로 ??)

RAW = RVA - VA + PointerToRawData

RAW = 5000 - 1000 + 400 = 4400 ^^ (위 그림 참고)

 

★ IAT

- IAT ? 프로그램이 어떤 라이브러리에서 어떤 함수를 사용하고 있는지를 기술한 테이블입니다.

- DLL ? '동적 연결 라이브러리', (프로그램에 library를 포함시키지 않고 별도의 DLL로 구성하여 필요할 때 불러씀)

 

자이언티 - 꺼내먹어요 ~

 

DLL의 로딩방식은 2가지 입니다. 

- Explicit Linking : 프로그램에서 사용되는 순간에 로딩하고 사용이 끝나면 메모리에서 해제

- Implicit Linking : 프로그램 시작과 같이 로딩되고 프로그램 종료시 메모리에서 해제

IAT는 후자의 메커니즘을 제공하는 역할을 합니다.

프로그램은 다른 모듈을 호출할 때 다음과 같은 형식으로 호출

GetCureentProcessId를 호출할 때 직접호출하지 않고 002410CC 주소에 있는 값을 가져와서 호출하는 방식임

제작자가 컴파일시에 실제주소가 002410CC에 올라오면서 실행됨

call dword ptr ds:[api 여기에 넣어라!]

 

'Reversing' 카테고리의 다른 글

리버싱 6  (2) 2019.04.04
PE file(3)  (0) 2019.04.03
PE File(1)  (0) 2019.04.02
리버싱 5  (0) 2019.04.02
리버싱 4  (0) 2019.03.29

+ Recent posts