我正在尝试基于 ICredentialProvider 接口挂钩自定义凭据提供程序 UI。
使用本指南(Vtable Patching),我成功地钩住了 COM 接口。
但是挂钩GetCredentenialAt方法有问题,我将 vtable 索引设置为 10,然后尝试重新登录。LogonUI 屏幕闪烁:Ctrl+Alt+Del 屏幕:。
我的源代码:
#include "stdafx.h"
#include "VtableHooks.h"
#include "credentialprovider.h"
namespace Hook
{
STDMETHODIMP GetCredentialAt(IUnknown* This, DWORD dwIndex, ICredentialProviderCredential** ppcpc);
STDMETHODIMP QueryInterface(IUnknown* This, REFIID riid, void **ppvObject);
}
struct Context
{
Context(): m_Name("Hooked object"){}
PVOID m_OriginalQueryInterface;
PVOID m_OriginalGetCredentialAt;
ATL::CComBSTR m_Name;
};
std::auto_ptr<Context> g_Context;
HRESULT HookMethod(IUnknown* original, PVOID proxyMethod, PVOID* originalMethod, DWORD vtableOffset)
{ PVOID* originalVtable = *(PVOID**)original;
if (originalVtable[vtableOffset] == proxyMethod)
return S_OK;
*originalMethod = originalVtable[vtableOffset];
originalVtable[vtableOffset] = proxyMethod;
return S_OK;
}
HRESULT InstallComInterfaceHooks(IUnknown* originalInterface, REFIID riid)
{
HRESULT hr = S_OK;
if (riid == IID_ICredentialProvider)
{
// Only single instance of a target object is supported in the sample
if (g_Context.get())return E_FAIL;
ATL::CComPtr<ICredentialProvider> so;
HRESULT hr = originalInterface->QueryInterface(IID_ICredentialProvider, (void**)&so);
if (FAILED(hr)) return hr; // we need this interface to be present
// remove protection from the vtable
DWORD dwOld = 0;
if (!::VirtualProtect(*(PVOID**)(originalInterface), sizeof(LONG_PTR), PAGE_EXECUTE_READWRITE, &dwOld))
return E_FAIL;
// hook interface methods
g_Context.reset(new Context);
HookMethod(so, (PVOID)Hook::QueryInterface, &g_Context->m_OriginalQueryInterface, 0);
HookMethod(so, (PVOID)Hook::GetCredentialAt, &g_Context->m_OriginalGetCredentialAt, 10);
}
return hr;
}
typedef HRESULT (WINAPI *QueryInterface_T)(IUnknown* This, REFIID riid, void **ppvObject);
STDMETHODIMP Hook::QueryInterface(IUnknown* This, REFIID riid, void **ppvObject)
{
QueryInterface_T qi = (QueryInterface_T)g_Context->m_OriginalQueryInterface;
HRESULT hr = qi(This, riid, ppvObject);
return hr;
}
typedef HRESULT(WINAPI *GetCredentialAt_T)(IUnknown* This, DWORD dwIndex, ICredentialProviderCredential** ppcpc);
STDMETHODIMP Hook::GetCredentialAt(IUnknown* This, DWORD dwIndex, ICredentialProviderCredential** ppcpc)
{
GetCredentialAt_T qi = (GetCredentialAt_T)g_Context->m_OriginalGetCredentialAt;
HRESULT hr = qi(This, dwIndex, ppcpc);
return hr;
}