Python DPAPI NG 解密库
项目描述
dpapi_ng - Python DPAPI-NG 解/加密库
DPAPI NG 库,也称为 CNG DPAPI,是 Python 中的解密和加密库。它旨在模拟 NCryptUnprotectSecret 和 NCryptProtectSecret 的行为。它可以在非 Windows 主机上用于解密/加密 DPAPI NG 受保护的秘密,例如 PFX 用户受保护的密码或 LAPS 加密的密码。它可以使用域根密钥的离线副本解密任何 DPAPI NG blob,或者使用提供的用户的凭据通过 RPC 获取所需信息进行解密/加密。
目前仅支持以下保护描述符
类型 | 用途 |
---|---|
SID | 只有 SID 用户或 SID 组的成员可以解密秘密 |
此实现遵循 MS-GKDI 组密钥分发协议。
要求
- CPython 3.7+
- cryptography
- dnspython >= 2.0.0
- pyspnego >= 0.9.0
如何安装
要安装具有所有基本功能的 dpapi-ng,请运行
python -m pip install dpapi-ng
Kerberos 身份验证
Kerberos 身份验证支持默认情况下不会安装,因为它依赖于系统库和有效的编译器。可以通过安装以下包来安装 krb5 库和编译器
# Debian/Ubuntu
apt-get install gcc python3-dev libkrb5-dev
# Centos/RHEL
yum install gcc python-devel krb5-devel
# Fedora
dnf install gcc python-devel krb5-devel
# Arch Linux
pacman -S gcc krb5
安装完成后,可以使用以下命令安装 Kerberos Python 扩展
python -m pip install dpapi-ng[kerberos]
Kerberos 还需要配置以与域通信,但这超出了本页的范围。
从源代码安装
git clone https://github.com/jborean93/dpapi-ng.git
cd dpapi-ng
pip install -e .
示例
提供了同步和 asyncio API 以解密/加密 blob。
import dpapi_ng
### DECRYPTION ###
dpapi_ng_blob = b"..."
decrypted_blob = dpapi_ng.ncrypt_unprotect_secret(dpapi_ng_blob)
# async equivalent to the above
decrypted_blob = await dpapi_ng.async_ncrypt_unprotect_secret(dpapi_ng_blob)
### ENCRYPTION ###
data = b"..."
target_sid = "S-1-5-21-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-XXXX"
dpapi_ng_blob = dpapi_ng.ncrypt_protect_secret(data, target_sid)
# async equivalent to the above
dpapi_ng_blob = await dpapi_ng.async_ncrypt_protect_secret(data, target_sid)
要解密 blob,需要从生成 blob 的域控制器检索 blob 中指定的密钥。要加密 blob,需要检索目标 SID 的组密钥。对于解密,将自动通过 DNS SRV
查找 _ldap._tcp.dc._msdcs.{domain_name}
(其中域名称在 DPAPI-NG blob 中找到或在 server
关键字参数中指定)来检索域控制器的主机名。对于加密,域控制器的名称可以是使用 domain_name
关键字参数进行 DNS SRV
查找的,是直接使用 server
关键字参数,或者使用系统的搜索域(如果可用)。它将尝试使用当前用户标识符进行身份验证,在 Linux 上只有当 kinit
已经被调用以检索用户的票据时才会存在。如果没有可用的身份,则可以使用 username
和 password
关键字参数指定自定义用户。
以下关键字参数可用于 ncrypt_unprotect_secret
、async_ncrypt_unprotect_secret
、ncrypt_protect_secret
和 async_ncrypt_protect_secret
。
server
:如果需要检索密钥,请使用此服务器作为 RPC 目标username
:用于 RPC 连接的认证用户名password
:用于 RPC 连接的认证密码auth_protocol
:用于 RPC 连接的认证协议(negotiate
、kerberos
、ntlm
)cache
:用于存储检索到的密钥以供将来操作的缓存
此外,ncrypt_protect_secret
和 async_ncrypt_protect_secret
还需要以下附加关键字参数。
domain_name
:用于查找检索密钥信息时使用的 RPC 目标时的域/森林名称root_key_identifier
:根密钥标识符 UUID,对于使缓存对这些函数起作用是必需的
还可以通过提供存储在域中的根密钥来加密和解密 DPAPI-NG blob。这可以通过离线攻击或以域管理员用户身份运行时通过 LDAP 查询来实现。要使用 PowerShell 获取域根密钥,可以运行以下命令:
$configurationContext = (Get-ADRootDSE).configurationNamingContext
$getParams = @{
LDAPFilter = '(objectClass=msKds-ProvRootKey)'
SearchBase = "CN=Master Root Keys,CN=Group Key Distribution Service,CN=Services,$configurationContext"
SearchScope = 'OneLevel'
Properties = @(
'cn'
'msKds-KDFAlgorithmID'
'msKds-KDFParam'
'msKds-SecretAgreementAlgorithmID'
'msKds-SecretAgreementParam'
'msKds-PrivateKeyLength'
'msKds-PublicKeyLength'
'msKds-RootKeyData'
)
}
Get-ADObject @getParams | ForEach-Object {
[PSCustomObject]@{
Version = 1
RootKeyId = [Guid]::new($_.cn)
KdfAlgorithm = $_.'msKds-KDFAlgorithmID'
KdfParameters = [System.Convert]::ToBase64String($_.'msKds-KDFParam')
SecretAgreementAlgorithm = $_.'msKds-SecretAgreementAlgorithmID'
SecretAgreementParameters = [System.Convert]::ToBase64String($_.'msKds-SecretAgreementParam')
PrivateKeyLength = $_.'msKds-PrivateKeyLength'
PublicKeyLength = $_.'msKds-PublicKeyLength'
RootKeyData = [System.Convert]::ToBase64String($_.'msKds-RootKeyData')
}
}
以下 ldapsearch
命令可以在 Windows 外部使用
ldapsearch \
-b 'CN=Master Root Keys,CN=Group Key Distribution Service,CN=Services,CN=Configuration,DC=domain,DC=test' \
-s one \
'(objectClass=msKds-ProvRootKey)' \
cn \
msKds-KDFAlgorithmID \
msKds-KDFParam \
msKds-SecretAgreementAlgorithmID \
msKds-SecretAgreementParam \
msKds-PrivateKeyLength \
msKds-PublicKeyLength \
msKds-RootKeyData
注意:ldapsearch 可能需要 -H 和用户绑定信息才能成功。
检索到的信息可以存储在缓存中,并用于后续的 ncrypt_protect_secret
和 ncrypt_unprotect_secret
调用。
import uuid
import dpapi_ng
cache = dpapi_ng.KeyCache()
root_key_id = uuid.UUID("76ec8b2d-d444-4f67-9db7-2f62b4358b35")
cache.load_key(
b"...", # msKds-RootKeydata
root_key_id, # cn
version=1,
kdf_algorithm="SP800_108_CTR_HMAC", # msKds-KDFAlgorithmID
kdf_parameters=b"...", # msKds-KDFParam
secret_algorithm="DH", # mskds-SecretAgreementAlgorithmID
secret_parameters=b"...", # msKds-SecretAgreementParam
private_key_length=512, # msKds-PrivateKeyLength
public_key_length=2048, # msKds-PublicKeyLength
)
dpapi_ng.ncrypt_unprotect_secret(b"...", cache=cache)
目前,已测试以下 KDF 算法可以工作:SP800_108_CTR_HMAC
和秘密协商算法 DH
、ECDH_P256
、ECDH_P384
。秘密协商算法 ECDH_P521
也应该可以工作,但尚未测试,因为无法创建包含它的测试环境。
特别感谢
我想感谢以下人员(括号中为 GitHub 或 Twitter 处理)在本项目中的帮助:
- Georg Sieber (@schorschii) 为实现加密支持
- Grzegorz Tworek (@0gtweet) 和 Michał Grzegorzewski 为提供有关 DPAPI-NG 中使用的内部 BCrypt* API 工作流程的更多信息
- Marc-André Moreau (@awakecoding) 为其帮助逆向工程一些 Windows API 以及讨论一些理论
- SkelSec (@SkelSec) 为 RPC 调用的帮助,并作为我理论的通用试金石
- Steve Syfuhs (@SteveSyfuhs) 为将其与我联系的一些微软工程师联系起来,以帮助理解一些未记录的逻辑
没有他们的耐心和知识,这可能是无法实现的。
项目详情
下载文件
下载您平台上的文件。如果您不确定选择哪个,请了解更多关于 安装软件包 的信息。
源分布
构建分布
dpapi-ng-0.2.0.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | e6fca84a13586ca93901181af7c47644fc31f729de18f00b20cfd8dad4d48ef0 |
|
MD5 | 7e8228afe74ed0ab3dfb9e9fd3042547 |
|
BLAKE2b-256 | aca9246f56c03e45cf5d7fad81b66405dd01c2304c0d228b10b95cb4d3308592 |
dpapi_ng-0.2.0-py3-none-any.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 75572bab45ca280d0d836062f880c9d2f29b30e5d294d9158d35e98bde3ba38b |
|
MD5 | f62f35678b9d2a3e060d4dda29697257 |
|
BLAKE2b-256 | d09348b8f2e58cd6dece91afc4035c18f3f2fd0045bd16a751413ce73005178b |