mirror of
https://github.com/ropnop/go-clr
synced 2026-06-08 17:11:59 +00:00
both examples working
This commit is contained in:
+6
-3
@@ -1,9 +1,12 @@
|
||||
package main
|
||||
// +build windows
|
||||
|
||||
package clr
|
||||
|
||||
import (
|
||||
"github.com/Microsoft/go-winio/pkg/guid"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Microsoft/go-winio/pkg/guid"
|
||||
)
|
||||
|
||||
type AppDomain struct {
|
||||
@@ -83,7 +86,7 @@ type AppDomainVtbl struct {
|
||||
get_DynamicDirectory uintptr
|
||||
}
|
||||
|
||||
func newAppDomain(ppv uintptr) *AppDomain {
|
||||
func NewAppDomain(ppv uintptr) *AppDomain {
|
||||
return (*AppDomain)(unsafe.Pointer(ppv))
|
||||
}
|
||||
|
||||
|
||||
+10
-3
@@ -1,9 +1,12 @@
|
||||
package main
|
||||
// +build windows
|
||||
|
||||
package clr
|
||||
|
||||
import (
|
||||
"github.com/Microsoft/go-winio/pkg/guid"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Microsoft/go-winio/pkg/guid"
|
||||
)
|
||||
|
||||
// from mscorlib.tlh
|
||||
@@ -16,6 +19,10 @@ type AssemblyVtbl struct {
|
||||
QueryInterface uintptr
|
||||
AddRef uintptr
|
||||
Release uintptr
|
||||
GetTypeInfoCount uintptr
|
||||
GetTypeInfo uintptr
|
||||
GetIDsOfNames uintptr
|
||||
Invoke uintptr
|
||||
get_ToString uintptr
|
||||
Equals uintptr
|
||||
GetHashCode uintptr
|
||||
@@ -62,7 +69,7 @@ type AssemblyVtbl struct {
|
||||
get_GlobalAssemblyCache uintptr
|
||||
}
|
||||
|
||||
func newAssembly(ppv uintptr) *Assembly {
|
||||
func NewAssembly(ppv uintptr) *Assembly {
|
||||
return (*Assembly)(unsafe.Pointer(ppv))
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
// +build windows
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"syscall"
|
||||
|
||||
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", hr)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
metahost, err := clr.GetICLRMetaHost()
|
||||
must(err)
|
||||
fmt.Println("[+] Got metahost")
|
||||
|
||||
installedRuntimes, err := clr.GetInstalledRuntimes(metahost)
|
||||
must(err)
|
||||
fmt.Printf("[+] Found installed runtimes: %s\n", installedRuntimes)
|
||||
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)
|
||||
fmt.Printf("[+] Using runtime: %s\n", versionString)
|
||||
|
||||
var isLoadable bool
|
||||
hr = runtimeInfo.IsLoadable(&isLoadable)
|
||||
checkOK(hr, "runtimeInfo.IsLoadable")
|
||||
if !isLoadable {
|
||||
log.Fatal("[!] IsLoadable returned false. Bailing...")
|
||||
}
|
||||
|
||||
var pRuntimeHost uintptr
|
||||
hr = runtimeInfo.GetInterface(&clr.CLSID_CLRRuntimeHost, &clr.IID_ICLRRuntimeHost, &pRuntimeHost)
|
||||
checkOK(hr, "runtimeInfo.GetInterface")
|
||||
runtimeHost := clr.NewICLRRuntimeHost(pRuntimeHost)
|
||||
|
||||
hr = runtimeHost.Start()
|
||||
checkOK(hr, "runtimeHost.Start")
|
||||
fmt.Println("[+] Loaded CLR into this process")
|
||||
|
||||
fmt.Println("[+] Executing assembly...")
|
||||
pDLLPath, _ := syscall.UTF16PtrFromString("TestDLL.dll")
|
||||
pTypeName, _ := syscall.UTF16PtrFromString("TestDLL.HelloWorld")
|
||||
pMethodName, _ := syscall.UTF16PtrFromString("SayHello")
|
||||
pArgument, _ := syscall.UTF16PtrFromString("foobar")
|
||||
var pReturnVal *uint16
|
||||
hr = runtimeHost.ExecuteInDefaultAppDomain(
|
||||
pDLLPath,
|
||||
pTypeName,
|
||||
pMethodName,
|
||||
pArgument,
|
||||
pReturnVal)
|
||||
|
||||
checkOK(hr, "runtimeHost.ExecuteInDefaultAppDomain")
|
||||
fmt.Printf("[+] Assembly returned: 0x%x\n", pReturnVal)
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
// +build windows
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"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 main() {
|
||||
metaHost, err := clr.GetMetaHost()
|
||||
must(err)
|
||||
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")
|
||||
|
||||
testEXEBytes, err := ioutil.ReadFile("./TestEXE.exe")
|
||||
must(err)
|
||||
runtime.KeepAlive(testEXEBytes)
|
||||
|
||||
fmt.Printf("[+] Loaded %d bytes into memory from TestExe.exe\n", len(testEXEBytes))
|
||||
|
||||
safeArray, err := clr.CreateSafeArray(testEXEBytes)
|
||||
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()
|
||||
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
// +build windows
|
||||
|
||||
package clr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var (
|
||||
Metahost *ICLRMetaHost
|
||||
RuntimeInfo *ICLRRuntimeInfo
|
||||
IsLoadable bool
|
||||
LegacyV2Runtime bool
|
||||
CorRuntimeHost *ICORRuntimeHost
|
||||
ClrRuntimeHost *ICLRRuntimeHost
|
||||
Iu *IUnknown
|
||||
LoadedAppDomain *AppDomain
|
||||
LoadedAssembly *Assembly
|
||||
EntryPoint *MethodInfo
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
func GetInstalledRuntimes(metahost *ICLRMetaHost) ([]string, error) {
|
||||
var runtimes []string
|
||||
var pInstalledRuntimes uintptr
|
||||
hr := metahost.EnumerateInstalledRuntimes(&pInstalledRuntimes)
|
||||
err := checkOK(hr, "EnumerateInstalledRuntimes")
|
||||
if err != nil {
|
||||
return runtimes, err
|
||||
}
|
||||
installedRuntimes := NewIEnumUnknown(pInstalledRuntimes)
|
||||
var pRuntimeInfo uintptr
|
||||
var fetched = uint32(0)
|
||||
var versionString string
|
||||
versionStringBytes := make([]uint16, 20)
|
||||
versionStringSize := uint32(len(versionStringBytes))
|
||||
var runtimeInfo *ICLRRuntimeInfo
|
||||
for {
|
||||
hr = installedRuntimes.Next(1, &pRuntimeInfo, &fetched)
|
||||
if hr != S_OK {
|
||||
break
|
||||
}
|
||||
runtimeInfo = NewICLRRuntimeInfo(pRuntimeInfo)
|
||||
if ret := runtimeInfo.GetVersionString(&versionStringBytes[0], &versionStringSize); ret != S_OK {
|
||||
return runtimes, fmt.Errorf("GetVersionString returned 0x%08x", ret)
|
||||
}
|
||||
versionString = syscall.UTF16ToString(versionStringBytes)
|
||||
runtimes = append(runtimes, versionString)
|
||||
}
|
||||
if len(runtimes) == 0 {
|
||||
return runtimes, fmt.Errorf("Could not find any installed runtimes")
|
||||
}
|
||||
runtimeInfo.Release()
|
||||
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_CorRuntimeHost, &IID_ICLRRuntimeHost, &pRuntimeHost)
|
||||
err := checkOK(hr, "runtimeInfo.GetInterface")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewICLRRuntimeHost(pRuntimeHost), nil
|
||||
}
|
||||
|
||||
// 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
|
||||
func ExecuteDLL(dllpath, typeName, methodName, argument string) (retCode int, err error) {
|
||||
retCode = -1
|
||||
metahost, err := GetMetaHost()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer metahost.Release()
|
||||
|
||||
runtimes, err := GetInstalledRuntimes(metahost)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var latestRuntime string
|
||||
for _, r := range runtimes {
|
||||
if strings.Contains(r, "v4") {
|
||||
latestRuntime = r
|
||||
break
|
||||
} else {
|
||||
latestRuntime = r
|
||||
}
|
||||
}
|
||||
runtimeInfo, err := GetRuntimeInfo(metahost, latestRuntime)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer runtimeInfo.Release()
|
||||
var isLoadable bool
|
||||
hr := runtimeInfo.IsLoadable(&isLoadable)
|
||||
err = checkOK(hr, "runtimeInfo.IsLoadable")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !isLoadable {
|
||||
return -1, fmt.Errorf("%s is not loadable for some reason", latestRuntime)
|
||||
}
|
||||
runtimeHost, err := GetICLRRuntimeHost(runtimeInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer runtimeHost.Release()
|
||||
hr = runtimeHost.Start()
|
||||
err = checkOK(hr, "runtimeHost.Start")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
pDLLPath, _ := syscall.UTF16PtrFromString(dllpath)
|
||||
pTypeName, _ := syscall.UTF16PtrFromString(typeName)
|
||||
pMethodName, _ := syscall.UTF16PtrFromString(methodName)
|
||||
pArgument, _ := syscall.UTF16PtrFromString(argument)
|
||||
var pReturnVal *uint16
|
||||
hr = runtimeHost.ExecuteInDefaultAppDomain(pDLLPath, pTypeName, pMethodName, pArgument, pReturnVal)
|
||||
err = checkOK(hr, "runtimeHost.ExecuteInDefaultAppDomain")
|
||||
if err != nil {
|
||||
return int(*pReturnVal), err
|
||||
}
|
||||
return int(*pReturnVal), nil
|
||||
|
||||
}
|
||||
@@ -4,7 +4,5 @@ go 1.13
|
||||
|
||||
require (
|
||||
github.com/Microsoft/go-winio v0.4.14
|
||||
github.com/go-ole/go-ole v1.2.4
|
||||
github.com/pkg/errors v0.9.1
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527
|
||||
)
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
|
||||
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package clr
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var (
|
||||
CLSID_CLRMetaHost = windows.GUID{0x9280188d, 0xe8e, 0x4867, [8]byte{0xb3, 0xc, 0x7f, 0xa8, 0x38, 0x84, 0xe8, 0xde}}
|
||||
IID_ICLRMetaHost = windows.GUID{0xD332DB9E, 0xB9B3, 0x4125, [8]byte{0x82, 0x07, 0xA1, 0x48, 0x84, 0xF5, 0x32, 0x16}}
|
||||
IID_ICLRRuntimeInfo = windows.GUID{0xBD39D1D2, 0xBA2F, 0x486a, [8]byte{0x89, 0xB0, 0xB4, 0xB0, 0xCB, 0x46, 0x68, 0x91}}
|
||||
|
||||
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}}
|
||||
|
||||
IID_AppDomain = windows.GUID{0x5f696dc, 0x2b29, 0x3663, [8]uint8{0xad, 0x8b, 0xc4, 0x38, 0x9c, 0xf2, 0xa7, 0x13}}
|
||||
)
|
||||
+24
-21
@@ -1,19 +1,20 @@
|
||||
//+build windows
|
||||
// +build windows
|
||||
|
||||
package main
|
||||
package clr
|
||||
|
||||
import (
|
||||
"github.com/Microsoft/go-winio/pkg/guid"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var (
|
||||
modMSCoree = syscall.MustLoadDLL("mscoree.dll")
|
||||
procCLRCreateInstance = modMSCoree.MustFindProc("CLRCreateInstance")
|
||||
modMSCoree = syscall.NewLazyDLL("mscoree.dll")
|
||||
procCLRCreateInstance = modMSCoree.NewProc("CLRCreateInstance")
|
||||
)
|
||||
|
||||
func CLRCreateInstance(clsid, riid *guid.GUID, ppInterface *uintptr) uintptr {
|
||||
func CLRCreateInstance(clsid, riid *windows.GUID, ppInterface *uintptr) uintptr {
|
||||
ret, _, _ := procCLRCreateInstance.Call(
|
||||
uintptr(unsafe.Pointer(clsid)),
|
||||
uintptr(unsafe.Pointer(riid)),
|
||||
@@ -21,14 +22,16 @@ func CLRCreateInstance(clsid, riid *guid.GUID, ppInterface *uintptr) uintptr {
|
||||
return ret
|
||||
}
|
||||
|
||||
// GetICLRMetaHost
|
||||
//func GetICLRMetaHost() (*ICLRMetaHost, error) {
|
||||
// var ppInterface uintptr
|
||||
// if hr := getICLRMetaHostPtr(&ppInterface); hr != S_OK {
|
||||
// return nil, fmt.Errorf("Could not get pointer to ICLRMetaHost. HRESULT: 0x%x", hr)
|
||||
// }
|
||||
// return newICLRMetaHost(ppInterface), nil
|
||||
//}
|
||||
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
|
||||
// https://stackoverflow.com/questions/37781676/how-to-use-com-component-object-model-in-golang
|
||||
@@ -49,7 +52,7 @@ type ICLRMetaHostVtbl struct {
|
||||
}
|
||||
|
||||
// newICLRMetaHost takes a uintptr to ICLRMetahost, which must come from the syscall CLRCreateInstance
|
||||
func newICLRMetaHost(ppv uintptr) *ICLRMetaHost {
|
||||
func NewICLRMetaHost(ppv uintptr) *ICLRMetaHost {
|
||||
return (*ICLRMetaHost)(unsafe.Pointer(ppv))
|
||||
}
|
||||
|
||||
@@ -83,16 +86,16 @@ func (obj *ICLRMetaHost) EnumerateInstalledRuntimes(pInstalledRuntimes *uintptr)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (obj *ICLRMetaHost) GetRuntime(pwzVersion *uint16, riid *guid.GUID, pRuntimeHost *uintptr) uintptr {
|
||||
v4Ptr, err := syscall.UTF16PtrFromString("v4.0.30319")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
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,
|
||||
uintptr(unsafe.Pointer(obj)),
|
||||
uintptr(unsafe.Pointer(v4Ptr)),
|
||||
uintptr(unsafe.Pointer(pwzVersion)),
|
||||
uintptr(unsafe.Pointer(&IID_ICLRRuntimeInfo)),
|
||||
uintptr(unsafe.Pointer(pRuntimeHost)),
|
||||
0,
|
||||
|
||||
+5
-3
@@ -1,4 +1,6 @@
|
||||
package main
|
||||
// +build windows
|
||||
|
||||
package clr
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
@@ -24,7 +26,7 @@ type ICLRRuntimeHostVtbl struct {
|
||||
ExecuteInDefaultAppDomain uintptr
|
||||
}
|
||||
|
||||
func newICLRRuntimeHost(ppv uintptr) *ICLRRuntimeHost {
|
||||
func NewICLRRuntimeHost(ppv uintptr) *ICLRRuntimeHost {
|
||||
return (*ICLRRuntimeHost)(unsafe.Pointer(ppv))
|
||||
}
|
||||
|
||||
@@ -74,7 +76,7 @@ func (obj *ICLRRuntimeHost) ExecuteInDefaultAppDomain(pwzAssemblyPath, pwzTypeNa
|
||||
return ret
|
||||
}
|
||||
|
||||
func (obj *ICLRRuntimeHost) GetCurrentappDomainID(pdwAppDomainId *uint16) uintptr {
|
||||
func (obj *ICLRRuntimeHost) GetCurrentAppDomainID(pdwAppDomainId *uint16) uintptr {
|
||||
ret, _, _ := syscall.Syscall(
|
||||
obj.vtbl.GetCurrentAppDomainId,
|
||||
2,
|
||||
|
||||
+6
-4
@@ -1,7 +1,9 @@
|
||||
package main
|
||||
// +build windows
|
||||
|
||||
package clr
|
||||
|
||||
import (
|
||||
"github.com/Microsoft/go-winio/pkg/guid"
|
||||
"golang.org/x/sys/windows"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
@@ -28,7 +30,7 @@ type ICLRRuntimeInfoVtbl struct {
|
||||
IsStarted uintptr
|
||||
}
|
||||
|
||||
func newICLRRuntimeInfo(ppv uintptr) *ICLRRuntimeInfo {
|
||||
func NewICLRRuntimeInfo(ppv uintptr) *ICLRRuntimeInfo {
|
||||
return (*ICLRRuntimeInfo)(unsafe.Pointer(ppv))
|
||||
}
|
||||
|
||||
@@ -62,7 +64,7 @@ func (obj *ICLRRuntimeInfo) GetVersionString(pcchBuffer *uint16, pVersionstringS
|
||||
return ret
|
||||
}
|
||||
|
||||
func (obj *ICLRRuntimeInfo) GetInterface(rclsid *guid.GUID, riid *guid.GUID, ppUnk *uintptr) uintptr {
|
||||
func (obj *ICLRRuntimeInfo) GetInterface(rclsid *windows.GUID, riid *windows.GUID, ppUnk *uintptr) uintptr {
|
||||
ret, _, _ := syscall.Syscall6(
|
||||
obj.vtbl.GetInterface,
|
||||
4,
|
||||
|
||||
+4
-2
@@ -1,4 +1,6 @@
|
||||
package main
|
||||
// +build windows
|
||||
|
||||
package clr
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
@@ -34,7 +36,7 @@ type ICORRuntimeHostVtbl struct {
|
||||
CurrentDomain uintptr
|
||||
}
|
||||
|
||||
func newICORRuntimeHost(ppv uintptr) *ICORRuntimeHost {
|
||||
func NewICORRuntimeHost(ppv uintptr) *ICORRuntimeHost {
|
||||
return (*ICORRuntimeHost)(unsafe.Pointer(ppv))
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -1,4 +1,6 @@
|
||||
package main
|
||||
// +build windows
|
||||
|
||||
package clr
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
@@ -19,7 +21,7 @@ type IEnumUnknownVtbl struct {
|
||||
Clone uintptr
|
||||
}
|
||||
|
||||
func newIEnumUnknown(ppv uintptr) *IEnumUnknown {
|
||||
func NewIEnumUnknown(ppv uintptr) *IEnumUnknown {
|
||||
return (*IEnumUnknown)(unsafe.Pointer(ppv))
|
||||
}
|
||||
|
||||
|
||||
+7
-4
@@ -1,9 +1,12 @@
|
||||
package main
|
||||
// +build windows
|
||||
|
||||
package clr
|
||||
|
||||
import (
|
||||
"github.com/Microsoft/go-winio/pkg/guid"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
type IUnknown struct {
|
||||
@@ -16,11 +19,11 @@ type IUnknownVtbl struct {
|
||||
Release uintptr
|
||||
}
|
||||
|
||||
func newIUnknown(ppv uintptr) *IUnknown {
|
||||
func NewIUnknown(ppv uintptr) *IUnknown {
|
||||
return (*IUnknown)(unsafe.Pointer(ppv))
|
||||
}
|
||||
|
||||
func (obj *IUnknown) QueryInterface(riid *guid.GUID, ppvObject *uintptr) uintptr {
|
||||
func (obj *IUnknown) QueryInterface(riid *windows.GUID, ppvObject *uintptr) uintptr {
|
||||
ret, _, _ := syscall.Syscall(
|
||||
obj.vtbl.QueryInterface,
|
||||
3,
|
||||
|
||||
@@ -1,273 +1 @@
|
||||
//+build windows
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/Microsoft/go-winio/pkg/guid"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
//ole "github.com/go-ole/go-ole"
|
||||
//"github.com/go-ole/go-ole/oleutil"
|
||||
)
|
||||
|
||||
const S_OK = 0
|
||||
const E_POINTER = 0x80004003
|
||||
|
||||
var (
|
||||
CLSID_CLRMetaHost = guid.GUID{0x9280188d, 0xe8e, 0x4867, [8]byte{0xb3, 0xc, 0x7f, 0xa8, 0x38, 0x84, 0xe8, 0xde}}
|
||||
IID_ICLRMetaHost = guid.GUID{0xD332DB9E, 0xB9B3, 0x4125, [8]byte{0x82, 0x07, 0xA1, 0x48, 0x84, 0xF5, 0x32, 0x16}}
|
||||
IID_ICLRRuntimeInfo = guid.GUID{0xBD39D1D2, 0xBA2F, 0x486a, [8]byte{0x89, 0xB0, 0xB4, 0xB0, 0xCB, 0x46, 0x68, 0x91}}
|
||||
|
||||
//EXTERN_GUID(CLSID_CLRRuntimeHost, 0x90F1A06E, 0x7712, 0x4762, 0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02);
|
||||
CLSID_CLRRuntimeHost = guid.GUID{0x90F1A06E, 0x7712, 0x4762, [8]byte{0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02}}
|
||||
|
||||
//EXTERN_GUID(IID_ICLRRuntimeHost, 0x90F1A06C, 0x7712, 0x4762, 0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02);
|
||||
IID_ICLRRuntimeHost = guid.GUID{0x90F1A06C, 0x7712, 0x4762, [8]byte{0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02}}
|
||||
|
||||
//EXTERN_GUID(IID_ICorRuntimeHost, 0xcb2f6722, 0xab3a, 0x11d2, 0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e);
|
||||
IID_ICorRuntimeHost = guid.GUID{0xcb2f6722, 0xab3a, 0x11d2, [8]byte{0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e}}
|
||||
|
||||
//EXTERN_GUID(CLSID_CorRuntimeHost, 0xcb2f6723, 0xab3a, 0x11d2, 0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e);
|
||||
CLSID_CorRuntimeHost = guid.GUID{0xcb2f6723, 0xab3a, 0x11d2, [8]byte{0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e}}
|
||||
|
||||
//https://docs.microsoft.com/en-us/dotnet/api/system._appdomain?view=netframework-4.8
|
||||
// _AppDomain Interface GUID
|
||||
IID_AppDomain = guid.GUID{0x5f696dc, 0x2b29, 0x3663, [8]uint8{0xad, 0x8b, 0xc4, 0x38, 0x9c, 0xf2, 0xa7, 0x13}}
|
||||
)
|
||||
|
||||
func must(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func checkOK(hr uintptr) {
|
||||
if hr == S_OK {
|
||||
return
|
||||
} else if hr == E_POINTER {
|
||||
log.Fatalf("Error getting pointer: 0x%x\n", hr)
|
||||
} else {
|
||||
log.Fatalf("Unknown return result: 0x%x\n", hr)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
var pMetaHost uintptr
|
||||
var metaHost *ICLRMetaHost
|
||||
hr := CLRCreateInstance(&CLSID_CLRMetaHost, &IID_ICLRMetaHost, &pMetaHost)
|
||||
checkOK(hr)
|
||||
metaHost = newICLRMetaHost(pMetaHost)
|
||||
|
||||
//metaHost, err := GetICLRMetaHost()
|
||||
//must(err)
|
||||
//var pInstalledRuntimes uintptr
|
||||
//
|
||||
//hr = metaHost.EnumerateInstalledRuntimes(&pInstalledRuntimes)
|
||||
//
|
||||
//checkOK(hr)
|
||||
//installedRuntimes := newIEnumUnknown(pInstalledRuntimes)
|
||||
//
|
||||
//var pRuntimeInfo uintptr
|
||||
//var fetched = uint32(0)
|
||||
//var versionString string
|
||||
//versionStringBytes := make([]uint16, 20)
|
||||
//versionStringSize := uint32(20)
|
||||
//var runtimeInfo *ICLRRuntimeInfo
|
||||
//fmt.Println("[+] Enumerating installed runtimes...")
|
||||
//for {
|
||||
// hr = installedRuntimes.Next(1, &pRuntimeInfo, &fetched )
|
||||
// if hr != S_OK {break}
|
||||
// runtimeInfo = newICLRRuntimeInfo(pRuntimeInfo)
|
||||
// if ret := runtimeInfo.GetVersionString(&versionStringBytes[0], &versionStringSize); ret != S_OK {
|
||||
// log.Fatalf("[+] Error getting version string: 0x%x", ret)
|
||||
// }
|
||||
// versionString = syscall.UTF16ToString(versionStringBytes)
|
||||
// fmt.Printf("\t[+] Found: %s\n", versionString)
|
||||
//}
|
||||
//fmt.Printf("[+] Using latest supported framework: %s\n", versionString)
|
||||
|
||||
//So I'll use the older API for now
|
||||
var pRuntimeInfo uintptr
|
||||
var runtimeInfo *ICLRRuntimeInfo
|
||||
versionString := "v4.0.30319"
|
||||
pwzVersion, _ := syscall.UTF16PtrFromString(versionString)
|
||||
hr = metaHost.GetRuntime(pwzVersion, &IID_ICLRRuntimeInfo, &pRuntimeInfo)
|
||||
checkOK(hr)
|
||||
runtimeInfo = newICLRRuntimeInfo(pRuntimeInfo)
|
||||
fmt.Println("[+] Got RuntimeHost")
|
||||
var isLoadable bool
|
||||
hr = runtimeInfo.IsLoadable(&isLoadable)
|
||||
checkOK(hr)
|
||||
fmt.Printf("[+] isLoadable: %t\n", isLoadable)
|
||||
|
||||
if !isLoadable {
|
||||
log.Fatal("[!] IsLoadable returned false. Won't load CLR")
|
||||
}
|
||||
|
||||
fmt.Println("[+] BindAsLegacyV2Runtime...")
|
||||
hr = runtimeInfo.BindAsLegacyV2Runtime()
|
||||
checkOK(hr)
|
||||
|
||||
var pRuntimeHost uintptr
|
||||
// This is the "new" API, but I can't figure out how to load assemblies from memory in unmanaged code :/
|
||||
//hr = runtimeInfo.GetInterface(&CLSID_CLRRuntimeHost, &IID_ICLRRuntimeHost, &pRuntimeHost)
|
||||
|
||||
// So I'll use the older API for now
|
||||
//pwzVersion, _ := syscall.UTF16PtrFromString(versionString)
|
||||
//hr = metaHost.GetRuntime(pwzVersion, &IID_ICLRRuntimeInfo, &pRuntimeInfo)
|
||||
//checkOK(hr)
|
||||
//runtimeInfo = newICLRRuntimeInfo(pRuntimeInfo)
|
||||
fmt.Println("[+] Getting interface...")
|
||||
hr = runtimeInfo.GetInterface(&CLSID_CorRuntimeHost, &IID_ICorRuntimeHost, &pRuntimeHost)
|
||||
checkOK(hr)
|
||||
runTimeHost := newICORRuntimeHost(pRuntimeHost)
|
||||
fmt.Println("[+] Got interface. Loading CLR...")
|
||||
hr = runTimeHost.Start()
|
||||
checkOK(hr)
|
||||
fmt.Println("[+] Loaded CLR into this process")
|
||||
|
||||
fmt.Println("[+] Getting Default AppDomain")
|
||||
|
||||
//ole.CoInitialize(0)
|
||||
//var pIUnknown uintptr
|
||||
//https://docs.microsoft.com/en-us/dotnet/api/system._appdomain?view=netframework-4.8
|
||||
//unknown, err := oleutil.CreateObject("{05F696DC-2B29-3663-AD8B-C4389CF2A713}")
|
||||
//if err != nil {
|
||||
// fmt.Printf("createobject failed: %s", err)
|
||||
//}
|
||||
//must(err)
|
||||
//iid, _ := oleutil.ClassIDFrom("{05F696DC-2B29-3663-AD8B-C4389CF2A713}")
|
||||
//oleappdomain, _ := unknown.QueryInterface(ole.IID_IDispatch)
|
||||
|
||||
var pAppDomain uintptr
|
||||
var pIUnknown uintptr
|
||||
hr = runTimeHost.GetDefaultDomain(&pIUnknown)
|
||||
checkOK(hr)
|
||||
iu := newIUnknown(pIUnknown)
|
||||
//appDomainGuid, err := guid.FromString("05F696DC-2B29-3663-AD8B-C4389CF2A713")
|
||||
//must(err)
|
||||
hr = iu.QueryInterface(&IID_AppDomain, &pAppDomain)
|
||||
appDomain := newAppDomain(pAppDomain)
|
||||
fmt.Println("[+] Got default appdomain")
|
||||
|
||||
//box := packr.New("EXEs", "./static")
|
||||
//testEXEBytes, err := box.Find("TestEXE.exe")
|
||||
//must(err)
|
||||
testEXEBytes, err := ioutil.ReadFile("./static/TestEXE.exe")
|
||||
must(err)
|
||||
//testEXEBytes := []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41}
|
||||
fmt.Printf("[+] Loaded %d bytes from TestExe.exe\n", len(testEXEBytes))
|
||||
|
||||
safeArray, err := createSafeArray(testEXEBytes)
|
||||
must(err)
|
||||
|
||||
var pAssembly uintptr
|
||||
hr = appDomain.Load_3(uintptr(unsafe.Pointer(&safeArray)), &pAssembly)
|
||||
checkOK(hr)
|
||||
|
||||
fmt.Printf("[+] Assembly loaded into memory at 0x%08x\n", pAssembly)
|
||||
assembly := newAssembly(pAssembly)
|
||||
var pEntryPointInfo uintptr
|
||||
fmt.Printf("entrypoint: 0x%08x\n", pEntryPointInfo)
|
||||
hr = assembly.GetEntryPoint(&pEntryPointInfo)
|
||||
checkOK(hr)
|
||||
fmt.Printf("entrypoint: 0x%08x\n", pEntryPointInfo)
|
||||
fmt.Println("[+] Found assembly entrypoint")
|
||||
|
||||
var pRetCode uintptr
|
||||
nullVariant := Variant{
|
||||
VT: 1,
|
||||
Val: 0,
|
||||
}
|
||||
|
||||
|
||||
//printRawData(uintptr(unsafe.Pointer(&nullVariant)), unsafe.Sizeof(nullVariant))
|
||||
methodInfo := newMethodInfo(pEntryPointInfo)
|
||||
//methodGUID, err := guid.FromString("ffcc1b5d-ecb8-38dd-9b01-3dc8abc2aa5f")
|
||||
//must(err)
|
||||
//iu = newIUnknown(pEntryPointInfo)
|
||||
//hr = iu.QueryInterface(&methodGUID, &pRetCode)
|
||||
//checkOK(hr)
|
||||
//fmt.Printf("[+] MethodInfo at 0x%08x\n", pRetCode)
|
||||
////
|
||||
////methodInfo := newMethodInfo(pRetCode)
|
||||
//fmt.Println("testing gettype")
|
||||
//hr = methodInfo.GetType(&pRetCode)
|
||||
//checkOK(hr)
|
||||
//
|
||||
|
||||
fmt.Println("[+] Calling default entry point with no args")
|
||||
hr = methodInfo.Invoke_3(
|
||||
uintptr(unsafe.Pointer(&nullVariant)),
|
||||
uintptr(0),
|
||||
&pRetCode)
|
||||
checkOK(hr)
|
||||
|
||||
//var appDomainID uint16
|
||||
//runTimeHost.GetCurrentappDomainID(&appDomainID)
|
||||
//checkOK(hr)
|
||||
//fmt.Printf("[+] Current AppDomain ID: %d\n", appDomainID)
|
||||
//
|
||||
//fmt.Println("[+] Executing assembly...")
|
||||
//pDLLPath, _ := syscall.UTF16PtrFromString("TestDLL.dll")
|
||||
//pTypeName, _ := syscall.UTF16PtrFromString("TestDLL.HelloWorld")
|
||||
//pMethodName, _ := syscall.UTF16PtrFromString("SayHello")
|
||||
//pArgument, _ := syscall.UTF16PtrFromString("foobar")
|
||||
//var pReturnVal *uint16
|
||||
//hr = runTimeHost.ExecuteInDefaultAppDomain(
|
||||
// pDLLPath,
|
||||
// pTypeName,
|
||||
// pMethodName,
|
||||
// pArgument,
|
||||
// pReturnVal)
|
||||
//
|
||||
//checkOK(hr)
|
||||
//fmt.Printf("[+] Assembly returned: 0x%x\n", pReturnVal)
|
||||
|
||||
//if hr == S_OK {
|
||||
// log.Println("[+] Enumerating runtimes")
|
||||
//} else if hr == E_POINTER {
|
||||
// log.Fatal("[!] Couldn't get pointer to enumerate runtimes")
|
||||
//} else {
|
||||
// log.Fatalf("[!] Unknown error: %x\n", hr)
|
||||
//}
|
||||
//
|
||||
//
|
||||
//
|
||||
//var pRuntimeInfo uintptr
|
||||
//
|
||||
//hr = metaHost.GetRuntime("v4.0.30319", pRuntimeInfo)
|
||||
//if hr == S_OK {
|
||||
// log.Println("[+] Got Runtime!")
|
||||
//} else if hr == E_POINTER {
|
||||
// log.Fatalf("[!] Error getting runtime pointer: %x\n", hr)
|
||||
//} else {
|
||||
// log.Fatalf("[!] Unknown error: %x\n", hr)
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
func printRawData(ptr uintptr, size uintptr) {
|
||||
fmt.Printf("Printing ptr %016x size %d\n", ptr, size)
|
||||
i := ptr
|
||||
var offset uintptr
|
||||
for i < ptr+size {
|
||||
if offset%16 == 0 {
|
||||
fmt.Printf("%016x : ", i)
|
||||
}
|
||||
|
||||
fmt.Printf("%02x", *(*byte)(unsafe.Pointer(i)))
|
||||
|
||||
i++
|
||||
offset++
|
||||
if offset%16 == 0 || offset == size {
|
||||
fmt.Print("\n")
|
||||
} else if offset%8 == 0 {
|
||||
fmt.Print(" ")
|
||||
} else {
|
||||
fmt.Print(" ")
|
||||
}
|
||||
}
|
||||
}
|
||||
package clr
|
||||
+9
-6
@@ -1,9 +1,12 @@
|
||||
package main
|
||||
// +build windows
|
||||
|
||||
package clr
|
||||
|
||||
import (
|
||||
"github.com/Microsoft/go-winio/pkg/guid"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Microsoft/go-winio/pkg/guid"
|
||||
)
|
||||
|
||||
// from mscorlib.tlh
|
||||
@@ -56,7 +59,7 @@ type MethodInfoVtbl struct {
|
||||
GetBaseDefinition uintptr
|
||||
}
|
||||
|
||||
func newMethodInfo(ppv uintptr) *MethodInfo {
|
||||
func NewMethodInfo(ppv uintptr) *MethodInfo {
|
||||
return (*MethodInfo)(unsafe.Pointer(ppv))
|
||||
}
|
||||
|
||||
@@ -100,16 +103,16 @@ func (obj *MethodInfo) GetType(pRetVal *uintptr) uintptr {
|
||||
return ret
|
||||
}
|
||||
|
||||
func (obj *MethodInfo) Invoke_3(variantObj, parameters uintptr, pRetVal *uintptr) uintptr {
|
||||
func (obj *MethodInfo) Invoke_3(variantObj Variant, parameters uintptr, pRetVal *uintptr) uintptr {
|
||||
ret, _, _ := syscall.Syscall6(
|
||||
obj.vtbl.Invoke_3,
|
||||
4,
|
||||
uintptr(unsafe.Pointer(obj)),
|
||||
uintptr(unsafe.Pointer(variantObj)),
|
||||
uintptr(unsafe.Pointer(&variantObj)),
|
||||
0,
|
||||
uintptr(unsafe.Pointer(pRetVal)),
|
||||
0,
|
||||
0,
|
||||
)
|
||||
)
|
||||
return ret
|
||||
}
|
||||
|
||||
+6
-7
@@ -1,7 +1,10 @@
|
||||
package main
|
||||
// +build windows
|
||||
|
||||
package clr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
@@ -15,8 +18,6 @@ import (
|
||||
|
||||
// from OAld.h
|
||||
|
||||
|
||||
|
||||
type SafeArray struct {
|
||||
cDims uint16
|
||||
fFeatures uint16
|
||||
@@ -31,7 +32,7 @@ type SafeArrayBound struct {
|
||||
lLbound int32
|
||||
}
|
||||
|
||||
func createSafeArray(rawBytes []byte) (SafeArray, error) {
|
||||
func CreateSafeArray(rawBytes []byte) (SafeArray, error) {
|
||||
modOleAuto, err := syscall.LoadDLL("OleAut32.dll")
|
||||
if err != nil {
|
||||
return SafeArray{}, err
|
||||
@@ -57,6 +58,7 @@ func createSafeArray(rawBytes []byte) (SafeArray, error) {
|
||||
}
|
||||
|
||||
sa := (*SafeArray)(unsafe.Pointer(ret))
|
||||
runtime.KeepAlive(sa)
|
||||
// now we need to use RtlCopyMemory to copy our bytes to the SafeArray
|
||||
modNtDll, err := syscall.LoadDLL("ntdll.dll")
|
||||
if err != nil {
|
||||
@@ -75,9 +77,6 @@ func createSafeArray(rawBytes []byte) (SafeArray, error) {
|
||||
return SafeArray{}, err
|
||||
}
|
||||
|
||||
//printRawData(uintptr(unsafe.Pointer(&sa)), uintptr(32))
|
||||
|
||||
return *sa, nil
|
||||
//return uintptr(unsafe.Pointer(&sa)), nil
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// +build windows
|
||||
|
||||
package clr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
||||
const S_OK = 0x0
|
||||
|
||||
func checkOK(hr uintptr, caller string) error {
|
||||
if hr != S_OK {
|
||||
return fmt.Errorf("%s returned 0x%08x", caller, hr)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func must(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
+5
-3
@@ -1,4 +1,6 @@
|
||||
package main
|
||||
// +build windows
|
||||
|
||||
package clr
|
||||
|
||||
import "unsafe"
|
||||
|
||||
@@ -9,10 +11,10 @@ type Variant struct {
|
||||
wReserved1 uint16
|
||||
wReserved2 uint16
|
||||
wReserved3 uint16
|
||||
Val int64
|
||||
Val uintptr
|
||||
_ [8]byte
|
||||
}
|
||||
|
||||
func newVariant(ppv uintptr) *Variant {
|
||||
func variantFromPtr(ppv uintptr) *Variant {
|
||||
return (*Variant)(unsafe.Pointer(ppv))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user