0x00 前言
在之前的文章《渗透技巧——获得Windows系统的远程桌面连接历史记录》曾介绍了获得远程桌面连接历史记录的方法。
在实际的渗透过程中,如果发现了远程桌面连接的历史记录,那么下一步就需要想办法获取远程桌面连接使用的口令。
本文将会结合RdpThief介绍从远程桌面客户端提取明文凭据的方法,分享需要注意的细节。
RdpThief地址:
https://github.com/0x09AL/RdpThief
0x01 简介
本文将要介绍以下内容:
· 获取远程桌面连接口令的思路
· 使用Detours库hook系统API的方法
· 使用API monitor监控系统API调用的方法
· 使用RdpThief从远程桌面客户端提取明文凭据
0x02 获取远程桌面连接口令的思路
通常有以下两种:
1.使用键盘记录程序,记录mstsc.exe在启动过程中用户输入的口令。
2.在mstsc.exe启动时,读取mstsc.exe的内存数据,提取出用户输入的口令。
RdpThief是第二种实现思路,使用Detours库hook系统API,使用API monitor监控系统的API调用,找到mstsc.exe在内存中存储明文口令的位置,代码简洁有效。
0x03 使用Detours库hook系统API的方法
RdpThief在实现上使用Detours库来hook系统API,所以这里简要介绍一下Detours库的用法。
Detours库用于监视和检测Windows上的API调用,可以用来hook系统API。
这里介绍使用Detours库hook系统API的两种方法。
1.编译Detours源码并使用
(1)编译Detours源码
下载Detours源码,地址如下:
https://github.com/Microsoft/Detours
使用Visual Studio编译Detours源码(这里以VS2015为例),需要区分32位和64位。
64位编译:
打开VS2015 x64 本机工具命令提示符。
执行以下命令:
cd Detours-master\src nmake
命令执行后将在文件夹Detours-master下生成以下三个文件夹,包括Detours的头文件和库文件。
· bin.X64
· include
· lib.X64
32位编译:
打开VS2015本机工具命令提示符。
执行以下命令:
cd Detours-master\src nmake
命令执行后将在文件夹Detours-master下生成以下三个文件夹,包括Detours的头文件和库文件。
· bin.X86
· include
· lib.X86
(2)导入Detours
在新建的C++工程中添加对应版本的头文件:
· detours.h
· detours.lib
代码如下:
#include "detours.h" #pragma comment (lib,"detours.lib")
2.通过Install-Package自动安装
(1)安装
在Visual Studio中选择工具->NuGet包管理器->程序包管理器控制台。
输入安装命令:
Install-Package Detours
将会自动安装Detours库,如下图:
(2)导入Detours
代码如下:
#include <detours.h> #pragma comment (lib,"detours.lib")
使用Detours库hook系统API时常用的几个函数:
· DetourTransactionBegin();
· DetourUpdateThread(GetCurrentThread());
· DetourAttach();
· DetourDetach();
· DetourTransactionCommit()
Hook系统API Messagebox()的实例代码如下:
#include <Windows.h> #include <detours.h> #pragma comment (lib,"detours.lib") static int(WINAPI *TrueMessageBox)(HWND, LPCTSTR, LPCTSTR, UINT) = MessageBox; int WINAPI OurMessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) { return TrueMessageBox(NULL, L"Hooked", lpCaption, 0); } int main() { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourAttach(&(PVOID&)TrueMessageBox, OurMessageBox); DetourTransactionCommit(); MessageBox(NULL, L"Hello", L"Hello", 0); DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourDetach(&(PVOID&)TrueMessageBox, OurMessageBox); DetourTransactionCommit(); }
0x04 使用API monitor监控系统API调用的方法
RdpThief使用API monitor监控系统的API调用,找到mstsc.exe在内存中存储明文口令的位置,这里简要介绍一下API monitor的用法。
API monitor的下载地址:
http://www.rohitab.com/downloads
运行后需要选择进行监控的模块,如下图:
接着选择需要监控的进程,如下图:
API monitor将会监控进程运行时调用的API,如下图:
0x05 RdpThief测试
介绍RdpThief细节的文章:
RdpThief的代码里包括三部分内容:
1.C++工程,编译生成dll
编译生成的dll,需要注入到mstsc.exe进程中。
这里可以使用我之前写的dll注入的代码,地址如下:
https://github.com/3gstudent/Homework-of-C-Language/blob/master/NtCreateThreadEx %2B LdrLoadDll.cpp
但是需要把FreeDll()的功能去掉,dll需要一直在进程mstsc.exe的内存中,用来记录用户输入的口令。
2.RdpThief_x64.tmp
shellcode格式的dll,作者使用sRDI将编译好的dll转换为shellcode格式,便于cna脚本的调用。
3.RdpThief.cna
Colbalt Strike使用的cna脚本,用于注入shellcode格式的dll。
支持三个命令:
· rdpthief_enable,每5秒搜索mstsc.exe并将dll注入
· rdpthief_disable,停止rdpthief_enable,但不会卸载注入的dll
· rdpthief_dump,显示抓取的凭据,默认读取路径为%temp%\data.bin
实际测试
预期功能:
在mstsc.exe中输入用户名口令后,无论是否正确,都会被记录在文件%temp%\data.bin中。
1.在Win10下没有问题。
2.在Win7下能够获得输入的用户名和口令,但无法获得Server名称。
查找问题原因:
RdpThief在实现上通过捕获API SspiPrepareForCredRead()获得Server名称。
在Win7系统下,我使用API monitor监控系统调用的API,发现不存在这个API,如下图:
找到问题的原因
解决方法1:
通过搜索,发现API CredReadW() 能够记录Server名称,如下图:
所以可以尝试hook API CredReadW ,示例代码如下:
static BOOL(WINAPI *OriginalCredReadW)(LPCWSTR TargetName, DWORD Type, DWORD Flags, PCREDENTIALW *Credential) = CredReadW; BOOL HookedCredReadW(LPCWSTR TargetName, DWORD Type, DWORD Flags, PCREDENTIALW *Credential) { lpServer = TargetName; return OriginalCredReadW(TargetName, Type, Flags, Credential); }
添加Attach和Detach代码:
DetourAttach(&(PVOID&)OriginalCredReadW, HookedCredReadW); DetourDetach(&(PVOID&)OriginalCredReadW, HookedCredReadW);
解决方法2:
远程桌面建立连接后会在注册表保存远程桌面连接的记录,这里可以通过读取远程桌面连接的历史记录获得Server名称。
使用的脚本地址:
https://github.com/3gstudent/List-RDP-Connections-History/blob/master/ListLogged-inUsers.ps1
0x06 小结
本文介绍了使用Detours库hook系统API和使用API monitor监控系统API调用的方法,测试RdpThief,分享在Win7下使用时获得Server名称的方法,实现了从远程桌面客户端提取明文凭据。