보안정보

전문화된 보안 관련 자료, 보안 트렌드를 엿볼 수 있는
차세대 통합보안관리 기업 이글루코퍼레이션 보안정보입니다.

DLL Hijacking PART 2: DLL Side-Loading

2023.11.21

46,742

01. DLL Hijacking PART 1: Search Order Hijacking 요약

DLL Hijacking PART 1: Search Order Hijacking을 통해 DLL Hijacking의 유형과 공격방식을 설명하고, DLL Hijacking 공격방식 중 하나인 Search Order Hijacking의 개념과 실제 공격사례를 통해 정상 서명된 파일도 Search Order Hijacking을 이용하면 공격에 악용할 수 있다는 점을 설명하였다.

Search Order Hijacking 공격방식은 실행파일이 실행될 때 라이브러리 파일인 DLL의 기본 로드 순서를 악용한 방식이다. 실행파일이 실행되는 폴더와 동일 경로에 존재하는 정상 DLL 파일을 바꿔치기하여 악성 DLL 파일이 실행되게 하는 것이다. 하지만 악성 DLL 파일로 교체가 가능할 뿐 Search Order Hijacking 공격만 사용하면 실행 파일 실행 시에 정상 DLL을 통해 필요한 함수가 정상적으로 로드되지 않아 프로그램이 제대로 실행되지 않는 문제가 발생하게 된다.

악성 DLL이 포함되어도 정상적으로 실행되어야 공격 사실을 인지할 수 없게 되는데 실행파일이 정상 실행되지 않아 공격 사실이 노출되게 되는 것이다. DLL Hijacking을 이용한 공격을 통해 목적한 공격 지속(Persistence), 권한 상승(Privilege Escalation), 측면 이동(Lateral Movement) 등이 불가해지고 백신 프로그램이나 엔드포인트 보안솔루션 등에 의해서 탐지되게 되는 것이다.

결국 공격자 입장에서는 정상적인 DLL의 함수 로드가 가능한 상태에서 Search Order Hijacking과 같이 공격자가 원하는 페이로드(Payload)가 포함된 공격 도구 및 흐름 변경을 위한 추가적인 공격이 필요하게 된다. 바로 이번 호에서 설명할 DLL Side Loading이 이러한 공격자의 목적을 달성할 수 있게 한다. 따라서 이번 호에서는 DLL Hijacking 시리즈의 마지막인 ‘PART 2: DLL Side Loading’에 대해서 설명하고자 한다.

02. DLL Side-Loading 개요 및 공격 방식

DLL Hijacking PART 1에서 알아본 Search Order Hijacking은 DLL 검색 순서를 악용하여 공격자가 원하는 DLL을 실행하는 방식이다. DLL Side-Loading은 DLL Search Order Hijacking과 공격 방식은 유사하나 정상 DLL로 위장하여 악성 DLL을 실행하게 하는 프록시(Proxy) DLL을 이용한다. Proxy DLL은 정상 실행파일에서 사용되는 DLL 로드 과정에 관여하여 함수 로딩 중 실행 흐름을 탈취하여 악성 DLL 또는 코드를 실행하게 하는 DLL이다. DLL Side-Loading은 DLL 검색 순서를 악용하는 Search Order Hijacking을 이용하여 Proxy DLL을 실행하게 하면서 악성 DLL 또는 코드가 실행되는 방식이다.

DLL Side-Loading을 이용한 공격 방식의 순서는 [그림 1]과 같다.

① 공격자가 이전에 생성한 Proxy DLL을 정상 DLL 파일명으로 변경한 이후 정상 DLL을 대체
② 정상적으로 디지털 서명된 실행파일을 이용할 경우 실행에 필요한 특정 DLL을 파일명으로 로드 시도
③ 정상 DLL이 로드되는 대신 Proxy DLL을 로드하며 Proxy DLL을 이용하여 악성 DLL을 메모리에 로드
④ Proxy DLL은 정상 실행파일의 함수 호출을 원본 DLL의 로컬 복사본으로 리다이렉션

이러한 방식을 이용하는 이유는 DLL 실행 시 정상적으로 로드가 되어야 할 함수를 불러오지 못할 경우 프로그램은 정상 동작하지 않고 크래시 되어 강제 종료된다. 문제는 강제 종료가 되는 것 자체가 공격자가 원하는 코드를 실행할 수 없음을 의미하기 때문에 정상적인 실행 방법 내에서 악성코드가 실행되길 원할 것이다. DLL Side-Loading을 이용하여 실행할 경우 정상 프로그램이 로드하는 방식으로 실행되기 때문에 탐지될 확률이 줄어들게 된다.

[그림 1] DLL Side-Loading 공격 구성도

03. DLL Side-Loading 공격개요 및 사례분석

1) DLL Side-Loading 공격개요

