SlideShare a Scribd company logo
1 of 65
REVERSING[4]
Reverse Engineering
목차
• PE File Format
• 시작하기 전에..
• 복습-DataDirectory
• 잠깐, DLL이란?
• 함수 Import
• IMAGE_IMPORT_DESCRIPTOR
• IMAGE_THUNK_DATA32
• IMAGE_IMPORT_BY_NAME
• IAT
• IAT바인딩 과정
• 함수 Export
• IMAGE_EXPORT_DIRECTORY
• 과제
• 직접 찾아보기
• PE viewer 업데이트
• 부록
• 참고 사이트
시작하기 전에..
• 복습- DataDirectory
• 잠깐, DLL이란?
복습
• 전 시간에 배운 내용
• IMAGE_DOS_HEADER
• IMAGE_NT_HEADER
• IMAGE_FILE_HEADER
• IMAGE_OPTIONAL_HEADER
• IMAGE_SECTION_HEADER
• 이번에 배울 내용
• IMAGE_OPTIONAL_HEADER의 마지막 값인 DataDirectory를 이용하여 접근 하는 정보들
• 함수의 Import / Export 방법
복습 - DataDirectory
DataDorectory
• 보통 명시된 수(IMAGE_NUMBEROF_DIRECTORY_ENTRIES,
16(0x10))만큼의 배열
• IMAGE_DATA_DIRECTORY struct의 배열, winnt.h에 정의되어 있음
• 배열의 각 항목마다 정의된 값을 가짐
복습 - DataDirectory
• winnt.h에 정의되어 있는 Data Directory와
IMAGE_NUMBEROF_DIRECTORY_ENTRIES
• VirtualAddress를 이용하여 각 항목이
의미하는 데이터를 얻으러 갈 수 있음
복습 - DataDirectory
• 각 배열 항목마다의 용도
복습 - DataDirectory
• 각 배열 항목마다의 용도
잠깐, DLL이란?
• Dynamic-Link Library
• MS Windows에서 구현된 동적 라이브러리
• 다른 프로그램이 불러서 쓸 수 있는 다양한 함수들을 가지고 있음
• 16비트 시절 -> DLL이 없음, 라이브러리만 있음
• 컴파일 시 라이브러리에서 해당 함수의 코드를 그대로 가져와서 프로그램에 넣었음
• 멀티 태스킹을 지원한 이후로 이러한 방식은 비효율적이 됨
• 여러 프로그램이 동시에 실행되어야 하는 상황에서 모든 프로그램마다 따로 라이브러리 코드를 넣는 것은 낭비
• 효율적인 멀티 태스킹을 위해 DLL 개발
• 프로그램에 라이브러리를 포함시키지 말고 별도의 파일(DLL)로 구성하여 필요할 때마다 불러 쓰자
• 일단 한 번 로딩된 DLL의 코드, 리소스는 Memory Mapping 기술로 여러 프로세스에서 공유해 쓰자
• 라이브러리가 업데이트되었을 때, 해당 DLL 파일만 교체하면 되니 쉽고 편해서 좋다
잠깐, DLL이란?
• Linking (DLL 로딩)
• 묵시적 링킹(Implicit Linking) ->앞으로 살펴볼 것
• 실행파일 자체에 어떤 DLL의 어떤 함수를 사용하겠다는 정보를 포함
• OS가 프로그램 실행 시 해당 함수를 초기화한 후 이용
• 프로그램이 시작할 때 가상 메모리에 올리고, 프로그램 종료할 때 가상 메모리에서 해제
• 명시적 링킹(Explicit Linking)
• 프로그램이 실행 중일 때 API를 이용하여 DLL 파일이 있는지 검사
• 동적으로 DLL을 로드하고, 해제함
• LoadLibrary함수로 불러오면 가상 메모리에 올리고, FreeLibrary 함수를 호출하면 가상 메모리에서 해제
잠깐, DLL이란?
• 프로그램에서 많은 DLL을 이용
• DLL도 EXE처럼 PE File Format
• Image base 등 PE header에 따라 메모리에 올림
• 서로 PE header의 값이 같을 수 있음
• Image base 등의 값이 겹치면 다른 곳에 올려야 함
• 이를 relocation이라 함
• 즉, DLL의 주소가 예상과는 다를 수 있음
• 따라서 주소를 하드 코딩하기 어렵고, 유지/보수가 불편함
• 그래서 생긴 개념이 IAT(Import Address Table)
• 프로그램 실행 시 PE 로더가 사용할 라이브러리 함수의 주소를 기록해 줌
• 코드에서는 사용할 함수의 정보가 적혀 있는 테이블의 주소를 써 둠
• 프로그램을 실행할 때 테이블에 내용을 쓰므로, DLL이 다른 imagebase를 이용해도 상관 없음
잠깐, DLL이란? – 매우 단순한 예시
어셈블리 코드
Call 50
주소 50
“Somefunction()의 주소는
100이다.” 라는 정보가 써
있음
(이 정보는 프로그램을
로딩할 때 씀)
Example.dll의 Somefunction()이 올라온 실제 (가상메모리) 주소 : 100
SomeFunction() 의 실제 (가상메모리) 주소를 기록해 둘 위치 : 50
주소 100
Somefunction()의 코드
실행
이러면 DLL이 예상과 다른 장소에 있더라도 코드를 바꿀 필요가 없음
(프로그램 실행 시 DLL이 실제로 올라온 주소를 테이블에 써 두므로)
함수 IMPORT
• 관련 구조체
• Dll 함수를 이용하기 위한 작업
IMAGE_IMPORT_DESCRIPTOR
• DataDirectory[1].VirtualAddress가 IMAGE_IMPORT_DESCRIPTOR구조체 배열의 시작 주소
• RVA값이기 때문에 파일에서 찾기 위해서는 계산해야 함
• Import Directory Table이라고도 함
• PE 바디에 위치함(.idata 섹션)
• 배열의 크기가 정의되지 않음
• 배열의 마지막은 NULL로 채워진 구조체
IMAGE_IMPORT_DESCRIPTOR
위는 DataDirectory[1]의 값이다
DataDirectory[1].VirtualAddress는 00007000
Import table은 .idata에 있으므로 section .idata의
VritualAddress와 PointerToRawData를 구하여
RAW를 구한다
IMAGE_IMPORT_DESCRIPTOR
.idata의 VirtualAddress는 00007000
.idata의 PointerToRawData는 00002E00
따라서 RAW = 00007000 – 00007000 + 00002E00 = 2E00
IMAGE_IMPORT_DESCRIPTOR
RAW 2E00 를 찾아갔다
마지막 NULL 배열 까지가 IMAGE_IMPORT_DESCRIPTOR 구조체 배열이다
IMAGE_IMPORT_DESCRIPTOR
winnt.h에 정의된 IMAGE_IMPORT_DESCRIPTOR 구조체이다.
IMAGE_IMPORT_DESCRIPTOR
DUMMYUNIONNAME
• Characteristics나 OriginalFirstThunk값을
가지는 Union
• Characteristics는 한 때 flag의
집합이었지만 현재 쓰이지 않음
• OriginalFirstThunk는
IMAGE_THUNK_DATA32 구조체의 시작
주소(RVA)를 가짐
IMAGE_THUNK_DATA32 RAW를 계산하여 파일에서 찾음
IMAGE_THUNK_DATA32
• winnt.h에 정의된 IMAGE_THUNK_DATA32
• 마지막 NULL 배열이 끝을 의미
• u1
• Union으로, 값이 무엇인가에 따라 용도가
다르게 부름
• Ordinal(서수) 필드를 사용하는 경우, 이
필드가 가리키는 것은 IOT(Import
Ordinal Table)
• AddressOfData 필드를 사용하는 경우,
이 필드가 가리키는 것은 INT(Import
Name Table)이며
IMAGE_IMPORT_BY_NAME배열을
가리킴
• 앞으로 자세히 볼 것은 INT
IMAGE_IMPORT_BY_NAME
RAW를 계산하여
파일에서 찾음
IMAGE_IMPORT_BY_NAME
• winnt.h에 정의된 IMAGE_IMPORT_BY_NAME 구조체
• Padding으로 인해 구조체 크기는 4가 됨
• Name필드 정의는 char 1개 이지만, 사실상 크기에 제한이
없으며 각자의 사이즈에 맞게 할당되는 듯
IMAGE_IMPORT_BY_NAME
Hint
• 라이브러리에서 함수의 고유 번호
• 함수 찾을 때 부하를 줄이는 용도로 이용됨
IMAGE_IMPORT_BY_NAME
Name
• 함수의 이름
• Name필드 정의는 char 1개 이지만, 사실상 크기에
제한이 없으며 NULL을 기준으로 종료를 알린다.
IMAGE_IMPORT_DESCRIPTOR
TimeDateStamp
• 시간과 날짜를 나타내는 타임 스탬프지만
실제 시간과는 상관이 없음
• IMAGE_IMPORT_DESCRIPTOR가 가리키는
해당 DLL이 바인딩 과정을 거치기 전에는
항상 0, 완료된 후에는 -1
• 바인딩이란?
• 로더가 라이브러리를 로드하고, IAT에
값을 기록하는 것(뒤에서 자세히 다룸)
IMAGE_IMPORT_DESCRIPTOR
ForwarderChain
• IMAGE_IMPORT_DESCRIPTOR가 가리키는
해당 DLL이 바인딩 과정을 거치기 전에는
항상 0, 완료된 후에는 -1
• DLL이 또 다른 DLL과 연관이 있을 때 이용
IMAGE_IMPORT_DESCRIPTOR
Name
• 라이브러리 파일 이름 문자열의
포인터(RVA)
• 포인터를 따라가면 dll의 이름을 구할
수 있다.
• 아래는 RAW를 계산하여 찾은 것
IMAGE_IMPORT_DESCRIPTOR
FirstThunk
• 해당 DLL의 IAT (Import Address
Table)의 시작 주소(RVA)
Import Address Table (IAT)
RAW를 계산하여
파일에서 찾음
Import Address Table (IAT)
IAT
• 실제 함수의 주소가 저장되는 테이블
• PE 로더가 프로그램을 로딩하며 덮어 씀
• 파일에서는 INT와 같은 값을 저장하곤
하지만 로딩된 후 값이 덮어써 짐
Import Address Table (IAT)
PE 이미지의 메모리 덤프
왼쪽은 INT, 오른쪽은 IAT
IAT의 값이 실제 함수의 주소로 덮어써진 것을 확인할 수 있음
Import Address Table (IAT)
맨 처음 값인 77AA45F5로 이동해 보았다.
해당 함수의 코드를 찾을 수 있다.
Import Address Table (IAT)
실제로 어떻게 함수가 호출되는가 예를 보자.
다음은 printf을 호출하는 모습이다. printf는
msvcrt dll에 속한다는 것을 알 수 있다.
Ollydbg 옵션을 해제하여 symbolic address를
보이지 않도록 설정했다.
printf를 호출하기 위해 0040285C를
호출한다.
Import Address Table (IAT)
PE viewer로 import하는 dll의 정보를 찾아보았다.
여태까지는 파일을 한 번 직접 보기 위하여 실제
파일을 까 보았지만 앞으로는 PE viewer
프로그램을 자주 사용할 것이다.
위는 IMAGE_IMPORT_DESCRIPTOR에서 읽어온
dll의 정보이고, 아래는 그 dll과 관련된 INT의
정보이다.
여태까지 예제로 본 것은 KERNEL32.dll이었는데,
printf는 msvcrt.dll에 속한다.(헷갈리지 말자)
해당 dll의 정보를 파일에서 찾아보자.
Import Address Table (IAT)
위의 PE viewer를 참고하여 찾은 msvcrt.dll의 정보이다.
msvcrt.dll의 INT
msvcrt.dll의 IAT
Import Address Table (IAT)
다시 코드로 돌아와서, call하는 0040285C를
살펴보았다.
40285C에는 또 다른 코드, JMP [4071D4] 가
있다. 이는 ‘4071D4에 저장된 주소’로
점프하라는 코드이다.
Import Address Table (IAT)
4071D4가 어디인지 찾아보자. 이는
mscvrt.dll의 IAT에 속한다.
4071D4에 저장된 값은 7594C5B9이다.
Import Address Table (IAT)
점프 코드를 실행하면 7594C5B9로 점프한다.
이는 printf함수의 코드이다.
이렇게 함수에 접근하기 위하여 IAT에 저장된
값을 이용한다는 것을 확인할 수 있다.
IAT 바인딩 과정
1. IMAGE_IMPORT_DISCRIPTOR(IID)의 Name 멤버를 읽어서 라이브러리의 이름 문자열(ex.
“kernel32.dll”)을 얻는다.
2. 해당 라이브러리를 로딩한다. (불러온다)
3. IID의 OriginalFirstThunk 멤버를 읽어서 INT 주소를 얻는다.
4. INT에서 배열의 값을 하나씩 읽어 해당 IMAGE_IMPORT_BY_NAME 주소(RVA)를 얻는다.
5. IMAGE_IMPORT_BY_NAME의 Hint(Ordinal) 또는 Name 항목을 이용하여 해당 함수의 시작주
소를 얻는다.
6. IID의 FirstThunk 멤버를 읽어서 IAT 주소를 얻는다.
7. 해당 IAT 배열 값에 위에서 구한 함수 주소를 입력한다.
8. INT 배열의 끝까지(NULL을 만날 때까지) 4~7을 반복한다.
IAT 바인딩 과정
IMAGE_IMPORT_DISCRIPTOR Name DLL 이름 얻기 DLL 파일에서
정보 불러오기
IAT 바인딩 과정
IMAGE_IMPORT_DISCRIPTOR Name DLL 이름 얻기 DLL 파일에서
정보 불러오기
OriginalFirstThunk INT 접근
IMAGE_IMPO
RT_BY_NAME
주소 얻기
IAT 바인딩 과정
IMAGE_IMPORT_DISCRIPTOR Name DLL 이름 얻기 DLL 파일에서
정보 불러오기
OriginalFirstThunk INT 접근
IMAGE_IMPOR
T_BY_NAME
얻기
Hint
(Ordinal)
(해당 함수 번호)
Name
함수 시작 주소
구하기
IAT 바인딩 과정
IMAGE_IMPORT_DISCRIPTOR Name DLL 이름 얻기 DLL 파일에서
정보 불러오기
OriginalFirstThunk INT 접근
IMAGE_IMPOR
T_BY_NAME
얻기
Hint
(Ordinal)
(해당 함수 번호)
Name
함수 시작 주소
구하기
FirstThunk IAT 접근 IAT 기록
다 기록할 때까지 반복
IMAGE_IMPORT_DESCRIPTOR의 전체 구조
함수 EXPORT
• 관련 구조체
IMAGE_EXPORT_DIRECTORY
• 함수를 다른 프로그램에서 불러 쓸 수 있도록 하기 위한 구조체이다.
• .edata나 .rdata에 있다.
• .edata는 함수 export를 위한 섹션이다.
• Export하지 않는 프로그램은 관련 없음
• DLL에서 중요
• .edata대신 .rdata 섹션에 있을 수도 있다.
• 앞에 r이 붙은 섹션 이름은 보통 read only 섹션을 의미한다.
• API를 제공하여 프로그램이 연동되게 하는 경우 EXE에도 Export 관련 정보가 있을 수 있다.
• EAT라는 매커니즘을 이용한다.
• EAT는 자신이 제공하는 함수에 대한 것이므로, IAT처럼 여러 개 있지 않다.
• 많은 dll을 대상으로 하는 것이 아니기 때문에
• IMAGE_EXPORT_DIRECTORY 구조체가 PE파일에 하나만 존재한다.
IMAGE_EXPORT_DIRECTORY
winnt.h에 정의된 IMAGE_EXPORT_DIRECTORY
IMAGE_EXPORT_DIRECTORY
Characteristics
• 이 필드는 사용되지 않으며, 0으로 설정된다.
IMAGE_EXPORT_DIRECTORY
TimeDateStamp
• 본 파일이 생성된 시간/날짜
IMAGE_EXPORT_DIRECTORY
Major/MinorVersion
• 파일의 버전을 나타내기 위한 필드이지만
실제로는 사용되지 않는다. 0으로 설정된다.
IMAGE_EXPORT_DIRECTORY
Name
• 해당 DLL의 이름을 나타내는 아스키 코드
문자열의 시작 주소(RVA)
IMAGE_EXPORT_DIRECTORY
Base
• 내보낸 함수들에 대한 서수의 시작 번호
• 내보내는 함수의 서수가 차례대로 3, 4, 5면 이
필드 값은 3이 된다.
IMAGE_EXPORT_DIRECTORY
NumberOfFunctions
• 실제 export하는 함수 개수
• AddressOfFunctions 필드가 가리키는 RVA
배열의 원소 개수와 같다
• 이 값은 NumberOfName과 다를 수도 있다.
IMAGE_EXPORT_DIRECTORY
NumberOfNames
• Export 함수 중에서 이름을 가지는 함수 개수
• NumberOfFunctions과 같거나 작음
• AddressOfNames과 AddressOfNameOrdinals 필드가
가리키는 RVA 배열의 원소 개수이다 .
IMAGE_EXPORT_DIRECTORY
AddressOfFunctions
• Export하는 함수들의 함수 포인터에 대한 RVA를 가진 배열
• 함수들의 시작 위치 배열의 주소
• 각각 내보낸 함수에 대한 진입점이 됨
• 함수의 시작점 주소이니까
• 원소 개수는 NumberOfFunctions
IMAGE_EXPORT_DIRECTORY
AddressOfNames
• 내보낸 함수들의 이름을 가리키는 RVA를 가진 배열
• 함수 이름 배열의 주소
• 원소 개수는 NumberOfNames
IMAGE_EXPORT_DIRECTORY
AddressOfNameOrdinals
• 서수 배열에 대한 포인터(RVA)
• 원소의 개수는 NumberOfNames
• 이 서수 배열의 최초 엔트리 값은 항상 0
• 각 원소에 Base 필드의 값을 더하면 정확한 서수 값을 획득
• Offset과 비슷
IMAGE_EXPORT_DIRECTORY
• 찾고자 하는 DLL의 이름을 찾고, AddressOfNames 배열의 몇
번째 인덱스에서 그 이름을 찾았는지 알아낸다.
• 위에서 찾은 인덱스와 같은 인덱스를 이용하여
AddressOfNameOrdinals 배열에 접근하여 저장된 값을
구한다.
• 이 값은 AddressOfFunctions의 인덱스이다.
• 위에서 찾은 AddressOfFunctions의 인덱스를 이용하여
AddressOfFunctions 배열에 접근한다.
• 함수 포인터를 얻을 수 있다.
AddressOfNames RVA RVA RVA RVA
“FuncA” “FuncB” “FuncC” “FuncD”
AddressOfNameOrdinals 0 2 3 4
FuncA
코드
<index 2>
AddressOfFunctions RVA null RVA RVA RVA
FuncB
코드
FuncC
코드
FunD
코드
IMAGE_EXPORT_DIRECTORY
• DLL을 이용하기 위해 GetProcAddress 함수를 호출하면, 함수
이름을 찾고, 그에 해당하는 주소를 찾아 반환한다.
• 서수를 이용하여 GetProcAddress를 호출할 수도 있다. 이
때는 서수를 이용하여 찾는다. (이름 찾는 것보다 더 빠르다)
• DLL을 이용하는 PE에 적힌 INT를 읽고, 이름이나 서수를
알아내어 해당 DLL파일의 EAT를 읽어 원하는 함수를 찾은 후,
IAT에 주소를 써 준다.
과제
• 직접 찾아보기
• PE viewer 업데이트
직접 찾아보기
• printf(“Hello world!”); 프로그램을 만들고, 직접 INT와 IAT를 찾아보자.
• PPT를 보고 따라해 보자.
• 여기저기 뒤적거려보고, 주소들을 따라가보면 좋다.
• 직접 만든 DLL의 함수가 이용되는 모습을 보는 것도 좋은 경험이다.
PE viewer 업데이트
• Import 하는 함수 정보도 알아낼 수 있도록 PE viewer를 업데이트 해보자.
• Dll 이름과 그 Dll에서 import할 함수 이름을 인쇄하도록 하자.
부록
• 참고 사이트
참고 사이트
• IAT 자세히 살펴보기
• http://reversecore.com/23
• http://yokang90.tistory.com/26
• EAT 자세히 살펴보기
• http://blog.naver.com/skddms/110180144875
• http://reversecore.com/24

