Building a dll with Go
Installation¶
MingGW¶
https://sourceforge.net/projects/mingw-w64/files/mingw-w64/mingw-w64-release/
Making DLLs¶
- 导入
C
模块 -
导出函数需要
//export
标记,注意//
与export
之间没有空格://export FuncName
-
需要
main
函数,可为空
package main
import "C"
import (
"fmt"
)
//export HelloWorld
func HelloWorld() {
fmt.Println("Hello World!")
}
func main() {}
Compiling the DLL¶
go -o dllmain.dll -buildmode=c-shared dllmain.go
go build -ldflags="-s -w" -buildmode=c-shared -o dllmain.dll -trimpath dllmain.go
To load and Execute a DLL¶
导入.h
调用
package main
// #cgo LDFLAGS: -L. -ldllmain
// #include "dllmain.h"
import "C"
func main() {
C.HelloWorld()
}
Calling DLL¶
想要触发init()
,需要导出一个函数作为类似main()
的初始化触发点
package main
import (
"C"
"fmt"
)
func init() {
// evil code
}
//export EXPORTED_FUNCTION_NAME
func <DLL EXPORT FUNCTION>() {
// 必须要有触发点才能执行 init(),内容可以为空
// 当然也可以在导出函数中执行
}
func main() {}
syscall.SyscallN()
触发
package main
import (
"syscall"
"golang.org/x/sys/windows"
)
func main() {
handle, err := windows.LoadLibrary("<DLL NAME>")
if err != nil {
panic(err)
}
proc, err := windows.GetProcAddress(handle, "<DLL EXPORT FUNCTION>")
if err != nil {
panic(err)
}
syscall.SyscallN(uintptr(proc))
}
LoadDLL()
触发
package main
import (
"golang.org/x/sys/windows"
)
func main() {
handle, err := windows.LoadDLL("<DLL NAME>")
if err != nil {
panic(err)
}
proc, err := handle.FindProc("<DLL EXPORT FUNCTION>")
if err != nil {
panic(err)
}
proc.Call()
}