hook COM接口抛出vTable

hook COM interface throw vTable

本文关键字:vTable 接口 COM hook      更新时间:2023-10-16

我正在尝试挂钩基于ICredentialProvider接口的自定义Credential Provider UI。

使用这个指南(Vtable Patching),我成功地挂接了COM接口。

但是挂接GetCredentennialAt方法的问题是,我将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;
}

使用IDA,我显示加载第三个自定义dll。此Dll中断接口。