More Related Content

What's hot

Pwnable study basic_2
Pwnable study basic_2Pwnable study basic_2
Pwnable study basic_2Jinkyoung Kim
 
Windows reversing study_basic_4
Windows reversing study_basic_4Windows reversing study_basic_4
Windows reversing study_basic_4Jinkyoung Kim
 
Linux reversing study_basic_4
Linux reversing study_basic_4Linux reversing study_basic_4
Linux reversing study_basic_4Jinkyoung Kim
 
Windows reversing study_basic_6
Windows reversing study_basic_6Windows reversing study_basic_6
Windows reversing study_basic_6Jinkyoung Kim
 
Assembly 스터디 2
Assembly 스터디 2Assembly 스터디 2
Assembly 스터디 2Jinkyoung Kim
 
Linux reversing study_basic_3
Linux reversing study_basic_3Linux reversing study_basic_3
Linux reversing study_basic_3Jinkyoung Kim
 
Pwnable study basic_1
Pwnable study basic_1Pwnable study basic_1
Pwnable study basic_1Jinkyoung Kim
 
Windows reversing study_basic_2
Windows reversing study_basic_2Windows reversing study_basic_2
Windows reversing study_basic_2Jinkyoung Kim
 
Web hacking introduction
Web hacking introductionWeb hacking introduction
Web hacking introductionJinkyoung Kim
 
