diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 039bbb66cf2..249af8f9d81 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -255,6 +255,7 @@ - [Abusing Auto Updaters And Ipc](windows-hardening/windows-local-privilege-escalation/abusing-auto-updaters-and-ipc.md) - [Arbitrary Kernel Rw Token Theft](windows-hardening/windows-local-privilege-escalation/arbitrary-kernel-rw-token-theft.md) - [Kernel Race Condition Object Manager Slowdown](windows-hardening/windows-local-privilege-escalation/kernel-race-condition-object-manager-slowdown.md) + - [Notepad Plus Plus Plugin Autoload Persistence](windows-hardening/windows-local-privilege-escalation/notepad-plus-plus-plugin-autoload-persistence.md) - [Abusing Tokens](windows-hardening/windows-local-privilege-escalation/privilege-escalation-abusing-tokens.md) - [Access Tokens](windows-hardening/windows-local-privilege-escalation/access-tokens.md) - [ACLs - DACLs/SACLs/ACEs](windows-hardening/windows-local-privilege-escalation/acls-dacls-sacls-aces.md) diff --git a/src/windows-hardening/windows-local-privilege-escalation/README.md b/src/windows-hardening/windows-local-privilege-escalation/README.md index 79ed59d7680..69469845845 100644 --- a/src/windows-hardening/windows-local-privilege-escalation/README.md +++ b/src/windows-hardening/windows-local-privilege-escalation/README.md @@ -741,6 +741,14 @@ Get-ChildItem 'C:\Program Files\*','C:\Program Files (x86)\*' | % { try { Get-Ac Get-ChildItem 'C:\Program Files\*','C:\Program Files (x86)\*' | % { try { Get-Acl $_ -EA SilentlyContinue | Where {($_.Access|select -ExpandProperty IdentityReference) -match 'BUILTIN\Users'} } catch {}} ``` +### Notepad++ plugin autoload persistence/execution + +Notepad++ autoloads any plugin DLL under its `plugins` subfolders. If a writable portable/copy install is present, dropping a malicious plugin gives automatic code execution inside `notepad++.exe` on every launch (including from `DllMain` and plugin callbacks). + +{{#ref}} +notepad-plus-plus-plugin-autoload-persistence.md +{{#endref}} + ### Run at startup **Check if you can overwrite some registry or binary that is going to be executed by a different user.**\ diff --git a/src/windows-hardening/windows-local-privilege-escalation/notepad-plus-plus-plugin-autoload-persistence.md b/src/windows-hardening/windows-local-privilege-escalation/notepad-plus-plus-plugin-autoload-persistence.md new file mode 100644 index 00000000000..87cf0f30d66 --- /dev/null +++ b/src/windows-hardening/windows-local-privilege-escalation/notepad-plus-plus-plugin-autoload-persistence.md @@ -0,0 +1,61 @@ +# Notepad++ Plugin Autoload Persistence & Execution + +{{#include ../../banners/hacktricks-training.md}} + +Notepad++ will **autoload every plugin DLL found under its `plugins` subfolders** on launch. Dropping a malicious plugin into any **writable Notepad++ installation** gives code execution inside `notepad++.exe` every time the editor starts, which can be abused for **persistence**, stealthy **initial execution**, or as an **in-process loader** if the editor is launched elevated. + +## Writable plugin locations +- Standard install: `C:\Program Files\Notepad++\plugins\\.dll` (usually requires admin to write). +- Writable options for low-privileged operators: + - Use the **portable Notepad++ build** in a user-writable folder. + - Copy `C:\Program Files\Notepad++` to a user-controlled path (e.g., `%LOCALAPPDATA%\npp\`) and run `notepad++.exe` from there. +- Each plugin gets its own subfolder under `plugins` and is loaded automatically at startup; menu entries appear under **Plugins**. + +## Plugin load points (execution primitives) +Notepad++ expects specific **exported functions**. These are all called during initialization, giving multiple execution surfaces: +- **`DllMain`** — runs immediately on DLL load (first execution point). +- **`setInfo(NppData)`** — called once on load to provide Notepad++ handles; typical place to register menu items. +- **`getName()`** — returns the plugin name shown in the menu. +- **`getFuncsArray(int *nbF)`** — returns menu commands; even if empty, it is called during startup. +- **`beNotified(SCNotification*)`** — receives editor events (file open/change, UI events) for ongoing triggers. +- **`messageProc(UINT, WPARAM, LPARAM)`** — message handler, useful for larger data exchanges. +- **`isUnicode()`** — compatibility flag checked at load. + +Most exports can be implemented as **stubs**; execution can occur from `DllMain` or any callback above during autoload. + +## Minimal malicious plugin skeleton +Compile a DLL with the expected exports and place it in `plugins\\MyNewPlugin\\MyNewPlugin.dll` under a writable Notepad++ folder: + +```c +BOOL APIENTRY DllMain(HMODULE h, DWORD r, LPVOID) { if (r == DLL_PROCESS_ATTACH) MessageBox(NULL, TEXT("Hello from Notepad++"), TEXT("MyNewPlugin"), MB_OK); return TRUE; } +extern "C" __declspec(dllexport) void setInfo(NppData) {} +extern "C" __declspec(dllexport) const TCHAR *getName() { return TEXT("MyNewPlugin"); } +extern "C" __declspec(dllexport) FuncItem *getFuncsArray(int *nbF) { *nbF = 0; return NULL; } +extern "C" __declspec(dllexport) void beNotified(SCNotification *) {} +extern "C" __declspec(dllexport) LRESULT messageProc(UINT, WPARAM, LPARAM) { return TRUE; } +extern "C" __declspec(dllexport) BOOL isUnicode() { return TRUE; } +``` + +1. Build the DLL (Visual Studio/MinGW). +2. Create the plugin subfolder under `plugins` and drop the DLL inside. +3. Restart Notepad++; the DLL is loaded automatically, executing `DllMain` and subsequent callbacks. + +## Reflective loader plugin pattern +A weaponized plugin can turn Notepad++ into a **reflective DLL loader**: +- Present a minimal UI/menu entry (e.g., "LoadDLL"). +- Accept a **file path** or **URL** to fetch a payload DLL. +- Reflectively map the DLL into the current process and invoke an exported entry point (e.g., a loader function inside the fetched DLL). +- Benefit: reuse a benign-looking GUI process instead of spawning a new loader; payload inherits the integrity of `notepad++.exe` (including elevated contexts). +- Trade-offs: dropping an **unsigned plugin DLL** to disk is noisy; consider piggybacking on existing trusted plugins if present. + +## Detection and hardening notes +- Block or monitor **writes to Notepad++ plugin directories** (including portable copies in user profiles); enable controlled folder access or application allowlisting. +- Alert on **new unsigned DLLs** under `plugins` and unusual **child processes/network activity** from `notepad++.exe`. +- Enforce plugin installation via **Plugins Admin** only, and restrict execution of portable copies from untrusted paths. + +## References +- [Notepad++ Plugins: Plug and Payload](https://trustedsec.com/blog/notepad-plugins-plug-and-payload) +- [MyNewPlugin PoC snippet](https://gitlab.com/-/snippets/4930986) +- [LoadDLL reflective loader plugin](https://gitlab.com/KevinJClark/ops-scripts/-/tree/main/notepad_plus_plus_plugin_LoadDLL) + +{{#include ../../banners/hacktricks-training.md}}