Windows 프로그래밍에서 DLL 호출 시 전체 경로를 입력하여 호출할 수도 있지만 모듈명 만으로도 호출이 가능하다. 전체 경로를 명시하지 않고 DLL을 동적으로 호출할 경우 시스템은 DLL 검색 순서에 따라 DLL을 찾는다.(DLL 검색순서 포스트 참조)

 

그런데 모듈명 만으로 DLL을 호출하게 될 경우 보안적 이슈가 발생할 수 있다.

만약 공격자가 DLL 검색 경로 중 하나의 권한을 취득할 경우 DLL 검색 경로에 악성코드가 존재하게 될 수 있다. 이를 DLL Preloading 공격 또는 Binary Planting 공격이라 부른다. 시스템이 손상당한(혹은 공격당한) 디렉토리를 검색하기 전에 적당한 DLL을 찾지 못할 경우 애플리케이션은 악성 DLL을 로드하게 된다. 애플리케이션이 administrator 권한으로 동작하게 될 경우 공격자는 로컬 권한 상승을 할 수 있다.

 

이러한 공격을 방지하기 위해 아래와 같은 방법으로 개발할 수 있다.

 

  • LoadLibrary, LoadLibraryEx, CreateProcess, ShellExecute 함수를 호출할 때 전체 경로를 명시한다.(가장 바람직하다)

  • LoadLibraryEx 함수 호출 시 LOAD_LIBRARY_SEARCH 플래그를 사용한다. 또는 SetDefaultDllDirectories 함수에 이 플래그를 사용하여 DLL 검색 순서를 다시 수립한다. AddDllDirectory 또는 SetDllDirectory 함수로 리스트를 수정할 수 있다.

    ※ Windows 7, Windows Server 2008 R2, Windows Vista, Windows Server 2008은 이러한 플래그와 함수를 사용하기 위해 KB2533623을 설치해야 한다.

    ※ SetDllDirectory는 프로세스 초기화 시 한 번만 호출한다. 프로세스 전체에 영향을 미치므로 멀티 스레드 환경에서 다른 값을 설정할 경우 정의되지 않은 동작을 할 수 있다. 특히 third-party DLL을 사용할 경우 주의해서 사용해야 한다.

  • 애플리케이션이 정확한 DLL을 호출하는 것을 보장하기 위해 DLL 리다이렉션이나 manifest를 고려한다.

  • 표준 검색 순서를 사용해야 할 경우 Safe DLL 검색모드가 활성화 되어 있도록 보장해라. 이는 사용자의 현재 디렉토리의 검색 우선순위를 낮추어 시스템이 악성 DLL보다 올바른 DLL을 먼저 찾을 수 있도록 돕는다.

  • Safe Process 검색모드가 활성화 되어 있지 않은 경우 LoadLibrary 함수에서 사용할 경로를 얻기 위해 SearchPath 함수를 사용하지 마라. Safe Process 검색모드가 활성화 되어 있지 않으면 LoadLibarary와 다른 검색 순서를 사용하게 된다. Safe Process 모드는 SetSearchPathMode로 설정 가능하다.

 

[참고문서]

https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-security

Windows에는 동일한 이름의 DLL도 여러 버전이 존재할 수 있다. 애플리케이션은 DLL의 전체 경로를 명시하거나 리다이렉션을 이용하거나 manifest를 이용하여 어느 위치에 있는 DLL을 사용할 것인지를 정할 수 있다. 만약 이러한 방법 중 어느 방법도 취하지 않는다면, 시스템은 미리 약속 된 순서로 DLL을 검색한다. 이 포스트에서는 시스템이 DLL을 검색하는 미리 약속 된 순서를 설명한다.

 

DLL 검색에 영향을 주는 요소들

- 만약 메모리에 동일한 이름의 DLL이 로드되어 있을 경우 시스템은 리다이렉션과 manifest만 확인하고 DLL을 검색하지 않는다.