Linux reversing study_basic_2
Linux reversing study_basic_2Linux reversing study_basic_2
Linux reversing study_basic_2Jinkyoung Kim
 
[Kerference] 시작! 리버싱 - 김종범(KERT)
[Kerference] 시작! 리버싱 - 김종범(KERT)[Kerference] 시작! 리버싱 - 김종범(KERT)
[Kerference] 시작! 리버싱 - 김종범(KERT)NAVER D2
 
Linux reversing study_basic_1
Linux reversing study_basic_1Linux reversing study_basic_1
Linux reversing study_basic_1Jinkyoung Kim
 
Java 이해하기 쉬운 코드 20210405
Java 이해하기 쉬운 코드 20210405Java 이해하기 쉬운 코드 20210405
Java 이해하기 쉬운 코드 20210405Hyosang Hong
 

What's hot (20)

System+os study 1
System+os study 1System+os study 1
System+os study 1
 
System+os study 3
System+os study 3System+os study 3
System+os study 3
 
Pwnable study basic_2
Pwnable study basic_2Pwnable study basic_2
Pwnable study basic_2
 
Python
PythonPython
Python
 
Windows reversing study_basic_4
Windows reversing study_basic_4Windows reversing study_basic_4
Windows reversing study_basic_4
 
Linux reversing study_basic_4
Linux reversing study_basic_4Linux reversing study_basic_4
Linux reversing study_basic_4
 
