Hey Checkyourlogs Fans,
This post explores how we used PoolMon.exe, part of Microsoft’s Windows Driver Kit (WDK), to identify and remediate a weekly memory leak in a production Windows Server 2025 environment. This leak occurred across physical and virtual servers, gradually consuming memory over 5–7 days and forcing weekly reboots.
Our investigation pointed toward a kernel memory leak—possibly caused by an agent like antivirus software or a patch management tool like ManageEngine Update Manager. Using PoolMon, we isolated the issue to a memory tag, which led us to the culprit driver.

Symptoms of the Leak
| Symptom | Description |
| High RAM usage over time | Memory usage grows without an associated high-usage process |
| Task Manager shows low process use | But the server still consumes 90–100% RAM |
| Nonpaged pool usage > 1–2 GB | (Normal range is 200–500 MB) |
| The server needs weekly reboots | Freeing memory temporarily resolves the issue |
| Multiple servers affected | Common agent suspected across all systems |
Step 1: Installing PoolMon.exe
To get started with PoolMon:
| Step | Action |
|---|---|
| 1 | Download and install the Windows Driver Kit (WDK) for Windows 10/11 or Server 2025 |
| 2 | Locate poolmon.exe – usually found at:
C:\Program Files (x86)\Windows Kits\10\Tools\x64 |
| 3 | Copy poolmon.exe to the affected server |
| 4 | Run from elevated Command Prompt or PowerShell |
Note: Pool tagging is enabled by default in Server 2025. If PoolMon doesn’t show data, ensure the registry value below exists:
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager
DWORD: GlobalFlag = 0x400
Reboot after applying this setting.
Step 2: Capturing Pool Usage During a Leak
Run PoolMon to capture live pool allocation data:
poolmon /b
Inside PoolMon:
| Key Press | Action |
| P | Toggle between Paged/Nonpaged pool |
| B | Sort list by bytes used |
Focus on Nonpaged Pool usage first. It’s common for drivers and kernel agents to leak here.
Sample PoolMon Output (Filtered by Nonpaged Pool and Sorted by Bytes)
| Tag | Type | Allocs | Frees | Diff | Bytes | Avg Bytes/Alloc |
| MEUP | Nonp | 150,000 | 5,000 | 145,000 | 800,000,000 | ~5.5 KB |
| Ntfx | Nonp | 45,000 | 44,950 | 50 | 12,000,000 | ~240 KB |
| ConT | Nonp | 33,000 | 32,500 | 500 | 8,000,000 | ~16 KB |
The MEUP tag is the outlier—consuming 800 MB of kernel memory and showing 145,000 unfreed allocations.
Step 3: Interpreting the Results
To determine if a tag is leaking:
| Indicator | Description |
| High Diff | Indicates allocations that haven’t been freed |
| Increasing Bytes | Memory usage by that tag is growing over time |
| High Avg Bytes/Alloc | Each allocation is large (proper for assessing impact) |
| Tag unknown in system docs | Suggests a custom or 3rd-party driver (investigate further) |
Take snapshots of PoolMon hourly. If a tag keeps climbing, it’s likely the culprit.
Step 4: Mapping Pool Tags to Drivers
We need to determine which driver is responsible for the MEUP tag.
Using findstr (Recommended)
cd C:\Windows\System32\drivers
findstr /m /s /l “MEUP” *.sys
Output Example:
MEAgent.sys
This confirms that the tag MEUP exists inside the MEAgent.sys binary—likely part of ManageEngine Update Manager.
Optional: PowerShell Alternative
Get-ChildItem *.sys | Select-String “MEUP” | Select-Object -Unique Path
Confirm Driver Details
You can validate the driver details with:
Get-Item “C:\Windows\System32\drivers\MEAgent.sys” | Select-Object VersionInfo
Step 5: Triaging and Isolating the Culprit
| Step | Purpose |
| Confirm driver belongs to agent | Cross-check with installed apps or services |
| Check other servers | Is the same tag present on other leaking systems? |
| Disable agent on test system | See if the leak behavior stops after disabling the suspected agent |
| Search forums/vendor KB | Others may have reported this issue; fixes may already exist |
Step 6: Remediation Options
| Option | Description |
| Update the agent/driver | Always check for the latest version – many leaks are fixed in updates |
| Contact vendor support | Provide tag name, driver file, and PoolMon stats |
| Temporarily disable agent | If safe, disable or stop the agent to confirm the leak source |
| Schedule reboots | Not ideal, but it may be necessary until a fix is in place |
| Adjust task scheduling | If scans or updates trigger the leak, stagger or reduce frequency |
| Implement monitoring | Use PerfMon or other tools to alert when Nonpaged Pool exceeds safe limits |
Summary: The PoolMon Method
| Step | Tool/Command | Goal |
| Capture memory usage | poolmon /b | Identify high pool tags |
| Filter by pool type | Press P in PoolMon | Focus on Nonpaged or Paged |
| Find the offending tag | Sort by Bytes (press B) | Spot leaks growing over time |
| Map tag to driver | findstr /m /s /l “TAG” *.sys | Identify the associated .sys file |
| Confirm source | File version check/service listing | Match driver to installed software |
| Take action | Update/contact vendor / disable | Stop the leak and stabilize the system |
Pro Tip: Monitor Memory Pools Automatically
Consider setting up monitoring using PerfMon counters:
- Memory\Pool Nonpaged Bytes
- Memory\Pool Paged Bytes
Set alert thresholds (e.g., >1.5 GB Nonpaged Pool), and automate service restarts or send alerts when hit.
Conclusion
Memory leaks are sneaky, especially in kernel space. But with the right tools and a bit of patience, you can:
- Isolate the issue
- Find the leaking component
- Take proactive steps before it causes outages
In our case, the weekly server reboots were traced to a ManageEngine agent leaking memory under the MEUP tag. Using PoolMon and standard Windows tools, we saved countless hours of guesswork and got our servers back to a healthy state.
Stay sharp, sysadmins—and don’t let a 4-letter pool tag take down your infrastructure.
Thanks,
Dave
