Principle Analysis
When a virtual function is called, the compiler-generated code calls a function such as the virtual table address [0] (param1, param2). The function name is not already being called.
When we change the function implementation in the virtual table address [n] to another function, we control the implementation of the virtual function.
Experiment
According to the principle of virtual table, experiment to modify the virtual function table entry address of your program.
When the compiler-generated code executes a virtual function A, it executes the non-virtual function B that we define ourselves.
Knowledge points
* Use union assignment to bypass compiler functions and variable strongly-assigned value restrictions
* Execution of class member function pointers
* Modify and restore your own code snippet properties
* Positioning and reading and writing of virtual function table entries
Experiment Code
[CPP]View PlainCopy
- virtual void Fnfoo (); < CC ' s Fnfoo
- typedef VOID (CC::* Pfn_fnfoo) ();
- typedef Union UN_FUNCTION_PT
- {
- Pfn_fnfoo PFN;
- int ifunaddr;
- }un_function_pt;
- void Fnreplacevirtualfunction ()
- {
- /// Replace the virtual table function experiment
- /// through experiments, there are 2 cc virtual functions
- /// virtual function 1 cc destructor
- /// virtual function 2 Cc::fnfoo
- ////We will replace the Cc::fnfoo in the virtual table with Fnnewvirtualfunction ()
- int ivirtualtbladdr = 0; ///< cc virtual function table address
- int ivirtualfunctionaddr_cc_fnfoo = 0; ///< Address of the Cc::fnfoo object method
- Un_function_pt UNFUNPT; ///< for int to fun*, bypassing compiler restrictions
- DWORD dwoldprotect = 0;
- ca* PCA = new CC ();
- IVIRTUALTBLADDR = * ((int*) PCA);
- Ivirtualfunctionaddr_cc_fnfoo = * ((int*) ivirtualtbladdr + 1);
- /// The original function of executing cc.fnfoo virtual function
- UNFUNPT.IFUNADDR = Ivirtualfunctionaddr_cc_fnfoo;
- (((cc*) PCA)->*UNFUNPT.PFN) ();
- /// manual execution of PCA Fnnewfunctionsamedefineasfnfoo
- /// Let CC instance execute our own specified CC class member function
- /// must be a function of the same parameter return value as the CC class already has
- UNFUNPT.PFN = &CC::fnNewFunctionSameDefineAsfnFoo;
- (((cc*) PCA)->*UNFUNPT.PFN) ();
- //Make memory writable
- if (VirtualProtect ((void*) ivirtualtbladdr, 8, Page_execute_readwrite, &dwoldprotect))
- {
- /// replace the Cc::fnfoo in the virtual table as Cc::fnnewfunctionsamedefineasfnfoo
- UNFUNPT.PFN = &CC::fnNewFunctionSameDefineAsfnFoo;
- ///< does not release the write limit 0x0040 the code snippet, it C05
- * ((int*) ivirtualtbladdr + 1) = unfunpt.ifunaddr;
- //Reprotect
- VirtualProtect ((void*) ivirtualtbladdr, 8, Dwoldprotect, NULL);
- /// execute Pca->fnfoo becomes the execution Pca->fnnewfunctionsamedefineasfnfoo
- Pca->fnfoo ();
- //OK has executed the function of our own specified CC and cc::fnfoo with the same parameter return value.
- /// This function can be a non-virtual function
- }
- }
[CPP]View PlainCopy
- Classtest.h:interface for the Cclasstest class.
- //
- //////////////////////////////////////////////////////////////////////
- #if!defined (Afx_classtest_h__d794cc4b_d79e_4a61_9d5a_95110788ae39__included_)
- #define Afx_classtest_h__d794cc4b_d79e_4a61_9d5a_95110788ae39__included_
- #if _msc_ver > 1000
- #pragma once
- #endif//_msc_ver > 1000
- #include <iostream>
- Using namespace std;
- Class CA
- {
- Public
- CA ();
- virtual ~ca ();
- virtual void Fnfoo ();
- };
- Class CB: Public CA
- {
- Public
- CB ();
- virtual ~CB ();
- virtual void Fnfoo ();
- };
- Class CC: Public CB
- {
- Public
- CC ();
- virtual ~cc ();
- virtual void Fnfoo ();
- void Fnnewfunctionsamedefineasfnfoo ();
- };
- #endif//!defined (AFX_CLASSTEST_H__D794CC4B_D79E_4A61_9D5A_95110788AE39__INCLUDED_)
[CPP]View PlainCopy
- ClassTest.cpp:implementation of the Cclasstest class.
- //
- //////////////////////////////////////////////////////////////////////
- #include "ClassTest.h"
- //////////////////////////////////////////////////////////////////////
- Ca
- //////////////////////////////////////////////////////////////////////
- CA::CA ()
- {
- cout << "CA::CA" << Endl;
- }
- Ca::~ca ()
- {
- cout << "Ca::~ca" << Endl;
- }
- void Ca::fnfoo ()
- {
- cout << "Ca::fnfoo" << Endl;
- }
- //////////////////////////////////////////////////////////////////////
- Cb
- //////////////////////////////////////////////////////////////////////
- CB::CB ()
- {
- cout << "CB::CB" << Endl;
- }
- CB::~CB ()
- {
- cout << "CB::~CB" << Endl;
- }
- void Cb::fnfoo ()
- {
- cout << "Cb::fnfoo" << Endl;
- }
- //////////////////////////////////////////////////////////////////////
- Cc
- //////////////////////////////////////////////////////////////////////
- CC::CC ()
- {
- cout << "cc::cc" << Endl;
- }
- CC::~CC ()
- {
- cout << "cc::~cc" << Endl;
- }
- void Cc::fnfoo ()
- {
- cout << "Cc::fnfoo" << Endl;
- }
- void Cc::fnnewfunctionsamedefineasfnfoo ()
- {
- ///A function to replace the same parameter of the virtual function with the return value
- cout << "Cc::fnnewfunctionsamedefineasfnfoo" << Endl;
- }
Implementation effect
[CPP]View PlainCopy
- Ca::ca
- Cb::cb
- Cc::cc
- Cc::fnfoo
- Cc::fnnewfunctionsamedefineasfnfoo
- Cc::fnnewfunctionsamedefineasfnfoo
http://blog.csdn.net/lostspeed/article/details/50359445
The realization analysis of the principle of the virtual function table (when we replace the function in the virtual table address [n], then we control the implementation of the virtual function)