Windows reversing study_basic_6
Windows reversing study_basic_6Windows reversing study_basic_6
Windows reversing study_basic_6
 
Assembly 스터디 2
Assembly 스터디 2Assembly 스터디 2
Assembly 스터디 2
 
Linux reversing study_basic_3
Linux reversing study_basic_3Linux reversing study_basic_3
Linux reversing study_basic_3
 
Pwnable study basic_1
Pwnable study basic_1Pwnable study basic_1
Pwnable study basic_1
 
System+os study 7
System+os study 7System+os study 7
System+os study 7
 
Windows reversing study_basic_2
Windows reversing study_basic_2Windows reversing study_basic_2
Windows reversing study_basic_2
 
Web hacking introduction
Web hacking introductionWeb hacking introduction
Web hacking introduction
 
Linux reversing study_basic_2
Linux reversing study_basic_2Linux reversing study_basic_2
Linux reversing study_basic_2
 
System+os study 5
System+os study 5System+os study 5
System+os study 5
 
[Kerference] 시작! 리버싱 - 김종범(KERT)
[Kerference] 시작! 리버싱 - 김종범(KERT)[Kerference] 시작! 리버싱 - 김종범(KERT)
[Kerference] 시작! 리버싱 - 김종범(KERT)
 
Linux reversing study_basic_1
Linux reversing study_basic_1Linux reversing study_basic_1
Linux reversing study_basic_1
 
Java 이해하기 쉬운 코드 20210405
Java 이해하기 쉬운 코드 20210405Java 이해하기 쉬운 코드 20210405
Java 이해하기 쉬운 코드 20210405
 
Java lambda
Java lambdaJava lambda
Java lambda
 
Introduce php7
Introduce php7Introduce php7
Introduce php7
 

Similar to Windows reversing study_basic_5

2006 03 15_pe & api hook
2006 03 15_pe & api hook2006 03 15_pe & api hook
2006 03 15_pe & api hook용환 노
 
Windosw via c 스터디20장.pptx
Windosw via c 스터디20장.pptxWindosw via c 스터디20장.pptx
Windosw via c 스터디20장.pptxHolyTak
 
19_DLL의 기본.pptx
19_DLL의 기본.pptx19_DLL의 기본.pptx
19_DLL의 기본.pptxssuser0c2478
 
More effective c++ chapter1,2
More effective c++ chapter1,2More effective c++ chapter1,2
More effective c++ chapter1,2문익 장
 
[0618구경원]초보 게임프로그래머를 위한 c++
[0618구경원]초보 게임프로그래머를 위한 c++[0618구경원]초보 게임프로그래머를 위한 c++
[0618구경원]초보 게임프로그래머를 위한 c++KyeongWon Koo
 
C++20에서 리플렉션 기능 구현
C++20에서 리플렉션 기능 구현C++20에서 리플렉션 기능 구현
C++20에서 리플렉션 기능 구현Bongseok Cho
 
C++ Advanced 강의 1주차
C++ Advanced 강의 1주차C++ Advanced 강의 1주차
C++ Advanced 강의 1주차HyunJoon Park
 