DLL Side-Loading의 공격사례를 살펴보기에 앞서 공격개념에 대해 살펴보고자 한다. 기본적인 조건은 PART 1에서 소개한 Search Order Hijacking과 유사한 방식으로 ▲디지털 서명된 실행파일 ▲같은 위치에 존재하여 DLL 로드를 시도하는 실행파일을 찾아야 한다. 이 조건에 부합하는 파일 중 FileZilla FTP Client에서 사용하는 fzsftp.exe를 이용하여 실행에 필요한 DLL을 찾은 뒤 Proxy DLL로 바꿔치기했을 경우 공격에 성공하는지 알아보려 한다.

[표 1] 사용되는 파일 정보 (FileZilla FTP Client 3.64.0 기준)

fzsftp.exe는 FileZilla FTP Client가 설치될 때 동시에 생성되며 PuTTY의 psftp 컴포넌트를 기반으로 하는 FileZilla용 SFTP 모듈로 확인된다.

[그림 2] FileZilla FTP Client가 설치된 폴더에서 확인되는 fzsftp.exe

fzsftp.exe를 단독으로 다른 폴더에 복사 후 실행 시 libnettle-8.dll이 존재하지 않아 정상적인 실행이 불가능하며 DLL 로드 현황 확인 시 동일한 경로에 존재하는 경우 해당 DLL을 로드하기 때문에 Search Order Hijacking은 성공적으로 가능하다.

[그림 3] fzsftp.exe 실행 시 필요한 DLL 정보 확보

DLL Side-Loading 성공 시 메시지 박스를 띄울 목적으로 한 쉘코드를 Metasploit으로 미리 제작한다.

[그림 4] Metasploit을 이용한 쉘코드 제작

Dotnet Core 프로그램인 SharpDllProxy를 이용하여 Proxy DLL을 제작한다. 이때, libnettle-8.dll 내부에 Export 함수를 기반으로 작성되며 Proxy DLL 로드 시 shellcode.bin 내부의 쉘 코드를 로드 하여 실행하는 함수가 추가된다.

[그림 5] SharpDllProxy를 이용하여 libnettle-8.dll 내 함수 추출

작업 완료 시 원본 libnettle-8.dll은 실행 시 함수 로드를 위해 tmp(랜덤 숫자문자 4자리).dll로 파일명만 변경되며 libnettle-8_pragma.c를 DLL로 컴파일을 진행하면 Proxy DLL이 생성된다.

[그림 6] Proxy DLL 원본 코드 생성

libnettle-8_pragma.c에서 DoMagic 함수 확인 시 shellcode.bin 파일을 오픈하여 내부에 존재하는 데이터를 메모리에 저장한다.

[그림 7] libnettle-8_pragma.c에서 DoMagic 함수

DLLMain 함수 확인 시 DLL_PROCESS_ATTACH(DLL 로드)인 경우 CreateThread 함수를 이용하여 DoMagic 함수를 스레드로 생성하여 실행시킨다.

[그림 8] DLLMain 함수에서 확인되는 DoMagic 함수 로드 시도

libnettle-8_pragma.c를 DLL로 컴파일 완료 후 libnettle-8.dll으로 파일명을 변경하여 동일한 경로에 위치시킨다.

[그림 9] DLL Side-Loading 공격에 사용되는 DLL, Shellcode 목록

fzsftp.exe 실행 시 Shellcode가 실행되면서 “Proxy Loading Worked”라는 메시지 박스가 생성된다. DLL 로드 현황 확인 시 Proxy DLL과 이름이 변경된 tmp92F7.dll이 동시에 로드되어 프로그램 실행에 전혀 방해가 되지 않는 것으로 확인된다.

[그림 10] DLL Side-Loading 작업 완료 후 fzsftp.exe 실행 화면
[그림 11] DLL Side-Loading에 성공하여 Proxy DLL 및 파일명이 변경된 원본 DLL 로드 현황

2) DLL Side-Loading을 활용한 악성코드 공격사례

DLL Side-Loading을 사용하는 악성코드 중 PlugX가 있으며, 중국과 연계된 APT 그룹인 Mustang Panda(TA416)가 주로 사용하고 있다. 백도어를 포함한 정보 탈취, 시스템 제어 등의 기능을 제공하며 기능별 모듈화가 되어 있다는 특징이 있다. 해당 악성코드는 2022년 1월 유럽 외교기관을 목표로 한 공격에서 확보된 샘플로 다운로드 된 파일에서 Daum이 배포하는 정상 PotPlayer 실행파일을 이용하여 PlugX 악성 모듈을 실행하는 것으로 확인된다. 해당 악성코드가 어떤 행위를 통해 악성 행위를 시작하는지 알아보고자 한다.

[표 2] 악성코드 샘플 정보
[그림 12] 악성코드 샘플 정보
[그림 13] 악성코드 샘플 공격 구성도

