Created
November 15, 2023 07:52
-
-
Save chitoku-k/ec0843f9badbfef1fece175bfa57c8dc to your computer and use it in GitHub Desktop.
Invoke Win32_Process::Create using github.com/go-ole/go-ole
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"runtime" | |
"github.com/go-ole/go-ole" | |
"github.com/go-ole/go-ole/oleutil" | |
"golang.org/x/sys/windows" | |
) | |
func main() { | |
processID, err := createProcess("cmd.exe", windows.SW_HIDE) | |
if err != nil { | |
panic(err) | |
} | |
fmt.Printf("Process ID: %d\n", processID) | |
} | |
// See: https://learn.microsoft.com/en-us/windows/win32/wmisdk/creating-a-wmi-script | |
func createProcess(commandLine string, showWindow uint16) (*int32, error) { | |
runtime.LockOSThread() | |
defer runtime.UnlockOSThread() | |
err := ole.CoInitializeEx(uintptr(0), ole.COINIT_MULTITHREADED) | |
if err != nil { | |
oleerr := err.(*ole.OleError) | |
if oleerr.Code() != uintptr(windows.S_FALSE) { | |
return nil, fmt.Errorf("failed to initialize COM: %w", err) | |
} | |
} | |
defer ole.CoUninitialize() | |
// See: https://learn.microsoft.com/en-us/windows/win32/wmisdk/swbemlocator | |
unknown, err := oleutil.CreateObject("WbemScripting.SWbemLocator") | |
if err != nil { | |
return nil, fmt.Errorf("failed to create WbemScripting.SWbemLocator (%#x): %w", err.(*ole.OleError).Code(), err) | |
} | |
defer unknown.Release() | |
wmi, err := unknown.QueryInterface(ole.IID_IDispatch) | |
if err != nil { | |
return nil, fmt.Errorf("failed to query interface (%#x): %w", err.(*ole.OleError).Code(), err) | |
} | |
defer wmi.Release() | |
// See: https://learn.microsoft.com/en-us/windows/win32/wmisdk/swbemlocator-connectserver | |
swbemservicesVariant, err := oleutil.CallMethod(wmi, "ConnectServer", ".", `Root\CIMV2`) | |
if err != nil { | |
return nil, fmt.Errorf("failed to connect to server (%#x): %w", err.(*ole.OleError).Code(), err) | |
} | |
defer swbemservicesVariant.Clear() | |
// See: https://learn.microsoft.com/en-us/windows/win32/wmisdk/swbemservices | |
swbemservices := swbemservicesVariant.ToIDispatch() | |
defer swbemservices.Release() | |
// See: https://learn.microsoft.com/en-us/windows/win32/wmisdk/swbemservices-get | |
processVariant, err := swbemservices.CallMethod("Get", "Win32_Process") | |
if err != nil { | |
return nil, fmt.Errorf("failed to get Win32_Process (%#x): %w", err.(*ole.OleError).Code(), err) | |
} | |
defer processVariant.Clear() | |
// See: https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-process | |
process := processVariant.ToIDispatch() | |
defer process.Release() | |
// See: https://learn.microsoft.com/en-us/windows/win32/wmisdk/swbemservices-get | |
processStartupVariant, err := swbemservices.CallMethod("Get", "Win32_ProcessStartup") | |
if err != nil { | |
return nil, fmt.Errorf("failed to get Win32_ProcessStartup (%#x): %w", err.(*ole.OleError).Code(), err) | |
} | |
// See: https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-processstartup | |
processStartup := processStartupVariant.ToIDispatch() | |
// See: https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow | |
showwindowVariant, err := processStartup.PutProperty("ShowWindow", showWindow) | |
if err != nil { | |
return nil, fmt.Errorf("failed to put Win32_ProcessStartup::ShowWindow (%#v): %w", err.(*ole.OleError).Code(), err) | |
} | |
defer showwindowVariant.Clear() | |
// See: https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/create-method-in-class-win32-process | |
var processID int32 | |
ret, err := process.CallMethod("Create", commandLine, nil, processStartupVariant, &processID) | |
if err != nil { | |
return nil, fmt.Errorf("failed to create a process (%#x): %w", err.(*ole.OleError).Code(), err) | |
} | |
defer ret.Clear() | |
retval := ret.Value().(int32) | |
if retval != 0 { | |
return nil, fmt.Errorf("failed to create a process (%d)", retval) | |
} | |
return &processID, nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If the subsystem of the process is console that does not need console, this can be as simple as: