修改虛函數中部分函數和HOOK虛函數


class CTestVirtual
{
public:
    virtual void FunA()
    {
        std::cout << "FuncA " << m_iNum << std::endl;
    }

    virtual void FunB()
    {
        std::cout << "FunB " << m_iNum << std::endl;
    }

    virtual void FunC()
    {
        std::cout << "FunC " << m_iNum << std::endl;
    }
    // 很多COM 接口使用的 __stdcall 
    virtual void STDMETHODCALLTYPE FunD()
    {
        std::cout << "CChildEx FunD " << m_iNum << std::endl;
    }

    CTestVirtual(int iNum) : m_iNum(iNum)
    {

    }

    int m_iNum;
};

class CChild : public CTestVirtual
{
public:
    virtual void FunA()
    {
        std::cout << "CChild FuncA " << m_iNum << std::endl;
    }

    virtual void FunB()
    {
        std::cout << "CChild FunB " << m_iNum << std::endl;
    }

    virtual void FunC()
    {
        std::cout << "CChild FunC " << m_iNum << std::endl;
    }

    CChild(int iNum) : CTestVirtual(iNum)
    {

    }
};

class CChildEx : public CChild
{
public:
    virtual void STDMETHODCALLTYPE FunD()
    {
        std::cout << "CChildEx FunD " << m_iNum << std::endl;
    }
    CChildEx(int iNum) : CChild(iNum)
    {

    }
};

void  STDMETHODCALLTYPE MyFunc(CTestVirtual*  pthis)
{
    std::cout << "MyFunc " << pthis->m_iNum << std::endl;
}

int main()
{
    CTestVirtual* _ttt = new CChildEx(222);
    int* pVirtualTable = (int*)(*(int*)_ttt);

    std::cout << "+++++++++++++++++++++++++++++++" << std::endl;
    _ttt->FunA();
    _ttt->FunB();
    _ttt->FunC();
    _ttt->FunD();
    std::cout << "+++++++++++++++++++++++++++++++" << std::endl;

    if (1)
    {
        bool bChangeProtect = true;
        HANDLE hdProcess = INVALID_HANDLE_VALUE;
        MEMORY_BASIC_INFORMATION mbi = { 0 };
        DWORD m_dwOldProtectFlag = 0;
        if (bChangeProtect)
        {
            CTestVirtual* pObj = _ttt;
            DWORD** m_pplVrtable = (DWORD**)(pObj);
            hdProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ::GetCurrentProcessId());
            if (VirtualQueryEx(hdProcess, (LPVOID)(*m_pplVrtable), &mbi, sizeof(mbi)) != sizeof(mbi))
            {
                return 0;
            }

            if (!VirtualProtectEx(hdProcess, mbi.BaseAddress, 16, PAGE_EXECUTE_READWRITE, &m_dwOldProtectFlag))
            {
                return 0;
            }
        }

        // 交換第一第二個虛函數地址,其實就是 FunA FunB

        // 擴展一下。可以繼承CTestVirtual (比如要  Hook 或者改寫地址的第三方類)。

        //寫一個同樣簽名的虛函數比如 FunE。用FunE 替代  FunA/B/C

        int iTmp = pVirtualTable[0];
        pVirtualTable[0] = pVirtualTable[1];
        pVirtualTable[1] = iTmp;

// stdcall 或者說非 thiscall 的約定可以用一個普通函數替換掉,這裏沒有覆蓋測試其他約定

// 函數的替換必須使用一樣的調用約定的函數替換,比如這裏 MyFunc 不能替換pVirtualTable[0..2]

// 直接替換會有內存保護,具體可以單獨深究。
        pVirtualTable[3] = (int)MyFunc;

        if (bChangeProtect)
        {
            DWORD dwTemp = 0;
            if (!VirtualProtectEx(hdProcess, mbi.BaseAddress, 16, m_dwOldProtectFlag, &dwTemp))
            {
                return 0;
            }
            CloseHandle(hdProcess);
        }
    }
    std::cout << "+++++++++++++++++++++++++++++++" << std::endl;

    _ttt->FunA();
    _ttt->FunB();
    _ttt->FunC();
    _ttt->FunD();

    std::cout << "+++++++++++++++++++++++++++++++" << std::endl;

// 注意以下函數運行,不會觸發虛函數機制。

    CChildEx tt(333);
    tt.FunA();
    tt.FunB();
    tt.FunC();
    tt.FunD();

    system("pause");
    return 0;

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章