최초 실행 시 그리스 지역 원조 관련된 내용의 PDF 문서가 실행된다. 해당 문서는 [그림 15]에서 설명할 C2와 연결하여 악성파일을 다운로드해 사용자의 TEMP 폴더에 저장 후 실행된다.

[그림 14] 악성코드 실행 시 다운로드 받은 위장 PDF 파일

[그림 13]의 2,3,4번과 같이 실제 PDF 문서를 다운로드해 화면에 표시되는 동안 외부 C2인 hxxps://45[.]154[.]14[.]235에서 총 3종의 파일을 다운로드해 사용자의 TEMP 폴더에 저장하게 된다.

[그림 15] State_aid__Commission_approves_2022- 2027_regional_aid_map_for_Greece.exe 내 C2 정보

Temp 폴더에 저장된 PotPlayer.exe는 Daum에서 제작한 음악/동영상 재생 프로그램으로 현재 유효한 디지털 서명을 가지고 있는 것으로 확인된다.

[그림 16] PotPlayer.exe 파일 정보

[그림 13]의 5번과 같이 PotPlayer.exe 최초 실행 시 동일한 경로 내에 PotPlayer.dll이 존재하는지 확인하며, 존재하는 경우 DLL을 로드하여 Export 함수를 로드한다.

[그림 17] PotPlayer.exe 내 DLL 존재여부 확인 로직

PotPlayer.dll는 공격자가 생성한 악성코드로 Export 함수를 로드하는 과정에서 SetPotPlayerRegKeyW를 불러올 때 공격자가 심어둔 코드를 실행하게 된다. 여기서 정상적으로 로드가 실패하는 경우 DLL이 없다고 판단하고 프로그램을 강제 종료한다.

[그림 18] Export 함수 로드 과정에서 발생되는 악성 행위 시도

SetPotPlayerRegKeyW를 제외한 PreprocessCmdLineExW, UninitPotPlayer, CreatePotPlayerExW, DestroyPotPlayer, RunPotPlayer의 경우 내용이 존재하지 않는 것으로 확인된다.

[그림 19] PotPlayer.dll 내 함수 중 내용이 없는 함수

[그림 13]의 6번과 같이 SetPotPlayerRegKeyW의 경우 PotPlayerDB.dat를 로드한 이후 메모리에 로드하며 해당 데이터를 복호화 하여 정보 탈취에 사용되는 코드를 메모리에서 직접 실행한다.

[그림 20] PotPlayer.exe 내 DLL 존재여부 확인 로직

04. 맺음말

DLL Hijacking PART 1 : Search Order Hijacking , DLL Hijacking PART 2 : DLL Side-Loading 2편의 내용을 토대로 Search Order Hijacking의 공격 방식, 예제, 실제 악용 사례를 알아보며 취약점을 악용할 경우 정상 실행파일을 악용하여 공격자가 원하는 공격 코드를 실행할 수 있음을 확인하였다. 현재 해당 취약점에 대해 Microsoft에서 패치를 제공하지 않아 근본적인 공격 차단이 어렵기 때문에 정상적인 실행파일이더라도 실행 이전에 DLL 및 의심파일에 대한 확인이 선행되어야 한다.

MITRE ATT&CK 13버전 기준으로 Search Order Hijacking 및 DLL Side-Loading 완화 방안은 [표 3]과 같다.

[표 3] MITRE ATT&CK 13버전 기준 완화 방안

완화 방안 중 M1051 : Application Developer Guidance에 대해서 알아보고자 한다. Microsoft에서 제시한 완화 방안으로 개발자가 로드된 라이브러리가 유효한지 확인하기 위해 매니페스트를 생성할 수 있다. 매니페스트에 DLL Hash를 기록할 수 있으며, 이를 이용하여 DLL 로드 시 개발자가 생성한 DLL를 먼저 로드하는 것이 가능하다.

[표 4] DLL 로드 시 참조하는 DLL Hash를 포함한 매니페스트

05. 참고자료

1) Hijack Execution Flow: DLL Side-Loading
https://attack.mitre.org/techniques/T1574/002/
2) DLL Proxy Loading Your Favourite C# Implant
https://redteaming.co.uk/2020/07/12/dll-proxy-loading-your-favorite-c-implant/
3) Flangvik/SharpDllProxy
https://github.com/Flangvik/SharpDllProxy
4) LuminousMoth APT: Sweeping attacks for the chosen few
https://securelist.com/apt-luminousmoth/103332/
5) Secure loading of libraries to prevent DLL preloading attacks
https://support.microsoft.com/en-us/topic/secure-loading-of-libraries-to-prevent-dll-preloading-attacks-d41303ec-0748-9211-f317-2edc819682e1
6) DLL SIDE-LOADING: A Thorn in the Side of the Anti-Virus Industry
https://www.mandiant.com/sites/default/files/2021-09/rpt-dll-sideloading.pdf