effective c++ chapter 3~4 정리
effective c++ chapter 3~4 정리effective c++ chapter 3~4 정리
effective c++ chapter 3~4 정리Injae Lee
 
[Week5] Getting started with R
[Week5] Getting started with R[Week5] Getting started with R
[Week5] Getting started with Rneuroassociates
 
프로세스 방어
프로세스 방어프로세스 방어
프로세스 방어주항 박
 
C# 뉴비를 위한 맛보기 2
C# 뉴비를 위한 맛보기 2C# 뉴비를 위한 맛보기 2
C# 뉴비를 위한 맛보기 2진상 문
 
Move semantics
Move semanticsMove semantics
Move semanticsQooJuice
 
Dll 분석 방법
Dll 분석 방법Dll 분석 방법
Dll 분석 방법상윤 유
 
Effective c++ 정리 chapter 6
Effective c++ 정리 chapter 6Effective c++ 정리 chapter 6
Effective c++ 정리 chapter 6연우 김
 
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기NAVER Engineering
 
웹사이트기획 및 관리
웹사이트기획 및 관리웹사이트기획 및 관리
웹사이트기획 및 관리봉조 김
 
Java rmi 개발 가이드
Java rmi 개발 가이드Java rmi 개발 가이드
Java rmi 개발 가이드중선 곽
 
Boost 라이브리와 C++11
Boost 라이브리와 C++11Boost 라이브리와 C++11
Boost 라이브리와 C++11OnGameServer
 

Similar to Windows reversing study_basic_5 (20)

2006 03 15_pe & api hook
2006 03 15_pe & api hook2006 03 15_pe & api hook
2006 03 15_pe & api hook
 
Pe+file+format
Pe+file+formatPe+file+format
Pe+file+format
 
Windosw via c 스터디20장.pptx
Windosw via c 스터디20장.pptxWindosw via c 스터디20장.pptx
Windosw via c 스터디20장.pptx
 
19_DLL의 기본.pptx
19_DLL의 기본.pptx19_DLL의 기본.pptx
19_DLL의 기본.pptx
 
More effective c++ chapter1,2
More effective c++ chapter1,2More effective c++ chapter1,2
More effective c++ chapter1,2
 
[0618구경원]초보 게임프로그래머를 위한 c++
[0618구경원]초보 게임프로그래머를 위한 c++[0618구경원]초보 게임프로그래머를 위한 c++
[0618구경원]초보 게임프로그래머를 위한 c++
 
C++20에서 리플렉션 기능 구현
C++20에서 리플렉션 기능 구현C++20에서 리플렉션 기능 구현
C++20에서 리플렉션 기능 구현
 
C++ Advanced 강의 1주차
C++ Advanced 강의 1주차C++ Advanced 강의 1주차
C++ Advanced 강의 1주차
 
effective c++ chapter 3~4 정리
effective c++ chapter 3~4 정리effective c++ chapter 3~4 정리
effective c++ chapter 3~4 정리
 
Light Tutorial Django
Light Tutorial DjangoLight Tutorial Django
Light Tutorial Django
 
[Week5] Getting started with R
[Week5] Getting started with R[Week5] Getting started with R
[Week5] Getting started with R
 
프로세스 방어
프로세스 방어프로세스 방어
프로세스 방어
 
C# 뉴비를 위한 맛보기 2
C# 뉴비를 위한 맛보기 2C# 뉴비를 위한 맛보기 2
C# 뉴비를 위한 맛보기 2
 
Move semantics
Move semanticsMove semantics
Move semantics
 
Dll 분석 방법
Dll 분석 방법Dll 분석 방법
Dll 분석 방법
 
Effective c++ 정리 chapter 6
Effective c++ 정리 chapter 6Effective c++ 정리 chapter 6
Effective c++ 정리 chapter 6
 
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
 
웹사이트기획 및 관리
웹사이트기획 및 관리웹사이트기획 및 관리
웹사이트기획 및 관리
 
Java rmi 개발 가이드
Java rmi 개발 가이드Java rmi 개발 가이드
Java rmi 개발 가이드
 
Boost 라이브리와 C++11
Boost 라이브리와 C++11Boost 라이브리와 C++11
Boost 라이브리와 C++11
 

More from Jinkyoung Kim

Axelar 22.04 bughunting case study
Axelar 22.04 bughunting case studyAxelar 22.04 bughunting case study
Axelar 22.04 bughunting case studyJinkyoung Kim
 
Angle Protocol bughunting case study
Angle Protocol bughunting case studyAngle Protocol bughunting case study
Angle Protocol bughunting case studyJinkyoung Kim
 
Nouns DAO bughunting case study
Nouns DAO bughunting case studyNouns DAO bughunting case study
Nouns DAO bughunting case studyJinkyoung Kim
 
해커가 되고 싶은 자는 나에게... 정보보안 입문과 길 찾기
해커가 되고 싶은 자는 나에게... 정보보안 입문과 길 찾기해커가 되고 싶은 자는 나에게... 정보보안 입문과 길 찾기
해커가 되고 싶은 자는 나에게... 정보보안 입문과 길 찾기Jinkyoung Kim
 

More from Jinkyoung Kim (6)

Axelar 22.04 bughunting case study
Axelar 22.04 bughunting case studyAxelar 22.04 bughunting case study
Axelar 22.04 bughunting case study
 
Angle Protocol bughunting case study
Angle Protocol bughunting case studyAngle Protocol bughunting case study
Angle Protocol bughunting case study
 
Nouns DAO bughunting case study
Nouns DAO bughunting case studyNouns DAO bughunting case study
Nouns DAO bughunting case study
 
해커가 되고 싶은 자는 나에게... 정보보안 입문과 길 찾기
해커가 되고 싶은 자는 나에게... 정보보안 입문과 길 찾기해커가 되고 싶은 자는 나에게... 정보보안 입문과 길 찾기
해커가 되고 싶은 자는 나에게... 정보보안 입문과 길 찾기
 
System+os study 6
System+os study 6System+os study 6
System+os study 6
 
System+os study 2
System+os study 2System+os study 2
System+os study 2
 

