skelsec/awinrm
GitHub: skelsec/awinrm
纯 Python 异步 WinRM 客户端,支持多种认证方式和交互式远程管理 Windows 主机
Stars: 19 | Forks: 1
# awinrm
**用于 Windows 远程管理 (WinRM) 的异步 Python 库**
[](https://www.python.org/downloads/)
[](https://opensource.org/licenses/MIT)
`awinrm` 是一个完全异步的 Python Windows 远程管理 (WinRM) 客户端。它允许你在远程 Windows 机器上执行命令、运行 PowerShell 脚本、传输文件以及维护交互式 Shell 会话。
## ✨ 功能特性
- **完全异步** - 基于 `asyncio` 和 `httpx` 构建,实现非阻塞 I/O
- **纯 Python 认证** - NTLM、Kerberos、SPNEGO 和 CredSSP 均通过 `asyauth` 和 `minikerberos` 以纯 Python 实现(无需 `krb5` 或 `sspi` 等系统依赖!)
- **交互式 Shell** - 创建支持 keepalive 的持久化 CMD 或 PowerShell 会话
- **文件传输** - 通过 base64 编码的 PowerShell 命令上传和下载文件
- **消息加密** - 自动进行 GSSAPI 消息加密,确保通过 HTTP 通信的安全性
- **优雅终止** - 干净地处理 Shell 退出和会话超时
## 📦 安装
```
pip install awinrm
```
### 依赖项
所有依赖项均为纯 Python:
- `httpx` - 异步 HTTP 客户端
- `asyauth` - NTLM、Kerberos、SPNEGO、CredSSP 的纯 Python 实现
- `unicrypto` - 密码学原语
- `aioconsole` - 用于交互式 Shell 的异步控制台输入
## 🔗 URL 格式
`awinrm` 使用基于 URL 的凭据规范(来自 `asyauth`)。格式如下:
```
+-://:@:/?
```
### 组成部分
| Component | Description | Examples |
|-----------|-------------|----------|
| `transport` | HTTP 或 HTTPS | `http`, `https` |
| `auth_type` | 认证协议 | `ntlm`, `kerberos`, `spnego` |
| `auth_method` | 凭据类型 | `password`, `nt`, `aes`, `ccache` |
| `username` | 用户名(可选域名) | `user`, `DOMAIN\user`, `user@domain.com` |
| `password` | 密码或哈希 | 明文密码或 NT 哈希 |
| `host` | 目标主机名或 IP | `192.168.1.100`, `server.domain.com` |
| `port` | WinRM 端口(可选) | `5985` (HTTP), `5986` (HTTPS) |
| `options` | 查询参数 | `dc=`, `proxytype=`, 等 |
### URL 示例
```
# 带密码的 NTLM(本地账户)
"http+ntlm-password://administrator:Password123@192.168.1.100"
# 带密码的 NTLM(域账户)
"http+ntlm-password://MYDOMAIN\\admin:Password123@server.mydomain.com"
# 带密码的 Kerberos
"http+kerberos-password://NORTH\\vagrant:vagrant@winterfell.north.sevenkingdoms.local/?dc=192.168.56.11"
# 带 ccache 的 Kerberos(票据缓存)
"http+kerberos-ccache://winterfell.north.sevenkingdoms.local/?ccache=/tmp/krb5cc_1000"
# 带 NT hash 的 NTLM(pass-the-hash)
"http+ntlm-nt://administrator:aad3b435b51404eeaad3b435b51404ee@192.168.1.100"
# 带 NTLM 的 HTTPS
"https+ntlm-password://admin:secret@secure-server.domain.com:5986"
```
### 查询参数
| Parameter | Description |
|-----------|-------------|
| `dc=` | 域控制器 IP (用于 Kerberos) |
| `ccache=` | Kerberos 凭据缓存路径 |
| `proxytype=` | 代理类型 (`socks5`, `http`) |
| `proxyhost=` | 代理主机名 |
| `proxyport=` | 代理端口 |
## 📖 API 用法
### 基本命令执行
```
import asyncio
from awinrm import Session
async def main():
url = "http+ntlm-password://administrator:Password123@192.168.1.100"
async with Session(url) as session:
# Run a command
stdout, stderr, return_code = await session.run_cmd('ipconfig', ('/all',))
print(stdout.decode())
# Run PowerShell
stdout, stderr, return_code = await session.run_ps('Get-Process | Select-Object -First 5')
print(stdout.decode())
asyncio.run(main())
```
### 交互式 Shell
```
import asyncio
from awinrm import Session, ShellTerminatedError
async def main():
url = "http+ntlm-password://administrator:Password123@192.168.1.100"
async with Session(url) as session:
# Create a CMD shell
async with session.create_shell(shell_type='cmd') as shell:
# Send commands
await shell.send_input(b'whoami\r\n')
# Read output
stdout = await shell.stdout.get()
print(stdout.decode())
# Check if shell is still running
if not shell.is_terminated:
await shell.send_input(b'exit\r\n')
asyncio.run(main())
```
### PowerShell Shell
```
async with Session(url) as session:
# Create a PowerShell shell (recommended for most use cases)
async with session.create_shell(shell_type='powershell') as shell:
await shell.send_input(b'$PSVersionTable\r\n')
stdout = await shell.stdout.get()
print(stdout.decode())
```
### 文件传输
```
async with Session(url) as session:
# Upload a file
await session.upload_file(
local_path='/tmp/script.ps1',
remote_path='C:\\temp\\script.ps1',
progress_callback=lambda sent, total: print(f'{sent}/{total} bytes')
)
# Download a file
await session.download_file(
remote_path='C:\\Windows\\System32\\drivers\\etc\\hosts',
local_path='/tmp/hosts'
)
# Check if file exists
exists = await session.file_exists('C:\\temp\\script.ps1')
# Get file size
size = await session.get_file_size('C:\\temp\\script.ps1')
```
### 认证类型
```
# SPNEGO(自动协商 NTLM 或 Kerberos)
async with Session(url, authtype='spnego') as session:
...
# CredSSP(允许凭据委派 / 双跳)
async with Session(url, authtype='credssp') as session:
...
```
### Shell 配置
```
async with Session(url) as session:
shell = session.create_shell(
shell_type='powershell', # 'cmd', 'powershell', or 'pwsh'
working_directory='C:\\temp',
env_vars={'MY_VAR': 'value'},
codepage=65001, # UTF-8
keepalive_interval=60, # Seconds between keepalive pings
idle_timeout=300, # Server-side idle timeout
)
async with shell:
...
```
### 自定义 HTTP 传输
用于高级用例(代理、自定义 SSL 等):
```
import httpx
transport = httpx.AsyncHTTPTransport(
verify=False,
http2=True,
)
async with Session(url, transport=transport, verify=False) as session:
...
```
### 异常处理
```
from awinrm import (
Session,
ShellTerminatedError,
ShellNotFoundError,
WinRMError,
WinRMTransportError,
AuthenticationError,
)
async with Session(url) as session:
async with session.create_shell() as shell:
try:
await shell.send_input(b'exit\r\n')
await shell.read_output()
except ShellTerminatedError as e:
print(f"Shell exited with code: {e.exit_code}")
except ShellNotFoundError:
print("Shell was closed by the server")
except AuthenticationError:
print("Authentication failed")
except WinRMTransportError as e:
print(f"HTTP error: {e.code}")
```
## 🛠️ 命令行工具
### awinrm-runcmd
在远程主机上执行单个命令:
```
# 基本用法
awinrm-runcmd 'http+ntlm-password://admin:pass@192.168.1.100' 'ipconfig /all'
# 带详细输出
awinrm-runcmd -v 'http+ntlm-password://admin:pass@192.168.1.100' 'whoami'
# 使用 CredSSP
awinrm-runcmd -a credssp 'http+ntlm-password://admin:pass@192.168.1.100' 'hostname'
```
### awinrm-cmdshell
交互式远程 Shell:
```
# CMD shell
awinrm-cmdshell -s cmd 'http+ntlm-password://admin:pass@192.168.1.100'
# PowerShell shell(默认)
awinrm-cmdshell 'http+ntlm-password://admin:pass@192.168.1.100'
# PowerShell Core
awinrm-cmdshell -s pwsh 'http+ntlm-password://admin:pass@192.168.1.100'
# 带详细日志
awinrm-cmdshell -v 'http+kerberos-password://DOMAIN\\user:pass@server/?dc=dc.domain.com'
```
### awinrm-authcheck
测试认证而无需执行命令:
```
# 测试 NTLM
awinrm-authcheck 'http+ntlm-password://admin:pass@192.168.1.100'
# 测试 Kerberos
awinrm-authcheck 'http+kerberos-password://DOMAIN\\user:pass@server/?dc=dc.domain.com'
# 详细模式
awinrm-authcheck -v 'http+ntlm-password://admin:pass@192.168.1.100'
```
## ⚙️ WinRM 服务器配置
### 启用 WinRM(在 Windows 目标机上)
```
# 快速设置(HTTP + NTLM)
winrm quickconfig -q
# 启用 CredSSP(用于凭据委派)
Enable-WSManCredSSP -Role Server -Force
# 检查当前配置
winrm get winrm/config
```
### 防火墙
WinRM 使用:
- **端口 5985** 用于 HTTP
- **端口 5986** 用于 HTTPS
```
# 允许 WinRM 通过防火墙
New-NetFirewallRule -Name "WinRM-HTTP" -DisplayName "WinRM (HTTP)" -Enabled True -Direction Inbound -Protocol TCP -LocalPort 5985 -Action Allow
```
## 🔐 安全说明
1. **在生产环境中使用 HTTPS** - HTTP 会以可恢复的格式传输凭据
2. **优先使用 Kerberos** - 比 NTLM 更安全,支持委派
3. **消息加密是自动的** - 即使通过 HTTP,NTLM/Kerberos 也会加密消息负载
4. **CredSSP 允许委派** - 当你需要从远程主机访问网络资源时使用
## 📚 API 参考
### Session
| Method | Description |
|--------|-------------|
| `run_cmd(command, args)` | 执行命令,返回 (stdout, stderr, rc) |
| `run_ps(script)` | 执行 PowerShell 脚本 |
| `create_shell(shell_type, ...)` | 创建交互式 Shell |
| `create_powershell(...)` | PowerShell Shell 的便捷方法 |
| `upload_file(local, remote, callback)` | 上传文件到远程 |
| `download_file(remote, local, callback)` | 从远程下载文件 |
| `file_exists(path)` | 检查远程文件是否存在 |
| `get_file_size(path)` | 获取远程文件大小 |
### WinRMShell
| Property/Method | Description |
|-----------------|-------------|
| `is_terminated` | 如果 Shell 已退出则为 True |
| `return_code` | 退出代码(如果已终止) |
| `send_input(data)` | 发送字节到 Shell stdin |
| `read_output()` | 读取可用的 stdout/stderr |
| `wait_for_termination()` | 阻塞直到 Shell 退出 |
| `close()` | 关闭 Shell |
### 异常
| Exception | Description |
|-----------|-------------|
| `WinRMError` | 所有 WinRM 错误的基类异常 |
| `WinRMTransportError` | HTTP 层级错误 (4xx, 5xx) |
| `ShellTerminatedError` | Shell 已退出(包含 exit_code) |
| `ShellNotFoundError` | Shell 在服务器上不再存在 |
| `AuthenticationError` | 认证失败 (401) |
| `WinRMOperationTimeoutError` | 操作超时(可重试) |
## 📄 许可证
MIT License - 详情见 [LICENSE](LICENSE)。
标签:Asyncio, Awesome, CredSSP, CTF学习, DNS枚举, GSSAPI加密, Httpx, IPv6, Kerberos认证, NTLM认证, OpenCanary, PE 加载器, PowerShell, Python, SPNEGO, Windows远程管理, WinRM, 交互式Shell, 内网渗透, 异步编程, 文件传输, 无后门, 横向移动, 系统管理, 纯Python实现, 编程规范, 网络信息收集, 网络安全工具, 自动化运维, 计算机取证, 运行时操纵, 远程命令执行, 远程控制, 逆向工具