C++ COM Object Hotpatching?

房东的猫 提交于 2019-12-04 20:41:32

You may not have the source to class A1, but do you control when it gets instantiated (either by "new", CoCreateInstance, or some other factory function)? If so, then just implement a class that implements interface A and just forwards all the calls on interface A to the real object and intercept the method(s) you care about.

In the example below, we show an example of replacing

class InterfaceA : public IUnknown
{
public:

    virtual int M1() = 0;
    virtual int M2(int x, int y) = 0;
    virtual int M3() = 0;
};


class CMyWrapperClass : public InterfaceA
{
public:

    int _refcount;
    InterfaceA* _pInner;

    CSomeClass2(InterfaceA* pInner)
    {
        _pInner = pInner;
        _pInner->AddRef();
        _refcount = 1;
    }

    ~CSomeClass2()
    {
        _pInner->Release();
    }

    virtual int M1() {return _pInner->M1();}
    virtual int M2(int x, int y)  {printf("CSomeClass2::M2(x=%d, y=%d)\n", x, y); return _pInner->M2(x,y);  }
    virtual int M3() {return _pInner->M3();}

    // not shown - addRef, release, queryinterface
};


   // example instantiation
   hr = CoCreateInstance(CLSID_A1, NULL, CLXCTX_ALL, IID_InterfaceA, (void**)&pInterfaceA);

   // now do the wrap
   pInterfaceA = new CMyWrapperClass(pInterfaceA);

If you don't have control of the instantiation of the class you are trying to hotpatch, I do have code to share for that. But it's obivously a bit more complicated. If this doesn't work, I'll post another answer directly related to hotpatching a COM vtable.

It took me quite a while to understand this problem. I actually wrote out a good chunk of code that I thought to demonstrate how to patch a vtable and then invoke the original method in a wrapper class. Patching the vtable is easy.

And then I discovered the problem you are referring to. And that is when the patched vtable method is called (newmethod), even if it defined within another class, "this" is the original object and you don't have any context of which instance is being invoked. So you can't easily just reference a member variable to get back to the "oldmethod" you have saved off.

So after some thought, I think the global map is the safest approach for doing this. You likely only need a lock (critical_section) to guard inserting, removing, or looking up the function pointers in the map. You likely won't need to hold the lock while invoking the old method after you have safely retrieved it from the map. As such, the runtime overhead of doing this operation is very negligible.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!