DLL 인젝션
1. 개요
DLL 인젝션은 실행 중인 프로세스에 동적 링크 라이브러리(DLL) 코드를 삽입하는 기술이다. 윈도우 및 유닉스 계열 운영체제에서 다양한 방식으로 구현될 수 있으며, 애플리케이션의 기능 확장, 동작 변경, 보안 취약점 분석, 악성코드 분석 등 다양한 목적으로 활용된다. 윈도우에서는 레지스트리, CreateRemoteThread 함수, 윈도우 후킹 등을 통해 DLL 인젝션을 수행하며, 유닉스 계열에서는 LD_PRELOAD 환경 변수를 사용하거나 디버거 기반 기술을 활용한다.
| 이름 | DLL 인젝션 |
|---|---|
| 다른 이름 | DLL 삽입 DLL 주입 |
| 종류 | 소프트웨어 악용 기술 |
|---|---|
| 목적 | 다른 프로세스에 코드 삽입 및 실행 |
| 작동 방식 | 대상 프로세스의 주소 공간에 DLL (동적 연결 라이브러리)을 로드하여 실행 |
|---|---|
| 사용되는 API (윈도우) | CreateRemoteThread LoadLibrary WriteProcessMemory |
| 다른 방법 | Windows Hook (윈도우 후크) 사용 SetWindowsHookEx 함수 사용 |
| 합법적 사용 | 디버깅 API 후킹 |
|---|---|
| 악의적 사용 | 맬웨어 삽입 프로세스 은닉 키로깅 |
| 탐지 방법 | 메모리 분석 API 호출 추적 |
|---|---|
| 방지 방법 | 코드 서명 액세스 제어 |
| 관련 자료 | API 후킹 동적 연결 라이브러리 (DLL) |
|---|
-
DLL 인젝션 -
후킹
후킹은 소프트웨어 실행 중 특정 위치에 삽입되어 프로그램의 흐름을 가로채거나 수정하는 기술로, 운영체제 수준의 이벤트 처리부터 응용 프로그램의 함수 호출 가로채기까지 활용되며, API 후킹, DLL 인젝션 등 여러 기술과 함께 사용된다. -
스레드 -
멀티스레딩
멀티스레딩은 프로세스 내에서 여러 스레드를 동시 실행하여 처리 능력을 향상시키는 기술로, 응답성 향상과 자원 공유 등의 장점이 있지만, 자원 간섭과 소프트웨어 복잡성 증가 등의 단점도 존재하며, 다양한 모델과 구현 방식, 스레드 스케줄러, 가상 머신 활성화 가능성 등을 고려해야 한다. -
스레드 -
동시 멀티스레딩
동시 멀티스레딩(SMT)은 슈퍼스칼라 구조 기반으로 한 클럭 사이클 내에 여러 스레드의 명령어를 동시에 실행하여 CPU 자원 활용률을 높이는 기술이지만, 자원 경합, 성능 저하, 보안 취약점 등의 단점도 있으며, 인텔 하이퍼 스레딩이 대표적이다. -
윈도우 관리 -
블루스크린
블루스크린은 윈도우 운영체제에서 발생하는 치명적인 오류로, 컴퓨터 작동을 멈추고 파란색 화면에 오류 메시지를 표시하며, 하드웨어 또는 소프트웨어 문제로 인해 발생하고, 시스템 복원, 안전 모드 부팅 등의 방법으로 대처한다. -
윈도우 관리 -
파워셸
파워셸은 마이크로소프트에서 개발한 작업 자동화 솔루션으로, 명령줄 셸과 스크립트 언어의 기능을 결합하여 윈도우 시스템 관리를 위해 설계되었으며, .NET 프레임워크 기반의 객체 지향적 특징을 갖고 다양한 플랫폼에서 자동화 스크립트 작성 및 실행, 시스템 구성 관리 등에 활용된다.
2. 운영체제별 DLL 인젝션 방법
DLL 인젝션은 운영체제별로 다른 방식으로 구현된다.
2.1. 마이크로소프트 윈도우
마이크로소프트 윈도우(Microsoft Windows) 운영체제는 DLL 인젝션을 위한 여러 가지 방법을 제공한다.
* 레지스트리의 `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs` 항목에 나열된 DLL은 User32.dll을 로드하는 모든 프로세스에서 로드된다. 이 DLL들은 프로세스 초기화 과정에서 로드된다. 윈도우 비스타 이후 AppInit_DLLs는 기본적으로 비활성화되어 있다. 윈도우 7부터는 코드 서명을 지원한다.
* `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDLLs` 레지스트리 키에 나열된 DLL들은 `CreateProcess`, `CreateProcessAsUser`, `CreateProcessWithLogonW`, `CreateProcessWithTokenW`, `WinExec` 등의 Win32 API 함수를 호출할 때 로드된다.
* `CreateRemoteThread`와 같은 프로세스 조작 함수나, AtomBombing과 같은 코드 인젝션 기술을 사용하면 프로그램 실행 중에 DLL을 주입할 수 있다.
* `SetWindowsHookEx`와 같은 윈도우즈 후킹 함수를 사용할 수 있다.
* `SuspendThread` 또는 `NtSuspendThread` 함수로 모든 스레드를 일시 중단시킨 후, `SetThreadContext` 또는 `NtSetContextThread` 함수로 기존 스레드의 컨텍스트를 변경하여 주입된 코드를 실행할 수 있다.
* 전체 경로를 지정하지 않고 `LoadLibrary` 또는 `LoadLibraryEx` 함수를 호출하는 윈도우 및 응용 프로그램의 설계상 허점을 이용할 수 있다.
* 응용 프로그램에 지정된 DLL을 원래 DLL과 동일한 함수를 내보내는 가짜 DLL로 대체할 수 있다.
2.1.1. AppInit_DLLs 레지스트리 키
마이크로소프트 윈도우 레지스트리 키 중 `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs`에 DLL 경로를 등록하면, User32.dll을 로드하는 모든 프로세스에 해당 DLL이 자동으로 로드된다.
이는 시스템 전체에 영향을 주는 강력한 기능이지만, 악용될 소지가 있어 보안에 취약하다. 윈도우 비스타부터는 AppInit_DLLs 기능이 기본 설정으로 비활성화되었다.
윈도우 7부터는 코드 서명(code signing) 지원이 추가되어, 서명되지 않은 DLL은 로드되지 않도록 보안이 강화되었다. 윈도우 8부터는 보안 부팅(Secure Boot)이 활성화되면 AppInit_DLLs 기능이 완전히 비활성화된다.
2.1.2. AppCertDLLs 레지스트리 키
마이크로소프트 윈도우 레지스트리 키 `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDLLs` 아래에 DLL 경로를 등록하면, CreateProcess, CreateProcessAsUser, CreateProcessWithLogonW, CreateProcessWithTokenW, WinExec 같은 특정 Win32 API 함수를 호출하는 프로세스에 해당 DLL이 로드된다. 이는 윈도우 10에서 합법적인 DLL 인젝션을 사용하는 방법이며, DLL은 유효한 인증서로 코드 서명되어야 한다.
2.1.3. CreateRemoteThread 함수
마이크로소프트 윈도우는 실행 중인 프로그램에 DLL을 삽입하기 위해 `CreateRemoteThread`라는 프로세스 조작 함수를 제공한다. DLL 인젝션은 다음 단계를 거쳐 수행된다.
# 타겟 프로세스의 핸들을 얻는다. 핸들은 프로세스를 생성하거나, 이미 존재하는 프로세스(예: 예측 가능한 타이틀을 가진 윈도우)를 이용하거나, 실행 중인 프로세스 목록에서 대상 실행 파일 이름을 조사하여 얻을 수 있다.
# 타겟 프로세스에 메모리를 할당하고, 할당받은 메모리에 인젝트될 DLL의 이름을 쓴다.
## 만약 타겟 프로세스 안에 적절한 DLL 이름이 이미 존재한다면 이 단계는 건너뛸 수 있다. 예를 들어, 프로세스가 'User32.dll', 'GDI32.dll', Kernel32.dll 또는 '32.dll'로 끝나는 다른 라이브러리와 링크되어 있다면, 이를 활용할 수 있다. 이 방법은 과거 DLL 인젝션 방어 기법에 대해 효과적이었다.
# 타겟 프로세스에 새로운 스레드를 생성한다. 이때 스레드의 시작 주소는 `LoadLibrary` 함수의 주소로, 인수는 타겟에 업로드되는 문자열(DLL 이름)의 주소로 설정한다.
## `LoadLibrary`에서 새 스레드를 시작하는 대신, 실행 가능한 코드를 타겟에 직접 넣고 실행하는 것도 가능하다.
# 운영체제는 삽입된 DLL의 `DllMain`을 호출한다.
## 이 과정에서 DLL_THREAD_ATTACH 알림(스레드 시작 시 모든 로드된 모듈에 보내짐) 때문에 타겟 프로세스에게 발견될 수 있다.
2.1.4. 윈도우 후킹
마이크로소프트 윈도우에서는 `SetWindowsHookEx` 같은 윈도우 후킹 함수를 사용할 수 있다. 이 함수를 이용하면 특정 이벤트가 발생했을 때 DLL이 로드되도록 설정할 수 있다.
2.1.5. 스레드 컨텍스트 수정
마이크로소프트 윈도우에서 `SuspendThread` 또는 `NtSuspendThread` 함수를 사용하여 모든 스레드를 중지시키고, `SetThreadContext`나 `NtSetContextThread` 함수를 사용하여 존재하는 응용 프로그램 내 스레드의 컨텍스트를 수정하여 DLL을 로드할 수 있다.
2.1.6. DLL 경로 악용
마이크로소프트 윈도우에서 애플리케이션이 DLL의 전체 경로를 지정하지 않고 `LoadLibrary` 함수를 호출하는 경우, DLL 검색 경로를 조작하여 악의적인 DLL을 로드할 수 있다.
2.1.7. DLL 대체
마이크로소프트 윈도우에서 DLL 인젝션은 응용 프로그램에 명시된 DLL을 원본과 똑같은 함수 호출을 내보내게 구현된 로그 교체로 대체하는 방식으로 수행할 수 있다.
2.2. 유닉스 계열
유닉스 계열 운영체제에서는 `LD_PRELOAD` 환경 변수를 사용하여 DLL (공유 라이브러리) 인젝션을 수행할 수 있다. macOS에서는 `DYLD_INSERT_LIBRARIES`와 `DYLD_FORCE_FLAT_NAMESPACE` 환경 변수를 사용하여 비슷한 작업을 수행할 수 있다.
2.2.1. LD_PRELOAD 환경 변수
유닉스 계열 운영체제(ld.so (on BSD) 또는 ld-linux.so (on 리눅스) 기반)에서 동적 링커를 사용할 때, `LD_PRELOAD` 환경 변수에 라이브러리 경로를 지정하면 새로운 프로세스에 해당 라이브러리를 링크할 수 있다. 이는 프로세스 안에서 전역적 또는 개별적으로 설정할 수 있다.
예를 들어, 배시 셸에서 다음 명령어를 사용하면 "prog" 명령어 실행 시 "test.so" 공유 라이브러리가 함께 링크된다.
`LD_PRELOAD="./test.so" prog`
이러한 라이브러리는 GCC에서 -fpic 또는 -fPIC 옵션으로 컴파일하고, `-shared` 옵션으로 링크하여 생성할 수 있다. 이 라이브러리는 프로그램에서 선언된 외부 심볼에 접근할 수 있다.
디버거 기반 기술도 사용 가능하다.
2.2.2. 디버거 기반 기술
유닉스 계열 시스템에서는 디버거 기반 기술을 사용하여 DLL 인젝션을 수행할 수도 있다.
3. DLL 인젝션 활용 사례
DLL 인젝션은 다음과 같은 다양한 목적으로 활용될 수 있다.
* 애플리케이션 기능 확장 및 동작 변경: 자세한 내용
* 설정 정보 접근 처리 변경: 자세한 내용
* DLL 함수 호출 감시 및 로깅: 자세한 내용
* 마이크로소프트 윈도우즈(Microsoft Windows)에서 DLL 강제 로드 및 실행 방법:
* 레지스트리 항목 이용.
* 프로세스 조작 함수 또는 코드 인젝션 기술 사용.
* 윈도우즈 후킹 호출.
* 응용 프로그램 기존 스레드 컨텍스트 수정.
* 윈도우즈 및 응용 프로그램 설계 제한 악용.
* 운영 체제 수준 심 이용.
* 악성 대체 DLL 사용.
3.1. 애플리케이션 기능 확장 및 동작 변경
DLL 인젝션을 통해 애플리케이션의 기능을 확장하거나, 기존 동작을 변경할 수 있다.
* 애플리케이션 작동 환경 위장: 실제로는 Windows 7에서 작동하고 있지만, 애플리케이션의 문의에는 'Windows XP에서 작동하고 있다'라고 위장한 응답을 반환하는 것이 가능하다. 많은 운영 체제에는 가동 환경 정보를 제공하는 DLL 내의 서비스 함수가 있는데, 이 함수를 후킹하여 원래와는 다른 응답을 반환하는 처리 루틴을 실행시키는 방식이다.
* 설정 정보 접근 처리 변경: 포터블 애플리케이션에서 많이 사용된다. 작동을 위해 레지스트리 등에 읽고 쓰기가 필수적인 애플리케이션을 쓰기 불가 매체 (CD-ROM 등) 상에서 작동시키는 경우에 활용된다.
* DLL 함수 호출 감시·기록: 감시·기록하고 싶은 DLL 함수를 후킹하여, 애플리케이션이 DLL 함수를 호출했을 때, 해당 로그를 기록한 뒤 원래의 DLL로 처리를 넘긴다. 이를 통해 DLL 함수의 호출을 기록하고, 디버그나 성능 측정 등에 이용할 수 있다.
3.2. 설정 정보 접근 처리 변경
포터블 애플리케이션에서 DLL 인젝션이 많이 사용된다. DLL 인젝션을 이용하면 레지스트리 등에 읽고 쓰기가 필수적인 애플리케이션을 쓰기 불가 매체 (CD-ROM 등) 상에서 작동시킬 수 있다. DLL 인젝션을 통해 레지스트리 대신 파일에 설정을 저장하도록 동작을 변경할 수 있다.
3.3. DLL 함수 호출 감시 및 로깅
감시·기록하고 싶은 DLL 함수를 후킹하여, 애플리케이션이 DLL 함수를 호출했을 때 해당 로그를 기록한 뒤 원래의 DLL로 처리를 넘긴다. 그렇게 함으로써 DLL 함수의 호출을 기록하고, 디버그나 성능 측정 등에 이용할 수 있다.
4. 샘플 코드
(샘플 코드는 제공되지 않았으므로, 이전 출력과 동일합니다.)
샘플 코드는 제공되지 않았습니다.