Windows reversing study_basic_5

  • 2. 목차 • PE File Format • 시작하기 전에.. • 복습-DataDirectory • 잠깐, DLL이란? • 함수 Import • IMAGE_IMPORT_DESCRIPTOR • IMAGE_THUNK_DATA32 • IMAGE_IMPORT_BY_NAME • IAT • IAT바인딩 과정 • 함수 Export • IMAGE_EXPORT_DIRECTORY • 과제 • 직접 찾아보기 • PE viewer 업데이트 • 부록 • 참고 사이트
  • 3. 시작하기 전에.. • 복습- DataDirectory • 잠깐, DLL이란?
  • 4. 복습 • 전 시간에 배운 내용 • IMAGE_DOS_HEADER • IMAGE_NT_HEADER • IMAGE_FILE_HEADER • IMAGE_OPTIONAL_HEADER • IMAGE_SECTION_HEADER • 이번에 배울 내용 • IMAGE_OPTIONAL_HEADER의 마지막 값인 DataDirectory를 이용하여 접근 하는 정보들 • 함수의 Import / Export 방법
  • 5. 복습 - DataDirectory DataDorectory • 보통 명시된 수(IMAGE_NUMBEROF_DIRECTORY_ENTRIES, 16(0x10))만큼의 배열 • IMAGE_DATA_DIRECTORY struct의 배열, winnt.h에 정의되어 있음 • 배열의 각 항목마다 정의된 값을 가짐
  • 6. 복습 - DataDirectory • winnt.h에 정의되어 있는 Data Directory와 IMAGE_NUMBEROF_DIRECTORY_ENTRIES • VirtualAddress를 이용하여 각 항목이 의미하는 데이터를 얻으러 갈 수 있음
  • 7. 복습 - DataDirectory • 각 배열 항목마다의 용도
  • 8. 복습 - DataDirectory • 각 배열 항목마다의 용도
  • 9. 잠깐, DLL이란? • Dynamic-Link Library • MS Windows에서 구현된 동적 라이브러리 • 다른 프로그램이 불러서 쓸 수 있는 다양한 함수들을 가지고 있음 • 16비트 시절 -> DLL이 없음, 라이브러리만 있음 • 컴파일 시 라이브러리에서 해당 함수의 코드를 그대로 가져와서 프로그램에 넣었음 • 멀티 태스킹을 지원한 이후로 이러한 방식은 비효율적이 됨 • 여러 프로그램이 동시에 실행되어야 하는 상황에서 모든 프로그램마다 따로 라이브러리 코드를 넣는 것은 낭비 • 효율적인 멀티 태스킹을 위해 DLL 개발 • 프로그램에 라이브러리를 포함시키지 말고 별도의 파일(DLL)로 구성하여 필요할 때마다 불러 쓰자 • 일단 한 번 로딩된 DLL의 코드, 리소스는 Memory Mapping 기술로 여러 프로세스에서 공유해 쓰자 • 라이브러리가 업데이트되었을 때, 해당 DLL 파일만 교체하면 되니 쉽고 편해서 좋다
  • 10. 잠깐, DLL이란? • Linking (DLL 로딩) • 묵시적 링킹(Implicit Linking) ->앞으로 살펴볼 것 • 실행파일 자체에 어떤 DLL의 어떤 함수를 사용하겠다는 정보를 포함 • OS가 프로그램 실행 시 해당 함수를 초기화한 후 이용 • 프로그램이 시작할 때 가상 메모리에 올리고, 프로그램 종료할 때 가상 메모리에서 해제 • 명시적 링킹(Explicit Linking) • 프로그램이 실행 중일 때 API를 이용하여 DLL 파일이 있는지 검사 • 동적으로 DLL을 로드하고, 해제함 • LoadLibrary함수로 불러오면 가상 메모리에 올리고, FreeLibrary 함수를 호출하면 가상 메모리에서 해제
  • 11. 잠깐, DLL이란? • 프로그램에서 많은 DLL을 이용 • DLL도 EXE처럼 PE File Format • Image base 등 PE header에 따라 메모리에 올림 • 서로 PE header의 값이 같을 수 있음 • Image base 등의 값이 겹치면 다른 곳에 올려야 함 • 이를 relocation이라 함 • 즉, DLL의 주소가 예상과는 다를 수 있음 • 따라서 주소를 하드 코딩하기 어렵고, 유지/보수가 불편함 • 그래서 생긴 개념이 IAT(Import Address Table) • 프로그램 실행 시 PE 로더가 사용할 라이브러리 함수의 주소를 기록해 줌 • 코드에서는 사용할 함수의 정보가 적혀 있는 테이블의 주소를 써 둠 • 프로그램을 실행할 때 테이블에 내용을 쓰므로, DLL이 다른 imagebase를 이용해도 상관 없음
  • 12. 잠깐, DLL이란? – 매우 단순한 예시 어셈블리 코드 Call 50 주소 50 “Somefunction()의 주소는 100이다.” 라는 정보가 써 있음 (이 정보는 프로그램을 로딩할 때 씀) Example.dll의 Somefunction()이 올라온 실제 (가상메모리) 주소 : 100 SomeFunction() 의 실제 (가상메모리) 주소를 기록해 둘 위치 : 50 주소 100 Somefunction()의 코드 실행 이러면 DLL이 예상과 다른 장소에 있더라도 코드를 바꿀 필요가 없음 (프로그램 실행 시 DLL이 실제로 올라온 주소를 테이블에 써 두므로)
  • 13. 함수 IMPORT • 관련 구조체 • Dll 함수를 이용하기 위한 작업
  • 14. IMAGE_IMPORT_DESCRIPTOR • DataDirectory[1].VirtualAddress가 IMAGE_IMPORT_DESCRIPTOR구조체 배열의 시작 주소 • RVA값이기 때문에 파일에서 찾기 위해서는 계산해야 함 • Import Directory Table이라고도 함 • PE 바디에 위치함(.idata 섹션) • 배열의 크기가 정의되지 않음 • 배열의 마지막은 NULL로 채워진 구조체
  • 15. IMAGE_IMPORT_DESCRIPTOR 위는 DataDirectory[1]의 값이다 DataDirectory[1].VirtualAddress는 00007000 Import table은 .idata에 있으므로 section .idata의 VritualAddress와 PointerToRawData를 구하여 RAW를 구한다
  • 16. IMAGE_IMPORT_DESCRIPTOR .idata의 VirtualAddress는 00007000 .idata의 PointerToRawData는 00002E00 따라서 RAW = 00007000 – 00007000 + 00002E00 = 2E00
  • 17. IMAGE_IMPORT_DESCRIPTOR RAW 2E00 를 찾아갔다 마지막 NULL 배열 까지가 IMAGE_IMPORT_DESCRIPTOR 구조체 배열이다
  • 19. IMAGE_IMPORT_DESCRIPTOR DUMMYUNIONNAME • Characteristics나 OriginalFirstThunk값을 가지는 Union • Characteristics는 한 때 flag의 집합이었지만 현재 쓰이지 않음 • OriginalFirstThunk는 IMAGE_THUNK_DATA32 구조체의 시작 주소(RVA)를 가짐
  • 21. IMAGE_THUNK_DATA32 • winnt.h에 정의된 IMAGE_THUNK_DATA32 • 마지막 NULL 배열이 끝을 의미 • u1 • Union으로, 값이 무엇인가에 따라 용도가 다르게 부름 • Ordinal(서수) 필드를 사용하는 경우, 이 필드가 가리키는 것은 IOT(Import Ordinal Table) • AddressOfData 필드를 사용하는 경우, 이 필드가 가리키는 것은 INT(Import Name Table)이며 IMAGE_IMPORT_BY_NAME배열을 가리킴 • 앞으로 자세히 볼 것은 INT
  • 23. IMAGE_IMPORT_BY_NAME • winnt.h에 정의된 IMAGE_IMPORT_BY_NAME 구조체 • Padding으로 인해 구조체 크기는 4가 됨 • Name필드 정의는 char 1개 이지만, 사실상 크기에 제한이 없으며 각자의 사이즈에 맞게 할당되는 듯
  • 24. IMAGE_IMPORT_BY_NAME Hint • 라이브러리에서 함수의 고유 번호 • 함수 찾을 때 부하를 줄이는 용도로 이용됨
  • 25. IMAGE_IMPORT_BY_NAME Name • 함수의 이름 • Name필드 정의는 char 1개 이지만, 사실상 크기에 제한이 없으며 NULL을 기준으로 종료를 알린다.
  • 26. IMAGE_IMPORT_DESCRIPTOR TimeDateStamp • 시간과 날짜를 나타내는 타임 스탬프지만 실제 시간과는 상관이 없음 • IMAGE_IMPORT_DESCRIPTOR가 가리키는 해당 DLL이 바인딩 과정을 거치기 전에는 항상 0, 완료된 후에는 -1 • 바인딩이란? • 로더가 라이브러리를 로드하고, IAT에 값을 기록하는 것(뒤에서 자세히 다룸)
  • 27. IMAGE_IMPORT_DESCRIPTOR ForwarderChain • IMAGE_IMPORT_DESCRIPTOR가 가리키는 해당 DLL이 바인딩 과정을 거치기 전에는 항상 0, 완료된 후에는 -1 • DLL이 또 다른 DLL과 연관이 있을 때 이용
  • 28. IMAGE_IMPORT_DESCRIPTOR Name • 라이브러리 파일 이름 문자열의 포인터(RVA) • 포인터를 따라가면 dll의 이름을 구할 수 있다. • 아래는 RAW를 계산하여 찾은 것
  • 29. IMAGE_IMPORT_DESCRIPTOR FirstThunk • 해당 DLL의 IAT (Import Address Table)의 시작 주소(RVA)
  • 30. Import Address Table (IAT) RAW를 계산하여 파일에서 찾음
  • 31. Import Address Table (IAT) IAT • 실제 함수의 주소가 저장되는 테이블 • PE 로더가 프로그램을 로딩하며 덮어 씀 • 파일에서는 INT와 같은 값을 저장하곤 하지만 로딩된 후 값이 덮어써 짐
  • 32. Import Address Table (IAT) PE 이미지의 메모리 덤프 왼쪽은 INT, 오른쪽은 IAT IAT의 값이 실제 함수의 주소로 덮어써진 것을 확인할 수 있음
  • 33. Import Address Table (IAT) 맨 처음 값인 77AA45F5로 이동해 보았다. 해당 함수의 코드를 찾을 수 있다.
  • 34. Import Address Table (IAT) 실제로 어떻게 함수가 호출되는가 예를 보자. 다음은 printf을 호출하는 모습이다. printf는 msvcrt dll에 속한다는 것을 알 수 있다. Ollydbg 옵션을 해제하여 symbolic address를 보이지 않도록 설정했다. printf를 호출하기 위해 0040285C를 호출한다.
  • 35. Import Address Table (IAT) PE viewer로 import하는 dll의 정보를 찾아보았다. 여태까지는 파일을 한 번 직접 보기 위하여 실제 파일을 까 보았지만 앞으로는 PE viewer 프로그램을 자주 사용할 것이다. 위는 IMAGE_IMPORT_DESCRIPTOR에서 읽어온 dll의 정보이고, 아래는 그 dll과 관련된 INT의 정보이다. 여태까지 예제로 본 것은 KERNEL32.dll이었는데, printf는 msvcrt.dll에 속한다.(헷갈리지 말자) 해당 dll의 정보를 파일에서 찾아보자.
  • 36. Import Address Table (IAT) 위의 PE viewer를 참고하여 찾은 msvcrt.dll의 정보이다. msvcrt.dll의 INT msvcrt.dll의 IAT
  • 37. Import Address Table (IAT) 다시 코드로 돌아와서, call하는 0040285C를 살펴보았다. 40285C에는 또 다른 코드, JMP [4071D4] 가 있다. 이는 ‘4071D4에 저장된 주소’로 점프하라는 코드이다.
  • 38. Import Address Table (IAT) 4071D4가 어디인지 찾아보자. 이는 mscvrt.dll의 IAT에 속한다. 4071D4에 저장된 값은 7594C5B9이다.
  • 39. Import Address Table (IAT) 점프 코드를 실행하면 7594C5B9로 점프한다. 이는 printf함수의 코드이다. 이렇게 함수에 접근하기 위하여 IAT에 저장된 값을 이용한다는 것을 확인할 수 있다.
  • 40. IAT 바인딩 과정 1. IMAGE_IMPORT_DISCRIPTOR(IID)의 Name 멤버를 읽어서 라이브러리의 이름 문자열(ex. “kernel32.dll”)을 얻는다. 2. 해당 라이브러리를 로딩한다. (불러온다) 3. IID의 OriginalFirstThunk 멤버를 읽어서 INT 주소를 얻는다. 4. INT에서 배열의 값을 하나씩 읽어 해당 IMAGE_IMPORT_BY_NAME 주소(RVA)를 얻는다. 5. IMAGE_IMPORT_BY_NAME의 Hint(Ordinal) 또는 Name 항목을 이용하여 해당 함수의 시작주 소를 얻는다. 6. IID의 FirstThunk 멤버를 읽어서 IAT 주소를 얻는다. 7. 해당 IAT 배열 값에 위에서 구한 함수 주소를 입력한다. 8. INT 배열의 끝까지(NULL을 만날 때까지) 4~7을 반복한다.
  • 41. IAT 바인딩 과정 IMAGE_IMPORT_DISCRIPTOR Name DLL 이름 얻기 DLL 파일에서 정보 불러오기
  • 42. IAT 바인딩 과정 IMAGE_IMPORT_DISCRIPTOR Name DLL 이름 얻기 DLL 파일에서 정보 불러오기 OriginalFirstThunk INT 접근 IMAGE_IMPO RT_BY_NAME 주소 얻기
  • 43. IAT 바인딩 과정 IMAGE_IMPORT_DISCRIPTOR Name DLL 이름 얻기 DLL 파일에서 정보 불러오기 OriginalFirstThunk INT 접근 IMAGE_IMPOR T_BY_NAME 얻기 Hint (Ordinal) (해당 함수 번호) Name 함수 시작 주소 구하기
  • 44. IAT 바인딩 과정 IMAGE_IMPORT_DISCRIPTOR Name DLL 이름 얻기 DLL 파일에서 정보 불러오기 OriginalFirstThunk INT 접근 IMAGE_IMPOR T_BY_NAME 얻기 Hint (Ordinal) (해당 함수 번호) Name 함수 시작 주소 구하기 FirstThunk IAT 접근 IAT 기록 다 기록할 때까지 반복
  • 47. IMAGE_EXPORT_DIRECTORY • 함수를 다른 프로그램에서 불러 쓸 수 있도록 하기 위한 구조체이다. • .edata나 .rdata에 있다. • .edata는 함수 export를 위한 섹션이다. • Export하지 않는 프로그램은 관련 없음 • DLL에서 중요 • .edata대신 .rdata 섹션에 있을 수도 있다. • 앞에 r이 붙은 섹션 이름은 보통 read only 섹션을 의미한다. • API를 제공하여 프로그램이 연동되게 하는 경우 EXE에도 Export 관련 정보가 있을 수 있다. • EAT라는 매커니즘을 이용한다. • EAT는 자신이 제공하는 함수에 대한 것이므로, IAT처럼 여러 개 있지 않다. • 많은 dll을 대상으로 하는 것이 아니기 때문에 • IMAGE_EXPORT_DIRECTORY 구조체가 PE파일에 하나만 존재한다.
  • 49. IMAGE_EXPORT_DIRECTORY Characteristics • 이 필드는 사용되지 않으며, 0으로 설정된다.
  • 51. IMAGE_EXPORT_DIRECTORY Major/MinorVersion • 파일의 버전을 나타내기 위한 필드이지만 실제로는 사용되지 않는다. 0으로 설정된다.
  • 52. IMAGE_EXPORT_DIRECTORY Name • 해당 DLL의 이름을 나타내는 아스키 코드 문자열의 시작 주소(RVA)
  • 53. IMAGE_EXPORT_DIRECTORY Base • 내보낸 함수들에 대한 서수의 시작 번호 • 내보내는 함수의 서수가 차례대로 3, 4, 5면 이 필드 값은 3이 된다.
  • 54. IMAGE_EXPORT_DIRECTORY NumberOfFunctions • 실제 export하는 함수 개수 • AddressOfFunctions 필드가 가리키는 RVA 배열의 원소 개수와 같다 • 이 값은 NumberOfName과 다를 수도 있다.
  • 55. IMAGE_EXPORT_DIRECTORY NumberOfNames • Export 함수 중에서 이름을 가지는 함수 개수 • NumberOfFunctions과 같거나 작음 • AddressOfNames과 AddressOfNameOrdinals 필드가 가리키는 RVA 배열의 원소 개수이다 .
  • 56. IMAGE_EXPORT_DIRECTORY AddressOfFunctions • Export하는 함수들의 함수 포인터에 대한 RVA를 가진 배열 • 함수들의 시작 위치 배열의 주소 • 각각 내보낸 함수에 대한 진입점이 됨 • 함수의 시작점 주소이니까 • 원소 개수는 NumberOfFunctions
  • 57. IMAGE_EXPORT_DIRECTORY AddressOfNames • 내보낸 함수들의 이름을 가리키는 RVA를 가진 배열 • 함수 이름 배열의 주소 • 원소 개수는 NumberOfNames
  • 58. IMAGE_EXPORT_DIRECTORY AddressOfNameOrdinals • 서수 배열에 대한 포인터(RVA) • 원소의 개수는 NumberOfNames • 이 서수 배열의 최초 엔트리 값은 항상 0 • 각 원소에 Base 필드의 값을 더하면 정확한 서수 값을 획득 • Offset과 비슷
  • 59. IMAGE_EXPORT_DIRECTORY • 찾고자 하는 DLL의 이름을 찾고, AddressOfNames 배열의 몇 번째 인덱스에서 그 이름을 찾았는지 알아낸다. • 위에서 찾은 인덱스와 같은 인덱스를 이용하여 AddressOfNameOrdinals 배열에 접근하여 저장된 값을 구한다. • 이 값은 AddressOfFunctions의 인덱스이다. • 위에서 찾은 AddressOfFunctions의 인덱스를 이용하여 AddressOfFunctions 배열에 접근한다. • 함수 포인터를 얻을 수 있다. AddressOfNames RVA RVA RVA RVA “FuncA” “FuncB” “FuncC” “FuncD” AddressOfNameOrdinals 0 2 3 4 FuncA 코드 <index 2> AddressOfFunctions RVA null RVA RVA RVA FuncB 코드 FuncC 코드 FunD 코드
  • 60. IMAGE_EXPORT_DIRECTORY • DLL을 이용하기 위해 GetProcAddress 함수를 호출하면, 함수 이름을 찾고, 그에 해당하는 주소를 찾아 반환한다. • 서수를 이용하여 GetProcAddress를 호출할 수도 있다. 이 때는 서수를 이용하여 찾는다. (이름 찾는 것보다 더 빠르다) • DLL을 이용하는 PE에 적힌 INT를 읽고, 이름이나 서수를 알아내어 해당 DLL파일의 EAT를 읽어 원하는 함수를 찾은 후, IAT에 주소를 써 준다.
  • 61. 과제 • 직접 찾아보기 • PE viewer 업데이트
  • 62. 직접 찾아보기 • printf(“Hello world!”); 프로그램을 만들고, 직접 INT와 IAT를 찾아보자. • PPT를 보고 따라해 보자. • 여기저기 뒤적거려보고, 주소들을 따라가보면 좋다. • 직접 만든 DLL의 함수가 이용되는 모습을 보는 것도 좋은 경험이다.
  • 63. PE viewer 업데이트 • Import 하는 함수 정보도 알아낼 수 있도록 PE viewer를 업데이트 해보자. • Dll 이름과 그 Dll에서 import할 함수 이름을 인쇄하도록 하자.
  • 65. 참고 사이트 • IAT 자세히 살펴보기 • http://reversecore.com/23 • http://yokang90.tistory.com/26 • EAT 자세히 살펴보기 • http://blog.naver.com/skddms/110180144875 • http://reversecore.com/24