mirror of
https://github.com/ropnop/go-clr
synced 2026-06-08 17:11:59 +00:00
some refactoring and commenting
This commit is contained in:
+4
-3
@@ -86,6 +86,7 @@ type AppDomainVtbl struct {
|
||||
get_DynamicDirectory uintptr
|
||||
}
|
||||
|
||||
// GetAppDomain is a wrapper function that returns an appDomain from an existing ICORRuntimeHost object
|
||||
func GetAppDomain(runtimeHost *ICORRuntimeHost) (appDomain *AppDomain, err error) {
|
||||
var pAppDomain uintptr
|
||||
var pIUnknown uintptr
|
||||
@@ -94,13 +95,13 @@ func GetAppDomain(runtimeHost *ICORRuntimeHost) (appDomain *AppDomain, err error
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
iu := NewIUnknown(pIUnknown)
|
||||
iu := NewIUnknownFromPtr(pIUnknown)
|
||||
hr = iu.QueryInterface(&IID_AppDomain, &pAppDomain)
|
||||
err = checkOK(hr, "IUnknown.QueryInterface")
|
||||
return NewAppDomain(pAppDomain), err
|
||||
return NewAppDomainFromPtr(pAppDomain), err
|
||||
}
|
||||
|
||||
func NewAppDomain(ppv uintptr) *AppDomain {
|
||||
func NewAppDomainFromPtr(ppv uintptr) *AppDomain {
|
||||
return (*AppDomain)(unsafe.Pointer(ppv))
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -69,7 +69,7 @@ type AssemblyVtbl struct {
|
||||
get_GlobalAssemblyCache uintptr
|
||||
}
|
||||
|
||||
func NewAssembly(ppv uintptr) *Assembly {
|
||||
func NewAssemblyFromPtr(ppv uintptr) *Assembly {
|
||||
return (*Assembly)(unsafe.Pointer(ppv))
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ func main() {
|
||||
|
||||
hr := metahost.GetRuntime(pwzVersion, &clr.IID_ICLRRuntimeInfo, &pRuntimeInfo)
|
||||
checkOK(hr, "metaHost.GetRuntime")
|
||||
runtimeInfo := clr.NewICLRRuntimeInfo(pRuntimeInfo)
|
||||
runtimeInfo := clr.NewICLRRuntimeInfoFromPtr(pRuntimeInfo)
|
||||
fmt.Printf("[+] Using runtime: %s\n", versionString)
|
||||
|
||||
var isLoadable bool
|
||||
@@ -49,7 +49,7 @@ func main() {
|
||||
var pRuntimeHost uintptr
|
||||
hr = runtimeInfo.GetInterface(&clr.CLSID_CLRRuntimeHost, &clr.IID_ICLRRuntimeHost, &pRuntimeHost)
|
||||
checkOK(hr, "runtimeInfo.GetInterface")
|
||||
runtimeHost := clr.NewICLRRuntimeHost(pRuntimeHost)
|
||||
runtimeHost := clr.NewICLRRuntimeHostFromPtr(pRuntimeHost)
|
||||
|
||||
hr = runtimeHost.Start()
|
||||
checkOK(hr, "runtimeHost.Start")
|
||||
|
||||
@@ -1,121 +1,121 @@
|
||||
// +build windows
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
clr "github.com/ropnop/go-clr"
|
||||
)
|
||||
|
||||
func must(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func checkOK(hr uintptr, caller string) {
|
||||
if hr != 0x0 {
|
||||
log.Fatalf("%s returned 0x%08x", caller, hr)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Println("Usage: EXEfromMemory.exe <exe_file>")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
filename := os.Args[1]
|
||||
exebytes, err := ioutil.ReadFile(filename)
|
||||
must(err)
|
||||
runtime.KeepAlive(exebytes)
|
||||
|
||||
var pMetaHost uintptr
|
||||
hr := clr.CLRCreateInstance(&clr.CLSID_CLRMetaHost, &clr.IID_ICLRMetaHost, &pMetaHost)
|
||||
checkOK(hr, "CLRCreateInstance")
|
||||
metaHost := clr.NewICLRMetaHost(pMetaHost)
|
||||
|
||||
versionString := "v4.0.30319"
|
||||
pwzVersion, _ := syscall.UTF16PtrFromString(versionString)
|
||||
var pRuntimeInfo uintptr
|
||||
hr = metaHost.GetRuntime(pwzVersion, &clr.IID_ICLRRuntimeInfo, &pRuntimeInfo)
|
||||
checkOK(hr, "metahost.GetRuntime")
|
||||
runtimeInfo := clr.NewICLRRuntimeInfo(pRuntimeInfo)
|
||||
|
||||
var isLoadable bool
|
||||
hr = runtimeInfo.IsLoadable(&isLoadable)
|
||||
checkOK(hr, "runtimeInfo.IsLoadable")
|
||||
if !isLoadable {
|
||||
log.Fatal("[!] IsLoadable returned false. Bailing...")
|
||||
}
|
||||
|
||||
hr = runtimeInfo.BindAsLegacyV2Runtime()
|
||||
checkOK(hr, "runtimeInfo.BindAsLegacyV2Runtime")
|
||||
|
||||
var pRuntimeHost uintptr
|
||||
hr = runtimeInfo.GetInterface(&clr.CLSID_CorRuntimeHost, &clr.IID_ICorRuntimeHost, &pRuntimeHost)
|
||||
runtimeHost := clr.NewICORRuntimeHost(pRuntimeHost)
|
||||
hr = runtimeHost.Start()
|
||||
checkOK(hr, "runtimeHost.Start")
|
||||
fmt.Println("[+] Loaded CLR into this process")
|
||||
|
||||
var pAppDomain uintptr
|
||||
var pIUnknown uintptr
|
||||
hr = runtimeHost.GetDefaultDomain(&pIUnknown)
|
||||
checkOK(hr, "runtimeHost.GetDefaultDomain")
|
||||
iu := clr.NewIUnknown(pIUnknown)
|
||||
hr = iu.QueryInterface(&clr.IID_AppDomain, &pAppDomain)
|
||||
checkOK(hr, "iu.QueryInterface")
|
||||
appDomain := clr.NewAppDomain(pAppDomain)
|
||||
fmt.Println("[+] Got default AppDomain")
|
||||
|
||||
fmt.Printf("[+] Loaded %d bytes into memory from %s\n", len(exebytes), filename)
|
||||
|
||||
safeArray, err := clr.CreateSafeArray(exebytes)
|
||||
must(err)
|
||||
runtime.KeepAlive(safeArray)
|
||||
fmt.Println("[+] Crated SafeArray from byte array")
|
||||
|
||||
var pAssembly uintptr
|
||||
hr = appDomain.Load_3(uintptr(unsafe.Pointer(&safeArray)), &pAssembly)
|
||||
checkOK(hr, "appDomain.Load_3")
|
||||
assembly := clr.NewAssembly(pAssembly)
|
||||
fmt.Printf("[+] Executable loaded into memory at 0x%08x\n", pAssembly)
|
||||
|
||||
var pEntryPointInfo uintptr
|
||||
hr = assembly.GetEntryPoint(&pEntryPointInfo)
|
||||
checkOK(hr, "assembly.GetEntryPoint")
|
||||
fmt.Printf("[+] Executable entrypoint found at 0x%08x. Calling...\n", pEntryPointInfo)
|
||||
fmt.Println("-------")
|
||||
methodInfo := clr.NewMethodInfo(pEntryPointInfo)
|
||||
|
||||
var pRetCode uintptr
|
||||
nullVariant := clr.Variant{
|
||||
VT: 1,
|
||||
Val: uintptr(0),
|
||||
}
|
||||
hr = methodInfo.Invoke_3(
|
||||
nullVariant,
|
||||
uintptr(0),
|
||||
&pRetCode)
|
||||
|
||||
fmt.Println("-------")
|
||||
|
||||
checkOK(hr, "methodInfo.Invoke_3")
|
||||
fmt.Printf("[+] Executable returned code %d\n", pRetCode)
|
||||
|
||||
appDomain.Release()
|
||||
runtimeHost.Release()
|
||||
runtimeInfo.Release()
|
||||
metaHost.Release()
|
||||
|
||||
}
|
||||
// +build windows
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
clr "github.com/ropnop/go-clr"
|
||||
)
|
||||
|
||||
func must(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func checkOK(hr uintptr, caller string) {
|
||||
if hr != 0x0 {
|
||||
log.Fatalf("%s returned 0x%08x", caller, hr)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Println("Usage: EXEfromMemory.exe <exe_file>")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
filename := os.Args[1]
|
||||
exebytes, err := ioutil.ReadFile(filename)
|
||||
must(err)
|
||||
runtime.KeepAlive(exebytes)
|
||||
|
||||
var pMetaHost uintptr
|
||||
hr := clr.CLRCreateInstance(&clr.CLSID_CLRMetaHost, &clr.IID_ICLRMetaHost, &pMetaHost)
|
||||
checkOK(hr, "CLRCreateInstance")
|
||||
metaHost := clr.NewICLRMetaHostFromPtr(pMetaHost)
|
||||
|
||||
versionString := "v4.0.30319"
|
||||
pwzVersion, _ := syscall.UTF16PtrFromString(versionString)
|
||||
var pRuntimeInfo uintptr
|
||||
hr = metaHost.GetRuntime(pwzVersion, &clr.IID_ICLRRuntimeInfo, &pRuntimeInfo)
|
||||
checkOK(hr, "metahost.GetRuntime")
|
||||
runtimeInfo := clr.NewICLRRuntimeInfoFromPtr(pRuntimeInfo)
|
||||
|
||||
var isLoadable bool
|
||||
hr = runtimeInfo.IsLoadable(&isLoadable)
|
||||
checkOK(hr, "runtimeInfo.IsLoadable")
|
||||
if !isLoadable {
|
||||
log.Fatal("[!] IsLoadable returned false. Bailing...")
|
||||
}
|
||||
|
||||
hr = runtimeInfo.BindAsLegacyV2Runtime()
|
||||
checkOK(hr, "runtimeInfo.BindAsLegacyV2Runtime")
|
||||
|
||||
var pRuntimeHost uintptr
|
||||
hr = runtimeInfo.GetInterface(&clr.CLSID_CorRuntimeHost, &clr.IID_ICorRuntimeHost, &pRuntimeHost)
|
||||
runtimeHost := clr.NewICORRuntimeHostFromPtr(pRuntimeHost)
|
||||
hr = runtimeHost.Start()
|
||||
checkOK(hr, "runtimeHost.Start")
|
||||
fmt.Println("[+] Loaded CLR into this process")
|
||||
|
||||
var pAppDomain uintptr
|
||||
var pIUnknown uintptr
|
||||
hr = runtimeHost.GetDefaultDomain(&pIUnknown)
|
||||
checkOK(hr, "runtimeHost.GetDefaultDomain")
|
||||
iu := clr.NewIUnknownFromPtr(pIUnknown)
|
||||
hr = iu.QueryInterface(&clr.IID_AppDomain, &pAppDomain)
|
||||
checkOK(hr, "iu.QueryInterface")
|
||||
appDomain := clr.NewAppDomainFromPtr(pAppDomain)
|
||||
fmt.Println("[+] Got default AppDomain")
|
||||
|
||||
fmt.Printf("[+] Loaded %d bytes into memory from %s\n", len(exebytes), filename)
|
||||
|
||||
safeArray, err := clr.CreateSafeArray(exebytes)
|
||||
must(err)
|
||||
runtime.KeepAlive(safeArray)
|
||||
fmt.Println("[+] Crated SafeArray from byte array")
|
||||
|
||||
var pAssembly uintptr
|
||||
hr = appDomain.Load_3(uintptr(unsafe.Pointer(&safeArray)), &pAssembly)
|
||||
checkOK(hr, "appDomain.Load_3")
|
||||
assembly := clr.NewAssemblyFromPtr(pAssembly)
|
||||
fmt.Printf("[+] Executable loaded into memory at 0x%08x\n", pAssembly)
|
||||
|
||||
var pEntryPointInfo uintptr
|
||||
hr = assembly.GetEntryPoint(&pEntryPointInfo)
|
||||
checkOK(hr, "assembly.GetEntryPoint")
|
||||
fmt.Printf("[+] Executable entrypoint found at 0x%08x. Calling...\n", pEntryPointInfo)
|
||||
fmt.Println("-------")
|
||||
methodInfo := clr.NewMethodInfoFromPtr(pEntryPointInfo)
|
||||
|
||||
var pRetCode uintptr
|
||||
nullVariant := clr.Variant{
|
||||
VT: 1,
|
||||
Val: uintptr(0),
|
||||
}
|
||||
hr = methodInfo.Invoke_3(
|
||||
nullVariant,
|
||||
uintptr(0),
|
||||
&pRetCode)
|
||||
|
||||
fmt.Println("-------")
|
||||
|
||||
checkOK(hr, "methodInfo.Invoke_3")
|
||||
fmt.Printf("[+] Executable returned code %d\n", pRetCode)
|
||||
|
||||
appDomain.Release()
|
||||
runtimeHost.Release()
|
||||
runtimeInfo.Release()
|
||||
metaHost.Release()
|
||||
|
||||
}
|
||||
|
||||
@@ -10,16 +10,7 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func GetMetaHost() (*ICLRMetaHost, error) {
|
||||
var pMetaHost uintptr
|
||||
hr := CLRCreateInstance(&CLSID_CLRMetaHost, &IID_ICLRMetaHost, &pMetaHost)
|
||||
err := checkOK(hr, "CLRCreateInstance")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewICLRMetaHost(pMetaHost), nil
|
||||
}
|
||||
|
||||
// GetInstallRuntimes is a wrapper function that returns an array of installed runtimes. Requires an existing ICLRMetaHost
|
||||
func GetInstalledRuntimes(metahost *ICLRMetaHost) ([]string, error) {
|
||||
var runtimes []string
|
||||
var pInstalledRuntimes uintptr
|
||||
@@ -28,7 +19,7 @@ func GetInstalledRuntimes(metahost *ICLRMetaHost) ([]string, error) {
|
||||
if err != nil {
|
||||
return runtimes, err
|
||||
}
|
||||
installedRuntimes := NewIEnumUnknown(pInstalledRuntimes)
|
||||
installedRuntimes := NewIEnumUnknownFromPtr(pInstalledRuntimes)
|
||||
var pRuntimeInfo uintptr
|
||||
var fetched = uint32(0)
|
||||
var versionString string
|
||||
@@ -40,7 +31,7 @@ func GetInstalledRuntimes(metahost *ICLRMetaHost) ([]string, error) {
|
||||
if hr != S_OK {
|
||||
break
|
||||
}
|
||||
runtimeInfo = NewICLRRuntimeInfo(pRuntimeInfo)
|
||||
runtimeInfo = NewICLRRuntimeInfoFromPtr(pRuntimeInfo)
|
||||
if ret := runtimeInfo.GetVersionString(&versionStringBytes[0], &versionStringSize); ret != S_OK {
|
||||
return runtimes, fmt.Errorf("GetVersionString returned 0x%08x", ret)
|
||||
}
|
||||
@@ -54,51 +45,12 @@ func GetInstalledRuntimes(metahost *ICLRMetaHost) ([]string, error) {
|
||||
return runtimes, err
|
||||
}
|
||||
|
||||
func GetRuntimeInfo(metahost *ICLRMetaHost, version string) (*ICLRRuntimeInfo, error) {
|
||||
pwzVersion, err := syscall.UTF16PtrFromString(version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pRuntimeInfo uintptr
|
||||
hr := metahost.GetRuntime(pwzVersion, &IID_ICLRRuntimeInfo, &pRuntimeInfo)
|
||||
err = checkOK(hr, "metahost.GetRuntime")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewICLRRuntimeInfo(pRuntimeInfo), nil
|
||||
}
|
||||
|
||||
func GetICLRRuntimeHost(runtimeInfo *ICLRRuntimeInfo) (*ICLRRuntimeHost, error) {
|
||||
var pRuntimeHost uintptr
|
||||
hr := runtimeInfo.GetInterface(&CLSID_CLRRuntimeHost, &IID_ICLRRuntimeHost, &pRuntimeHost)
|
||||
err := checkOK(hr, "runtimeInfo.GetInterface")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
runtimeHost := NewICLRRuntimeHost(pRuntimeHost)
|
||||
hr = runtimeHost.Start()
|
||||
err = checkOK(hr, "runtimeHost.Start")
|
||||
return runtimeHost, err
|
||||
}
|
||||
|
||||
func GetICORRuntimeHost(runtimeInfo *ICLRRuntimeInfo) (*ICORRuntimeHost, error) {
|
||||
var pRuntimeHost uintptr
|
||||
hr := runtimeInfo.GetInterface(&CLSID_CorRuntimeHost, &IID_ICorRuntimeHost, &pRuntimeHost)
|
||||
err := checkOK(hr, "runtimeInfo.GetInterface")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
runtimeHost := NewICORRuntimeHost(pRuntimeHost)
|
||||
hr = runtimeHost.Start()
|
||||
err = checkOK(hr, "runtimeHost.Start")
|
||||
return runtimeHost, err
|
||||
}
|
||||
|
||||
// ExecuteDLL is a wrapper function that will automatically load the latest installed CLR into the current process
|
||||
// and execute a DLL on disk in the default app domain
|
||||
// and execute a DLL on disk in the default app domain. It takes in the DLLPath, TypeName, MethodName and Argument to use
|
||||
// as strings. It returns the return code from the assembly
|
||||
func ExecuteDLL(dllpath, typeName, methodName, argument string) (retCode int16, err error) {
|
||||
retCode = -1
|
||||
metahost, err := GetMetaHost()
|
||||
metahost, err := GetICLRMetaHost()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -151,9 +103,12 @@ func ExecuteDLL(dllpath, typeName, methodName, argument string) (retCode int16,
|
||||
|
||||
}
|
||||
|
||||
// ExecuteByteArray is a wrapper function that will automatically load the latest supported framework into the current
|
||||
// process using the legacy APIs, then load and execute an executable from memory. It takes in a byte array of the
|
||||
// executable to load and run and returns the return code. It currently does not support any arguments on the entry point
|
||||
func ExecuteByteArray(rawBytes []byte) (retCode int32, err error) {
|
||||
retCode = -1
|
||||
metahost, err := GetMetaHost()
|
||||
metahost, err := GetICLRMetaHost()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -203,14 +158,14 @@ func ExecuteByteArray(rawBytes []byte) (retCode int32, err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
assembly := NewAssembly(pAssembly)
|
||||
assembly := NewAssemblyFromPtr(pAssembly)
|
||||
var pEntryPointInfo uintptr
|
||||
hr = assembly.GetEntryPoint(&pEntryPointInfo)
|
||||
err = checkOK(hr, "assembly.GetEntryPoint")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
methodInfo := NewMethodInfo(pEntryPointInfo)
|
||||
methodInfo := NewMethodInfoFromPtr(pEntryPointInfo)
|
||||
var pRetCode uintptr
|
||||
nullVariant := Variant{
|
||||
VT: 1,
|
||||
|
||||
@@ -11,6 +11,7 @@ var (
|
||||
|
||||
CLSID_CLRRuntimeHost = windows.GUID{0x90F1A06E, 0x7712, 0x4762, [8]byte{0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02}}
|
||||
IID_ICLRRuntimeHost = windows.GUID{0x90F1A06C, 0x7712, 0x4762, [8]byte{0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02}}
|
||||
|
||||
IID_ICorRuntimeHost = windows.GUID{0xcb2f6722, 0xab3a, 0x11d2, [8]byte{0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e}}
|
||||
CLSID_CorRuntimeHost = windows.GUID{0xcb2f6723, 0xab3a, 0x11d2, [8]byte{0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e}}
|
||||
|
||||
|
||||
+17
-17
@@ -14,6 +14,7 @@ var (
|
||||
procCLRCreateInstance = modMSCoree.NewProc("CLRCreateInstance")
|
||||
)
|
||||
|
||||
// Wrapper for the mscorree.dll CLRCreateInstance syscall
|
||||
func CLRCreateInstance(clsid, riid *windows.GUID, ppInterface *uintptr) uintptr {
|
||||
ret, _, _ := procCLRCreateInstance.Call(
|
||||
uintptr(unsafe.Pointer(clsid)),
|
||||
@@ -22,24 +23,15 @@ func CLRCreateInstance(clsid, riid *windows.GUID, ppInterface *uintptr) uintptr
|
||||
return ret
|
||||
}
|
||||
|
||||
func GetICLRMetaHost() (metahost *ICLRMetaHost, err error) {
|
||||
var pMetaHost uintptr
|
||||
hr := CLRCreateInstance(&CLSID_CLRMetaHost, &IID_ICLRMetaHost, &pMetaHost)
|
||||
err = checkOK(hr, "CLRCreateInstance")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
metahost = NewICLRMetaHost(pMetaHost)
|
||||
return
|
||||
}
|
||||
|
||||
//ICLRMetaHost Interface from metahost.h
|
||||
// Couldnt have done any of this without this SO answer I stumbled on:
|
||||
// https://stackoverflow.com/questions/37781676/how-to-use-com-component-object-model-in-golang
|
||||
|
||||
//ICLRMetaHost Interface from metahost.h
|
||||
type ICLRMetaHost struct {
|
||||
vtbl *ICLRMetaHostVtbl
|
||||
}
|
||||
|
||||
type ICLRMetaHostVtbl struct {
|
||||
QueryInterface uintptr
|
||||
AddRef uintptr
|
||||
@@ -53,8 +45,20 @@ type ICLRMetaHostVtbl struct {
|
||||
ExitProcess uintptr
|
||||
}
|
||||
|
||||
// newICLRMetaHost takes a uintptr to ICLRMetahost, which must come from the syscall CLRCreateInstance
|
||||
func NewICLRMetaHost(ppv uintptr) *ICLRMetaHost {
|
||||
// GetICLRMetaHost is a wrapper function to create and return an ICLRMetahost object
|
||||
func GetICLRMetaHost() (metahost *ICLRMetaHost, err error) {
|
||||
var pMetaHost uintptr
|
||||
hr := CLRCreateInstance(&CLSID_CLRMetaHost, &IID_ICLRMetaHost, &pMetaHost)
|
||||
err = checkOK(hr, "CLRCreateInstance")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
metahost = NewICLRMetaHostFromPtr(pMetaHost)
|
||||
return
|
||||
}
|
||||
|
||||
// NewICLRMetaHost takes a uintptr to an ICLRMetahost struct in memory. This pointer should come from the syscall CLRCreateInstance
|
||||
func NewICLRMetaHostFromPtr(ppv uintptr) *ICLRMetaHost {
|
||||
return (*ICLRMetaHost)(unsafe.Pointer(ppv))
|
||||
}
|
||||
|
||||
@@ -89,10 +93,6 @@ func (obj *ICLRMetaHost) EnumerateInstalledRuntimes(pInstalledRuntimes *uintptr)
|
||||
}
|
||||
|
||||
func (obj *ICLRMetaHost) GetRuntime(pwzVersion *uint16, riid *windows.GUID, pRuntimeHost *uintptr) uintptr {
|
||||
// v4Ptr, err := syscall.UTF16PtrFromString("v4.0.30319")
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
ret, _, _ := syscall.Syscall6(
|
||||
obj.vtbl.GetRuntime,
|
||||
4,
|
||||
|
||||
+15
-1
@@ -25,8 +25,22 @@ type ICLRRuntimeHostVtbl struct {
|
||||
ExecuteApplication uintptr
|
||||
ExecuteInDefaultAppDomain uintptr
|
||||
}
|
||||
// GetICLRRuntimeHost is a wrapper function that takes an ICLRRuntimeInfo object and
|
||||
// returns an ICLRRuntimeHost and loads it into the current process
|
||||
func GetICLRRuntimeHost(runtimeInfo *ICLRRuntimeInfo) (*ICLRRuntimeHost, error) {
|
||||
var pRuntimeHost uintptr
|
||||
hr := runtimeInfo.GetInterface(&CLSID_CLRRuntimeHost, &IID_ICLRRuntimeHost, &pRuntimeHost)
|
||||
err := checkOK(hr, "runtimeInfo.GetInterface")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
runtimeHost := NewICLRRuntimeHostFromPtr(pRuntimeHost)
|
||||
hr = runtimeHost.Start()
|
||||
err = checkOK(hr, "runtimeHost.Start")
|
||||
return runtimeHost, err
|
||||
}
|
||||
|
||||
func NewICLRRuntimeHost(ppv uintptr) *ICLRRuntimeHost {
|
||||
func NewICLRRuntimeHostFromPtr(ppv uintptr) *ICLRRuntimeHost {
|
||||
return (*ICLRRuntimeHost)(unsafe.Pointer(ppv))
|
||||
}
|
||||
|
||||
|
||||
+16
-1
@@ -30,7 +30,22 @@ type ICLRRuntimeInfoVtbl struct {
|
||||
IsStarted uintptr
|
||||
}
|
||||
|
||||
func NewICLRRuntimeInfo(ppv uintptr) *ICLRRuntimeInfo {
|
||||
// GetRuntimeInfo is a wrapper function to return an ICLRRuntimeInfo from a standard version string
|
||||
func GetRuntimeInfo(metahost *ICLRMetaHost, version string) (*ICLRRuntimeInfo, error) {
|
||||
pwzVersion, err := syscall.UTF16PtrFromString(version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pRuntimeInfo uintptr
|
||||
hr := metahost.GetRuntime(pwzVersion, &IID_ICLRRuntimeInfo, &pRuntimeInfo)
|
||||
err = checkOK(hr, "metahost.GetRuntime")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewICLRRuntimeInfoFromPtr(pRuntimeInfo), nil
|
||||
}
|
||||
|
||||
func NewICLRRuntimeInfoFromPtr(ppv uintptr) *ICLRRuntimeInfo {
|
||||
return (*ICLRRuntimeInfo)(unsafe.Pointer(ppv))
|
||||
}
|
||||
|
||||
|
||||
+17
-1
@@ -36,7 +36,23 @@ type ICORRuntimeHostVtbl struct {
|
||||
CurrentDomain uintptr
|
||||
}
|
||||
|
||||
func NewICORRuntimeHost(ppv uintptr) *ICORRuntimeHost {
|
||||
// GetICORRuntimeHost is a wrapper function that takes in an ICLRRuntimeInfo and returns an ICORRuntimeHost object
|
||||
// and loads it into the current process. This is the "deprecated" API, but the only way currently to load an assembly
|
||||
// from memory (afaict)
|
||||
func GetICORRuntimeHost(runtimeInfo *ICLRRuntimeInfo) (*ICORRuntimeHost, error) {
|
||||
var pRuntimeHost uintptr
|
||||
hr := runtimeInfo.GetInterface(&CLSID_CorRuntimeHost, &IID_ICorRuntimeHost, &pRuntimeHost)
|
||||
err := checkOK(hr, "runtimeInfo.GetInterface")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
runtimeHost := NewICORRuntimeHostFromPtr(pRuntimeHost)
|
||||
hr = runtimeHost.Start()
|
||||
err = checkOK(hr, "runtimeHost.Start")
|
||||
return runtimeHost, err
|
||||
}
|
||||
|
||||
func NewICORRuntimeHostFromPtr(ppv uintptr) *ICORRuntimeHost {
|
||||
return (*ICORRuntimeHost)(unsafe.Pointer(ppv))
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ type IEnumUnknownVtbl struct {
|
||||
Clone uintptr
|
||||
}
|
||||
|
||||
func NewIEnumUnknown(ppv uintptr) *IEnumUnknown {
|
||||
func NewIEnumUnknownFromPtr(ppv uintptr) *IEnumUnknown {
|
||||
return (*IEnumUnknown)(unsafe.Pointer(ppv))
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ type IUnknownVtbl struct {
|
||||
Release uintptr
|
||||
}
|
||||
|
||||
func NewIUnknown(ppv uintptr) *IUnknown {
|
||||
func NewIUnknownFromPtr(ppv uintptr) *IUnknown {
|
||||
return (*IUnknown)(unsafe.Pointer(ppv))
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ type MethodInfoVtbl struct {
|
||||
GetBaseDefinition uintptr
|
||||
}
|
||||
|
||||
func NewMethodInfo(ppv uintptr) *MethodInfo {
|
||||
func NewMethodInfoFromPtr(ppv uintptr) *MethodInfo {
|
||||
return (*MethodInfo)(unsafe.Pointer(ppv))
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ type SafeArrayBound struct {
|
||||
lLbound int32
|
||||
}
|
||||
|
||||
// CreateSafeArray is a wrapper function that takes in a Go byte array and creates a SafeArray by making two syscalls
|
||||
// and copying raw memory into the correct spot.
|
||||
func CreateSafeArray(rawBytes []byte) (SafeArray, error) {
|
||||
modOleAuto, err := syscall.LoadDLL("OleAut32.dll")
|
||||
if err != nil {
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ package clr
|
||||
|
||||
import "unsafe"
|
||||
|
||||
//from https://github.com/go-ole/go-ole/blob/master/variant_amd64.go
|
||||
// from https://github.com/go-ole/go-ole/blob/master/variant_amd64.go
|
||||
|
||||
type Variant struct {
|
||||
VT uint16 // VARTYPE
|
||||
@@ -15,6 +15,6 @@ type Variant struct {
|
||||
_ [8]byte
|
||||
}
|
||||
|
||||
func variantFromPtr(ppv uintptr) *Variant {
|
||||
func NewVariantFromPtr(ppv uintptr) *Variant {
|
||||
return (*Variant)(unsafe.Pointer(ppv))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user