- 만약 애플리케이션이 실행중인 윈도우의 Known-DLL 목록에 포함되어 있는 DLL을 로드할 경우 시스템은 DLL을 검색하지 않고 Known-DLL의 복사본을 사용한다. 현재 시스템의 Known-DLL 목록은 다음 레지스트리 경로에서 확인할 수 있다.

Known-DLL list: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs

 

데스크탑 애플리케이션의 표준 검색 순서

시스템의 DLL 검색 순서는 Safe DLL 검색모드의 활성 여부에 따라 달라진다. Safe DLL 검색모드는 사용자의 현재 디렉토리의 검색 순서를 뒤쪽으로 변경한다.

Safe DLL 검색모드는 default로 활성화 되어 있다. 이를 비활성화 하기 위해서는 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode 레지스트리의 값을 0으로 설정한다. SetDllDirectory 함수로도 검색 경로에 특정 디렉토리가 있는 동안 Safe DLL 검색모드를 비활성화 할 수 있다.

 

※ Windows XP는 Safe DLL 검색모드가 default로 비활성화 되어 있다. 이를 활성화 하기 위해서는 레지스트리를 1로 변경해야 한다.

Windows XP Service Pack 2부터 Safe DLL 검색모드가 default로 활성화 된다.

 

 

만약 Safe DLL 검색모드가 활성화되면 아래 순서로 검색을 한다.

1. 애플리케이션이 로드 된 경로

2. 시스템 디렉토리(GetSystemDirectory 함수로 얻은 경로)

3. 16-bit 시스템 디렉토리(함수로는 경로를 얻을 수 없지만 검색순서에 포함 됨)

4. Windows 경로(GetWindowsDirectory 함수로 얻은 경로)

5. 현재 경로

6. 환경변수 PATH에 존재하는 경로

 

Safe DLL 검색모드가 비활성화되면 아래 순서로 검색을 한다.

1. 애플리케이션이 로드 된 경로

2. 현재 경로

3. 시스템 디렉토리(GetSystemDirectory 함수로 얻은 경로)

4. 16-bit 시스템 디렉토리(함수로는 경로를 얻을 수 없지만 검색순서에 포함 됨)

5. Windows 경로(GetWindowsDirectory 함수로 얻은 경로)

6. 환경변수 PATH에 존재하는 경로

 

※ 중요
공격자가 검색 경로 중 하나의 권한을 취득할 경우 보안 위협이 될 수 있다.
DLL 보안 포스트를 참조하여 이러한 위협을 방지한다.

 

기타 참고사항

- Windows Store App의 경우 DLL 검색 순서가 다르다. 아래 참고 문서를 참조한다.

 

[참고 문서]

https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order

리눅스에서는 base64 명령으로 base64 인코딩, 디코딩을 쉽게 할 수 있다.

 

1.  문자열 인코딩, 디코딩

1

2

3

4

5

6

7

// base64 encoding (with new_line)

# echo 'hello world' | base64

aGVsbG8gd29ybGQK

 

// base64 decoding

# echo 'aGVsbG8gd29ybGQK' | base64 --decode

hello world

 

이 때 주의할 점은 개행(\n)이 함께 인코딩 된다는 점이다.

개행을 제외하여 인코딩을 하고자 할 경우에는 -n 옵션을 추가하여 인코딩을 한다.

1

2

3

4

5

6

7

// base64 encoding (without new_line)

# echo 'hello world' | base64

aGVsbG8gd29ybGQ=

 

// base64 decoding

# echo 'aGVsbG8gd29ybGQ=' | base64 --decode

hello world#

 

2. 파일 인코딩, 디코딩

파일을 이용하여 인코딩, 디코딩을 할 수 있다.

1

2

3

4

5

6

7

// base64 encoding

# echo 'hello world' | base64 > hello.txt

# cat hello.txt

aGVsbG8gd29ybGQK

// base64 decoding

# base64 -di hello.txt

hello world

+ Recent posts