深耕解释型语言:攻击性Python攻防技术
作者:Kevin Clark
红队对抗模拟 · 恶意代码分析
https://trustedsec.com/blog/operating-inside-the-interpreted-offensive-python
一、引言
我时常会回头复盘那些早年盛行、如今在攻击圈渐渐失宠的技术手段。Office宏、PowerShell、自定义ShellCode加载器这类技术曾经无往不利,但如今不少行业同行都称它们已经“失效暴露”。
这话虽有一定道理,但在实际渗透作业中,我和团队多次发现,这些所谓“被标记”的战术、技术与流程(TTP)依然能发挥奇效,时常带来意料之外的突破。
本文将重点介绍另一套老牌攻击手段:Windows平台下基于Python构建恶意载荷。开篇先梳理该领域过往相关研究成果。
二、Python恶意程序
黑客使用Python编写恶意代码由来已久,从Python反弹Shell,到Py2Exe打包简易植入程序,层出不穷。我最早接触的Python攻击工具是Chris Truncer开发的Veil Evasion项目,该工具2013年首次发布,能将Python代码转化为可执行Shell载荷,在当年堪称“黑科技”。
此后不久,微软宣布PowerShell预装于全系列Windows系统,开启了PowerShell攻击工具的黄金时代:PowerSploit初代工具集及大量衍生攻击脚本陆续问世,依托系统自带的PowerShell环境即可直接执行。
相较之下Python恶意程序逐渐边缘化——目标主机必须预先安装Python解释器才能运行相关代码。
但好景不长,微软对PowerShell做出大幅整改:引入反恶意软件扫描接口(AMSI)、完善各类行为日志记录机制,大幅提升了PowerShell恶意代码的开发与免杀门槛。最终攻击工具开发者纷纷放弃PowerShell,重新转向C、C++这类非托管原生语言。
2018年末,微软在微软商店(原Windows商店)上架Python程序。我时隔数年才意识到这套安装流程极其简便,相信很多安全从业者此前也并未留意。
2022年,Diego Capriotti推出纯Python编写的漏洞利用框架Pyramid,在我看来,这标志着现代Python攻击工具正式成型。同期Anthony Rose发布了嵌入.NET环境的Python3引擎实现方案,灵感源自图拉(Turla)组织的IronNetInjector恶意代码。依托该方案,无需在目标主机安装Python解释器,就能直接在Windows上运行Python代码。
如今Windows系统获取Python的渠道十分便捷,配套攻击工具生态也逐步完善。在恶意代码开发领域,Python已经形成一块独特且实用的攻击细分赛道。
三、从微软应用商店安装Python
前文提到,通过微软商店可以一键安装Python。现代Windows系统只需打开微软商店,搜索“Python”即可,商店内提供3.7至3.13全系列版本。点击“获取”按钮就能下载,全程无需管理员权限。
除此之外,微软商店提供专属协议跳转链接,已知对应程序ID即可直接拉起安装页面。以Python3.13为例,跳转地址:ms-windows-store://pdp/?ProductId=9pnrbtzxmb4z
安装完成后,可通过开始菜单启动Python,也能直接运行路径下的引导程序:C:\Users\[用户名]\AppData\Local\Microsoft\WindowsApps\
四、Python离线下载与安装
部分场景无法通过微软商店在线安装Python,典型情况包括:
- 仅能使用命令行,无图形界面操作权限
- 组策略或系统管控禁用微软商店
- 目标主机无外网访问能力
即便存在上述限制,依然可以离线部署微软商店类应用(含Python),完整步骤如下:
步骤1:浏览器打开Python商店详情页
步骤2:提取离线安装包
复制商店页面URL,粘贴至第三方站点 https://store.rg-adguard.net/,下载MSIX/APPX/APPXBundle格式离线安装包。
补充说明:该第三方站点可信度存疑,但下载的安装包带有官方数字签名,文件不会被篡改。建议先在实验环境测试安装包,确认无异常后再部署至目标主机。
步骤3:将安装包传输至目标主机
-
有图形界面:双击MSIX文件,系统自动调用
AppInstaller.exe启动安装向导 -
无图形界面:使用PowerShell
Add-AppxPackage命令或dism.exe完成安装/卸载
注意:dism.exe执行需要管理员权限,而单纯安装商店应用本身不需要提权。
我编写过一段Python脚本,无需完成安装即可预判商店应用主程序的存放路径,可用于提前定位Python可执行文件。
Python3.13默认完整路径示例:C:\Users\kevinclark\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\python3.13.exe
通用路径模板:C:\Users\[用户名]\AppData\Local\Microsoft\WindowsApps\[厂商名].[应用名]_[发布者哈希值]\[主程序].exe
其中发布者哈希值由开发者证书生成,主程序名称定义于安装包内AppxManifest.xml清单文件。少数程序会偏离该路径规则,但绝大多数商店应用均可套用此模板预判位置。
五、Pip包管理器
微软商店版Python自带Pip包管理工具,直接执行Python.exe -m pip即可调用。若主机可连通PyPI官方仓库,能正常在线下载安装第三方库。
但多数企业内网会拦截PyPI站点,或部署网络代理导致在线下载失败,极大限制Python攻击工具使用。应对方案分为两类:
- 仅使用Python标准库开发攻击工具,不依赖第三方组件
- 离线下载全部依赖库文件,上传至目标主机本地安装
离线部署流程可行,我编写了两套配套脚本:一套仅依赖标准库的离线依赖下载器、一套离线本地安装程序。
- 下载脚本:拉取目标工具所有依赖的Wheel离线包,自动打包为单一压缩文件,可上传内网主机或托管至私有Web服务
- 安装脚本:读取离线压缩包,批量完成所有Wheel包本地安装
六、Python标准库
即便可以离线导入第三方库,开发攻击性代码时仍应优先复用标准库,降低载荷体积与落地复杂度。例如网络请求场景,优先使用内置urllib,而非第三方requests库。
下表整理攻击开发高频需求,以及对应的内置标准库模块:
| 实现功能 | 标准库模块 |
|---|---|
| 网页网络请求 | urllib |
| TCP套接字通信 | socket |
| SHA256哈希计算 | hashlib |
| 文件压缩/解压缩 | gzip、bz2、zlib、zipfile |
| 加载DLL、调用原生非托管函数 | ctypes |
| 创建子进程、执行系统命令 | subprocess |
| 结构化数据解析 | json、xml |
| Windows注册表读写修改 | winreg |
| 二进制编解码 | base64 |
| IP地址处理 | ipaddress |
但标准库无法覆盖全部攻击需求,部分核心能力必须借助第三方库或自主实现:
| 实现功能 | 所需第三方库 |
|---|---|
| AES加密解密 | pycryptodome |
| WebSocket长连接 | aiohttp |
| 加载.NET公共语言运行时、交互托管代码 | pythonnet |
| 网卡抓包流量分析 | libpcap |
| LDAP目录服务交互 | ldap3 |
| Windows协议漏洞利用 | impacket |
Windows版Python预装标准库完整清单可查阅文末附链。
七、基于ctypes执行非托管代码
ctypes是我最常用的Python内置模块,搭配struct库后,能够用Python实现类C语言开发逻辑:加载非托管动态链接库、获取导出函数、手动内存管理、指针操作。如果熟悉C#的PInvoke机制,ctypes可以理解为Python版PInvoke。
通过ctypes调用Win32 Windows API固定分为6步:
- 加载包含目标函数的DLL文件
- 获取目标导出函数句柄
- 定义函数原型:参数类型、返回值类型
- 将Python数据类型转换适配C语言类型(数据封送)
- 调用原生API函数
- (可选)将原生返回值转回Python类型供后续代码使用
DLL加载语法
# 加载系统内置kernel32.dll
kernel32 = ctypes.windll.kernel32
kernel32_2 = ctypes.WinDLL("kernel32")
# 加载自定义路径第三方DLL
custom_dll = ctypes.CDLL(r"C:\test\custom.dll")
获取导出函数句柄
推荐通过函数名获取;按导出序号读取不推荐,不同Windows版本序号会发生变动:
# 通过函数名获取CreateFileW
CreateFileW = kernel32.CreateFileW
# 通过导出序号212读取(不推荐)
CreateFileW_ord = kernel32[212]
定义函数原型
导入wintypes模块,内置全套Windows标准数据类型;通过argtypes声明参数列表,restype定义返回值类型。以文件创建API CreateFileW为例:
from ctypes import wintypes
# 匹配MSDN官方文档参数结构
CreateFileW.argtypes = [
wintypes.LPCWSTR, # 文件路径
wintypes.DWORD, # 访问权限
wintypes.DWORD, # 共享模式
wintypes.LPVOID, # 安全属性(可选)
wintypes.DWORD, # 文件创建方式
wintypes.DWORD, # 文件属性标识
wintypes.HANDLE # 模板文件句柄(可选)
]
CreateFileW.restype = wintypes.HANDLE
封装参数并调用API
ctypes会自动完成Python字符串、空值到C语言对应类型的转换:
# 常量定义
filename = "test.txt"
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
CREATE_ALWAYS = 2
FILE_ATTRIBUTE_NORMAL = 0x80
# 调用API创建文件
handle = CreateFileW(
filename,
GENERIC_READ | GENERIC_WRITE,
0,
None,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
None
)
执行完成后,当前目录会生成test.txt文件,整套流程仅依靠Python内置ctypes模块完成原生系统调用。
八、ctypes实操示例
示例1:弹窗展示当前进程名与PID
完整可运行代码:
import ctypes
from ctypes import c_char_p, c_uint32, c_void_p, create_string_buffer
import os.path
# Windows弹窗常量
MAX_PATH = 260
MB_OK = 0x00000000
MB_ICONINFORMATION = 0x00000040
# 加载系统DLL
kernel32 = ctypes.windll.kernel32
user32 = ctypes.windll.user32
# 定义API原型
GetCurrentProcessId = kernel32.GetCurrentProcessId
GetCurrentProcessId.restype = c_uint32
GetCurrentProcessId.argtypes = []
GetModuleFileNameA = kernel32.GetModuleFileNameA
GetModuleFileNameA.restype = c_uint32
GetModuleFileNameA.argtypes = [c_void_p, ctypes.c_char_p, c_uint32]
MessageBoxA = user32.MessageBoxA
MessageBoxA.restype = ctypes.c_int32
MessageBoxA.argtypes = [c_void_p, c_char_p, c_char_p, c_uint32]
# 获取进程PID
process_id = GetCurrentProcessId()
# 获取程序完整路径
buffer = create_string_buffer(MAX_PATH)
path_length = GetModuleFileNameA(None, buffer, MAX_PATH)
if path_length == 0:
raise Exception("读取模块路径失败")
# 截取程序文件名
full_path = buffer.value.decode('ascii')
process_name = os.path.basename(full_path)
# 弹窗内容
message = f"进程名称:{process_name}\n进程PID:{process_id}"
# 弹出系统提示框
MessageBoxA(
None,
message.encode('ascii'),
b"进程信息",
MB_OK | MB_ICONINFORMATION
)
示例2:反射DLL加载器
我还编写了一套简易反射DLL加载器代码,属于红队攻击核心技术落地演示。该样例无法直接用于实战渗透,但清晰展示了攻击者常用载荷注入逻辑:
- 内存反射加载DLL文件
- 主动调用DllMain入口函数
- 查找并执行DLL内自定义导出Run函数
九、Python相关入侵指标(IoC)
Python是企业内网广泛使用的合法程序,python.exe带有微软与Python软件基金会双重有效数字签名,可信度高;大量工作站、服务器预装Python,攻击者无需额外安装即可直接利用。
和所有解释型语言一致,Python运行时会产生特殊内存特征:Windows官方CPython在执行任意代码前,就会创建无文件映射的可执行内存段、RWX(读写执行)权限内存页。
但Python本身是通用编程语言,业务场景覆盖数据分析、系统运维、游戏开发、云编排等,行为边界极广:
- python.exe联网访问外部网站是否正常?
- 与内网其他主机建立Socket连接是否合理?
- 申请、修改高权限内存页是否属于常规操作?
- 占用大量CPU/内存资源是否存在风险?
以上问题均没有固定答案,只能结合业务场景判断。多重模糊特征叠加,极大提升终端安全产品基线建模难度,方便攻击者以Python进程为掩护,实现行为隐匿驻留。
十、总结
Python作为恶意载荷载体的潜力长期被低估:安装部署门槛低、内置工具库完善、进程行为天然具备隐蔽优势。
它不会完全替代原生C/C++攻击方案,但在PowerShell、传统原生注入等手段失效受限的场景下,是一套便捷、可行的替代攻击方案。
更多推荐


所有评论(0)