从Hook虚函数到HOOK COM API
// HookVtable.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <iostream>#include <memory.h>#include <windows.h&
// HookVtable.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <memory.h>
#include <windows.h>
using namespace std;
class Test{
private:
HANDLE m_hProcess;
DWORD m_dwOldProtectFlag;
ULONG_PTR** m_pplVrtable;
ULONG_PTR m_OldProcAddress;
size_t m_sizeRead;
MEMORY_BASIC_INFORMATION mbi;
public:
Test() :m_hProcess(NULL),
m_dwOldProtectFlag(0),
m_pplVrtable(NULL),
m_OldProcAddress(0),
m_sizeRead(0)
{
ZeroMemory(&mbi, sizeof(mbi));
}
~Test()
{
};
virtual void fun1()
{
cout <<this<<":"<< "fun1 called!" << endl;
}
virtual void fun2()
{
cout << this << ":" << "fun2 called!" << endl;
}
virtual void fun3()
{
cout << this << ":" << "fun3 called!" << endl;
}
void Hook(ULONG_PTR dwAddFun)
{
m_pplVrtable = (ULONG_PTR**)(this);
m_hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ::GetCurrentProcessId());
if (VirtualQueryEx(m_hProcess, (LPVOID)(*m_pplVrtable), &mbi, sizeof(mbi)) != sizeof(mbi))
return;
if (!VirtualProtectEx(m_hProcess, mbi.BaseAddress, 16, PAGE_EXECUTE_READWRITE, &m_dwOldProtectFlag))
return;
ReadProcessMemory(m_hProcess, &(*m_pplVrtable)[1], &m_OldProcAddress, sizeof(ULONG_PTR), &m_sizeRead);
(*m_pplVrtable)[1] = dwAddFun;
}
void UnHook()
{
DWORD dwTemp = 0;
(*m_pplVrtable)[1] = m_OldProcAddress;
VirtualProtectEx(m_hProcess, mbi.BaseAddress, 16, m_dwOldProtectFlag, &dwTemp);
CloseHandle(m_hProcess);
}
};
void MyFun()
{
cout << "This is fake function" << endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
Test* pA = new Test;
Test* pA2 = new Test;
pA->Hook((ULONG_PTR)MyFun);
pA->fun1();
pA->fun2();
pA2->fun2();
pA->UnHook();
pA->fun1();
pA->fun2();
pA2->fun2();
delete pA;
return 0;
}
同一个进程下 某个类的虚函数列表是唯一的, 所有类对象共享 ,类对象的this指针指向的第一个地址就是虚函数表的地址。
修改表中某个虚函数的地址就能修改所有类对象的函数跳转 (虚函数的索引 是虚函数在类里面的排序位置 由0开始)。
以上就是HOOK COM API的基本原理
测试一下吧
ITextServices* pTextServices = NULL;
typedef HRESULT(ITextServices::*TrueTxSendMessage)(UINT msg, WPARAM wparam, LPARAM lparam, LRESULT *plresult);
TrueTxSendMessage g_func = NULL;
HRESULT STDMETHODCALLTYPE FakeTxSendMessage(
UINT msg,
WPARAM wparam,
LPARAM lparam,
LRESULT *plresult)
{
MessageBox(NULL, _T("FakeTxSendMessage"), _T("FakeTxSendMessage"), MB_OK);
return (pTextServices->*(g_func))(msg,wparam,lparam,plresult);
}
HANDLE m_hProcess = NULL;
DWORD** m_pplVrtable = NULL;
DWORD m_dwOldProtectFlag = 0;
DWORD m_OldProcAddress = 0;
DWORD m_sizeRead = 0;
MEMORY_BASIC_INFORMATION mbi = {0};
void Hook(DWORD dwAddFun, ITextServices* pITextServices)
{
m_pplVrtable = (DWORD**)(pITextServices);
m_hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ::GetCurrentProcessId());
if (VirtualQueryEx(m_hProcess, (LPVOID)(*m_pplVrtable), &mbi, sizeof(mbi)) != sizeof(mbi))
return;
if (!VirtualProtectEx(m_hProcess, mbi.BaseAddress, 16, PAGE_EXECUTE_READWRITE, &m_dwOldProtectFlag))
return;
ReadProcessMemory(m_hProcess, &(*m_pplVrtable)[3], &m_OldProcAddress, sizeof(DWORD), &m_sizeRead);
memcpy(&g_func, &m_OldProcAddress, sizeof(DWORD));
(*m_pplVrtable)[3] = dwAddFun;
}
void UnHook()
{
DWORD dwTemp = 0;
(*m_pplVrtable)[3] = m_OldProcAddress;
VirtualProtectEx(m_hProcess, mbi.BaseAddress, 16, m_dwOldProtectFlag, &dwTemp);
CloseHandle(m_hProcess);
}
do
{
HRESULT hr;
IUnknown* pUnk = NULL;
// Create an instance of the application-defined object that implements the ITextHost interface.
MyTextHost* pTextHost = new MyTextHost(g_hWnd);
MyTextHost* pTextHost2 = new MyTextHost(g_hWnd);
if (pTextHost == NULL)
break;
PCreateTextServices TextServicesProc = NULL;
HMODULE hmodRichEdit = LoadLibrary(_T("Msftedit.dll"));
// Retrieve the IID_ITextServices interface identifier from Msftedit.dll.
IID* pIID_ITS = NULL;
if (hmodRichEdit)
{
pIID_ITS = (IID*)(VOID*)GetProcAddress(hmodRichEdit, "IID_ITextServices");
TextServicesProc = (PCreateTextServices)GetProcAddress(hmodRichEdit, "CreateTextServices");
}
if (TextServicesProc)
{
hr = TextServicesProc(NULL, pTextHost, &pUnk);
}
// Create an instance of the text services object.
//hr = CreateTextServices(NULL, pTextHost, &pUnk);
if (FAILED(hr))
break;
// Retrieve the ITextServices interface.
hr = pUnk->QueryInterface(*pIID_ITS, (void **)&pTextServices);
Hook((ULONG_PTR)FakeTxSendMessage, pTextServices);
//UnHook();
if (TextServicesProc)
{
hr = TextServicesProc(NULL, pTextHost2, &pUnk);
hr = pUnk->QueryInterface(*pIID_ITS, (void **)&pTextServices);
}
pUnk->Release();
hr = pTextServices->TxSendMessage(WM_SETFOCUS, 0, 0, 0);
if (FAILED(hr))
break;
} while (0);
注意事项:
1,保存原有虚函数的指针类型需要为类成员函数指针类型
typedef HRESULT(ITextServices::*TrueTxSendMessage)(UINT msg, WPARAM wparam, LPARAM lparam, LRESULT *plresult);
否则异常
2,要保证调用约定前后一致
HRESULT STDMETHODCALLTYPE FakeTxSendMessage(
UINT msg,
WPARAM wparam,
LPARAM lparam,
LRESULT *plresult)
{
MessageBox(NULL, _T("FakeTxSendMessage"), _T("FakeTxSendMessage"), MB_OK);
return (pTextServices->*(g_func))(msg,wparam,lparam,plresult);
}
否则异常
Thanks~
更多推荐
所有评论(0)