前言

要 cs 内存加载 golang 程序,需要将 golang 程序编译成 dll 供 c# 调用,将 c# 编译并在 cs 中通过 execute-assembly 执行。

Demo1

启动 Golang 程序并将其加载到内存中

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System;
using System.Diagnostics;
using System.IO;

namespace MemoryLoadGo
{
    class Program
    {
        static void Main(string[] args)
        {
            Process process = new Process();
            process.StartInfo.FileName = "C:\\Workspace\\goland\\csharp\\hello.exe";
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardError = true;
            process.Start();

            Console.WriteLine(process.StandardOutput.ReadToEnd());

            process.WaitForExit();
        }
    }
}

Demo2

golang 导出 dll 并通过 c# 调用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package main

import "C"
import "fmt"

//export Test
func Test() {
    fmt.Println("Hello from Go!")
}

func main() {
    // 这里可以添加其他逻辑
}
1
2
3
4
5
6
7
8
# mac
CGO_ENABLED=1 GOOS=windows GOARCH=amd64 CC=/opt/homebrew/Cellar/mingw-w64/11.0.0/bin/i686-w64-mingw32-gcc go build -ldflags "-s -w" --buildmode=c-shared -o Test.dll test.go
CGO_ENABLED=1 GOOS=windows GOARCH=amd64 CC=/opt/homebrew/Cellar/mingw-w64/11.0.0/bin/x86_64-w64-mingw32-gcc go build -ldflags "-s -w" --buildmode=c-shared -o Test.dll test.go
# windows
set CGO_ENABLED=1
set CC=C:/TDM-GCC-64/bin/x86_64-w64-mingw32-gcc.exe
set CC=C:/TDM-GCC-64/bin/gcc.exe
go build -ldflags "-s -w" --buildmode=c-shared -o Test.dll test.go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
using System;
using System.Runtime.InteropServices;

class Program
{
    // 导入 Go 中的 Test 函数
    [DllImport("test.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern void Test();

    static void Main(string[] args)
    {
        // 调用 Go 中的 Test 函数
        Test();
    }
}

image-20230625114809128

image-20230625124427453

Demo3

实现不落地的几种方式。

  • 通过 http 不落地加载 dll

    • 通过 Assembly.Load() 不落地加载,似乎只能加载 .NET 程序集

      image-20230625162530705

    • 使用 IJW 不落地加载,似乎只能加载 .NET 程序集

      image-20230625162441988

  • 直接将 dll 资源嵌入 c# 程序(不过 360 动态查杀),另外 cs 的 execute-assembly 只支持加载 1M 一下的文件,所以也不可行

    image-20230713143420766

Demo4

调用 DInvoke 这个项目内存加载 PE 文件(本地解密读取和远程不落地加载)

image-20230626174327547

结束。

参考

https://cloud.tencent.com/developer/article/2159961

https://github.com/TheWover/DInvoke

https://medium.com/@shantanukhande/red-team-how-to-embed-golang-tools-in-c-e269bf33876a