04 dll 분석
TRANSCRIPT
Writing by Ilsun Choi 2
Index1. EXE 와 DLL
1) 공통점2) 차이점
2. DLL 의 번지 계산법3. 재배치를 고려한 방법4. 번지 고정5. 익스포트 함수6. DllAttach/DllDetach 찾기7. 패킹된 DLL 의 DllMain() 찾기8. DisableThreadLibraryCalls 로 찾기
E-mail : [email protected]
Writing by Ilsun Choi 3
1. EXE 와 DLL > 1) 공통점 DLL 에도 같은 PE Header 가 존재
DLL 역시 C/C++ 로 프로그래밍 구조가 비슷하다 .
E-mail : [email protected]
Writing by Ilsun Choi 4
1. EXE 와 DLL > 2) 차이점 WinMain() 대신 DllMain() 이 존재
DLL 은 주로 Export 함수 /EXE 는 주로 Import 함수를 가짐
DLL 파일은 하나의 EXE 에서 여러 개를 로딩할 수 있음
DLL 파일끼리 주소가 겹칠 경우 재배치를 함
E-mail : [email protected]
Writing by Ilsun Choi 5
2. DLL 의 번지 계산법 [1/3] IDA 로 디스어셈했을 때와 DLL 이 실제 메모리에 올라갔을 때 주소가 다르기에 초보들이 주로 혼동
단지 Image Base 가 달라졌기 때문 !
PE View 로 본 kernel32.dll(0x7C800000) 와 TestDLL2.dll( 기본 설정 : 0x10000000) 의 Im-age Base
E-mail : [email protected]
Writing by Ilsun Choi 6
2. DLL 의 번지 계산법 [2/3] 직접 제작한 DLL 은 0x10000000 으로 기본 고정되어 있기 때문에 겹칠 수 있음
##TIP2 를 참고하여 TestDLL3 를 제작하여 테스트함 ( 소스는 TestDLL2 와 같다 )
TestDLL3 역시 0x10000000 Image Base 를 가지고 있으나 로딩 시에는 다른 주소로 로딩됨
E-mail : [email protected]
Writing by Ilsun Choi 7
다음과 같은 방법으로 번지 계산이 가능하다 .( 저자의 글로는 너무 간단하여 계산이라고 하기에 부끄럽다 함 )
앞서 실습한 TestDLL3.dll 의 경우
E-mail : [email protected]
2. DLL 의 번지 계산법 [3/3]
Base Address + Base of Code0x10000000 + 0x1000( 파일 )0x003B000 + 0x1000
ex) 0x10001000 에 로딩되는 코드는 0x003B1000 으로 가면 찾을 수 있다 !
Writing by Ilsun Choi 8
3. 재배치를 고려한 방법 재배치된 DLL 파일에서 어떤 변화가 일어났는지 살펴보자 .
1. push 문
2. CALL 문
E-mail : [email protected]
Writing by Ilsun Choi 9
4. 번지 고정 DLL 파일에 다음 코드를 추가하면 DLL Base Address 를 고정시킬 수 있다 .
pragma comment(linker, “/base:0x23400000 /fixed”)
로딩 주소에 다른 DLL 이 있다면 제대로 로딩되지 않을 수 있기 때문에 추천하지 않음
E-mail : [email protected]
Writing by Ilsun Choi 10
5. 익스포트 함수 EXE 파일은 Entry Point(EP) 가 하나뿐이지만 DLL 의 경우는 익스포트 함수의 수만큼 존재
Dependency Walker 로 분석한 TESTDLL2.DLL 함수의 수 : 2 개
IDA 를 통해 확인한 EP : Export 함수 (2) + DLLMain(1) = 3
E-mail : [email protected]
Writing by Ilsun Choi 11
6. DllAttach/DllDetach 찾기 [1/5] DLL 이 로딩되자마자 해야 할 작업이 있다면 DllMain() 에 코드를 삽입한다 .
DLLMain() 의 원형
fdwReason 의 값에 따라 분기
E-mail : [email protected]
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, LPVOID lpRes);
Writing by Ilsun Choi 12
다음과 같이 DllMain 을 작성하여 컴파일
E-mail : [email protected]
6. DllAttach/DllDetach 찾기 [2/5]
Writing by Ilsun Choi 13
DllMain() : Switch 분기 ( 책과 많이 다름 )
E-mail : [email protected]
6. DllAttach/DllDetach 찾기 [3/5][EBP+C] 로부터 EAX 에 fdwReason 값을
받음EAX 값을 [EBP-8] 로 옮긴 후
0 이나 1 과 같은지 비교하여 분기한다 .
Writing by Ilsun Choi 14
DllMain() : Switch 분기 ( 책과 많이 다름 )
E-mail : [email protected]
6. DllAttach/DllDetach 찾기 [4/5]
0 과 같으면 PROCESS_ATTACH 를 출력
1 과 같으면 PROCESS_DETACH 를 출력
어떤 값과도 같지 않으면 무조건 분기문 (JMP)에 의해서 함수 에필로그를 진행
Writing by Ilsun Choi 15
IDA 를 통해 DllMain() Text 를 검색하면 바로 찾을 수 있다 .
E-mail : [email protected]
6. DllAttach/DllDetach 찾기 [5/5]
Writing by Ilsun Choi 16
7. 패킹된 DLL 의 DllMain() 찾기 패킹된 바이너리인 경우에는 DllMain() 을 수동으로 찾아야 한다 .
OllyDbg 를 실행하여 CPU 창 – [ 마우스 오른쪽 ] – [Search for] – [Binary String]
“8B 44 24 08 83 E8 00 74( 책에서 나온 패턴 )” 을 입력( 실습 결과는 “ 8B 45 0C 89 45 F8 83 7D”)
E-mail : [email protected]
Writing by Ilsun Choi 17
확인을 누르면 패턴이 일치하는 지점을 찾아줌
분석이 어렵다는 데미다 (Themida) 로 패킹해도 결과는 같음 이 패턴을 피해가기 쉽지 않음
특정 기능을 위해서 어떤 코드를 사용할 수 밖에 없는 패턴을 이용함( 휴리스틱 패턴 , heuristic pattern)
E-mail : [email protected]
7. 패킹된 DLL 의 DllMain() 찾기
Writing by Ilsun Choi 18
8. DisableThreadLibraryCalls 로 찾기 DisableThreadLibraryCalls()?
DLL_THREAD_ATTACH/DLL_THREAD_DETACH 와 연관( 스레드가 생성 / 종료될 때 마다 호출 )
스레드가 생성 / 소멸을 반복한다면 DllMain() 이 반복 호출되어 , 프로세스에 부하
의도적으로 DllMain() 호출을 막는 함수가 바로 DisableThreadLibraryCalls() 이다 !
많은 개발자들이 습관처럼 이 함수를 Dll_THREAD_ATTACH 에 넣는 편이므로이 IAT 를 역추적하면 DllMain() 을 찾을 수 있음
E-mail : [email protected]