본문 바로가기
Reversing/리버싱 핵심 원리

[리눅스 핵심 원리] 23장, DLL 인젝션

by Y06 2021. 12. 2.

다른 프로세스에 침투하는 가장 쉽고 강력한 방법인 DLL 인젝션에 대해 살펴보자! DLL 인젝션 기법을 통하여 API 후킹, 프로그램 기능 개성 및 버그 패치 등의 작업을 수행할 수 있다.

 

DLL 인젝션

DLL 인젝션이란 실행 중인 다른 프로세스에 특정 DLL 파일을 강제로 삽입하는 것이라고 말할 수 있다. 조금 더 기술적으로 표현하자면 다른 프로세스에게 LoadLibrary() API를 스스로 호출하도록 명령하여 사용자가 원하는 DLL을 로딩(Loading)하는 것이다. DLL 인젝션이 일반적인 DLL 로딩과 다른 점은 로딩 대상이 되는 프로세스가 나 자신이냐 아니면 다른 프로세스냐 하는 것이다.

 

DLL 인젝션 개념

notepad 프로세스에 myhack.dll을 강제로 삽입했다. 이처럼 notepad.exe 프로세스에 로딩된 myhack.dll은 notepad.exe 프로세스에 이미 로딩된 DLL들(kernel32.dll, user32.dll 등)과 마찬가지로 notepad.exe 프로세스 메모리에 대한 (정당한) 접근 권한을 가진다. 따라서 사용자가 원하는 어떤 일이라도 수행할 수 있다. (예, notepad에 통신기능을 추가하여 메신저나 텍스트 웹 브라우저 등의 기능을 추가할 수 있다)

 

[참고]

DLL(Dynamic Linked Library)

프로세스에 DLL이 로딩되면 자동으로 DllMain() 함수가 실행된다. 따라서 DllMain()에 사용자가 원하는 코드를 추가하면 DLL이 로딩될 때 자연스럽게 해당 코드가 실행된다. 이 특성을 이용하면 기존 애플리케이션의 버그를 수정하거나 새로운 기능을 추가할 수 있다.

 

DLL 인젝션 활용 예

LoadLibrary() API를 이용해서 어떤 DLL을 로딩하면 해당 DLL의 DllMain() 함수가 실행된다. DLL 인젝션의 동작원리는 외부에서 다르 프로세스로 하여금 LoadLibrary() API를 호출하도록 만드는 것이기 때문에(일반적인 DLL로딩과 마찬가지로) 강제 삽입된 DLL의 DllMain() 함수가 실행된다. 또한 삽입된 DLL은 해당 프로세스의 메모리에 대한 접근 권한을 갖기 때문에 사용자가 원하는 다양한 일(버그 패치, 기능 추가, 기타)을 수행할 수 있다.

 

(1) 기능 개선 및 버그 패치

[기능 개선] 및 [버그 패치]에 사용될 수 있다. 만약 어떤 프로그램의 소스코드가 없거나 수정이 여의치 않을 때 DLL 인젝션을 사용하여 전혀 새로운 기능을 추가(PluhIn 개념)하거나, 문제가 있는 코드와 데이터를 수정할 수 있다.

 

(2) 메시지 후킹

Windows OS에서 기본으로 제공되는 메시지 후킹(Message Hooking) 기능도 일종의 DLL 인젝션 기법이라고 볼 수 있다. 이 경우는 등록된 후킹 DLL을 OS에서 직접 인젝션시켜준다는 차이점이 있다.

 

(3) API 후킹

실제 개발 프로젝트에도 많이 사용되는 API 후킹을 할 때 DLL 인젝션 기법이 많이 사용된다. 후킹 함수를 DLL 형태로 만든 후 후킹을 원하는 프로세스에 간단히 인젝션하는 것만으로 API 후킹이 완성된다. 이 역시 삽입된 DLL은 해당 프로세스의 메모리에 대한 접근 권한을 가지고 있다는 특성을 이용하였다.

 

(4) 기타 응용 프로그램

주로 PC 사용자들을 감시하고 관리하기 위한 애플리케이션들에서 사용되기도 한다. 예를 들면 특정 프로그램(예, 게임, 주식거래, 기타)의 실행 차단, 유해사이트 접속 차단, PC 모니터링 프로그램 등이 있다. 이런 류의 차단/방지 프로그램들은 주로 관리자가 사용자를 관리/감시하기 위한 목적으로 설치된다. 하지만 DLL 인젝션 기법으로 정상 프로세스에 살짝 숨어들어가서 실행된다면, 들킬 걱정도 없고 프로세스가 종료 당할 걱정도 없다. (만약 사용자가 무리하게 Windows 시스템 프로세스를 강제로 종료하면 시스템도 같이 종료되기 때문에 결국 차단/방지라는 목적을 달성한다.)

 

(5) 악성 코드

이렇게 좋은 기술을 악성코드 제작자들이 그냥 놔둘 리가 없다. DLL 인젝션 기법을 자신들의 악성코드에 적극적으로 활용하고 있다. 정상적인 프로세스에 몰래 숨어들어가 백도어 포트(Backdoor port)를 열어서 외부에서 접속을 시도하거나, 키로깅 기능으로 사용자의 개인 정보를 훔치는 등의 악의적인 짓을 한다. 따하서 악성코드 제작자들이 사용하는 기법을 잘 알아야 그에 대한 대응책을 세울 수 있다.

 

DLL 인젝션 구현 방법

  • 원격 스레드 생성(CreateRemoteThread() API)
  • 레지스트리 이용(AppInt_DLLs 값)
  • 메시지 후킹(SetWindowsHookEx() API)

1) CreateRemoteThread()

[실습예제: myhack.dll]

실습 파일 복사

실습파일인 InjectDll.exe과 myhack.dll을 같은 파일 경로에 저장한다.

프로세스 ID

notepad.exe(메모장)를 실행한 후 Process Explorer(혹은 창 작업 관리자)를 실행하여 notepad.exe 프로세스의 PID(Process ID)를 알아낸다.

현재 제가 하고 있는 가상머신 Window10에서는 notepad.exe의 PID가 2072이다.

DebugView 실행

DebugView는 시스템에서 실행되는 프로세스들이 출력하는 모든 디버그 문자열(Debug String)을 가로채서 보여주는 매우 유용한 유틸리티이다.

→ 실습 예제 DLL 파일은 notepad.exe 프로세스에 성공적으로 인젝션되면 디버그 문자열을 출력하게 되는데, DebugView로 그 순간을 확인할 수 있다.

DebugView

myhack.dll 인젝션

InjectDll.exe 프로그램은 DLL 인젝션 유틸리티이다. InjectDll.exe를 실행한다.

 

DLL 인젝션 확인

myhack.dll 파일이 notepad.exe 프로세스에 성공적으로 인젝션되었는지 검증을 해보자!

먼저 DebugView의 로그를 살펴본다.

DebugView에 디버그 문자열이 출력되었다. 이 문자열은 PID 2072 프로세스에서 출력한 문자열이다. PID 2072가 바로 우리가 myhack.dll을 인젝션한 notepad.exe 프로세스이다. 즉 myhack.dll이 정상적으로 인젝션되어서 DllMain() 함수의 OutputDebugString() API가 호출된 것이다.

Process Explorer에서도 myhack.dll이 인젝션된 것을 확인할 수 있다. 

dll을 따로 검색해서 확인도 가능하다.

결과를 확인하면 다음과 같이 index.html이 생긴 것을 볼 수 있다.

클릭하면 다음과 같은 화면이 뜬다.

 

2) AppInit_DLLs

DLL 인젝션을 하기 위한 두 번째 방법으 레지스트리(Registry)를 이용하는 것이다. Windows 운영체제에서 기본으로 제공하는 AppInit_DLLs와 LoadAppInit_DLLs라는 이름의 레지스트리 항목이 있다.

레지스트리편집기

AppInit_DLLs 항목에 인젝션을 원하는 DLL 경로 문자열을 쓰고 LoadAppInit_DLLs 항목의 값을 1로 변경한 후 재부팅하면, 실행되는 모든 프로세스에 해당 DLL을 인젝션 한다. 너무 간단하지만 강력한 기능이다.

 

[실습예제: myhack2.dll]

적당한 위치에 넣는다.

레지스트리 값 입력

AppInit_DLLs 항목에 인젝션을 원하는 DLL 경로 문자열을 넣는다.

LoadAppInit_DLLs 항목의 값을 1로 변경한다.

재부팅

변경한 항목을 적용하기 위하여 시스템을 재부팅한다. 재부팅이 완료되었으면 Process Explorer를 이용해서 myhack.dll이 (user32.dll을 로딩한) 모든 프로세스에 인젝션 되었는지 확인한다.

myhack2.dll이 성공적으로 인젝션 되었다. 그런데 인젝션된 myhack2.dll은 아무 동작을 하고 있지 않는다.

 

[참고]

AppInit_DLLs 레지스트리 키는 너무나 강력해서 거의 모든 프로세스에 DLL을 인젝션시킨다. 만약 인젝션되는 DLL에 문제가 있다면 Windows 부팅이 안 되는 상황이 발생할 수 있으니, AppInit_DLLs 기법을 하기 전에는 철저한 테스트가 필요하다.

 

3) SetWindowsHookEx()

DLL 인젝션을 하기 위한 세 번째 방법은 메시지 후킹을 이용하는 것이다. SetWindowsHookEx() API를 이용하여 메시지 훅을 설치하면 OS에서 hook procedure를 담고 있는 DLL을 프로세스에게 강제로 인젝션한다.