如何将读写重定向到变量?

时间:2016-01-26 14:03:32

标签: c++ windows reverse-engineering

我有一个使用MSVC 6.0构建的已编译的32位Windows应用程序。我想注入代码并将读取或写入重定向到变量。对于简单的情况,例如:

DWORD& dword_995344 = *(DWORD*)0x995344;

可以工作。但我还希望代码编译为自己的独立exe。显然这不起作用,因为0x995344不太可能是有效的地址。此外,它不会像char buffer[256]; // at address 0xdeadbeef那样适用于此。

然后我想也许我可以想出一些模板包装器:

template<DWORD VarAddr, class VarType>
class Var
{
public:
    using VarTypePtr = VarType*;

    Var()
    {
        mVar = (VarTypePtr)VarAddr;
    }

    Var(const Var&) = delete;
    Var& operator = (const Var&) = delete;

    operator VarType()
    {
        return *mVar;
    }

    void operator = (VarType v)
    {
        *mVar = v;
    }


private:
    VarTypePtr mVar;
};

Var<0x00995344, DWORD> dword_995344_;

void Test()
{
    dword_995344_ = 7;
    DWORD y = dword_995344_;
}

但是,在某些情况下,再次处理所有类型和案例并不简单或可能不可行。是否有其他技术(无论多么hacky :))可以捕获读写,所以我可以做类似的事情:

DWORD dword_995344 = 0;

void InstallVarHooks()
{
   RedirectReadWrites(&dword_995344, 0x995344);
}

3 个答案:

答案 0 :(得分:3)

您可能会考虑使用代码来收集所需的信息。这可以使用program transformation systems完成。

这样的工具可以让你写出基本上说的模式,

when you see <this>, replace it by <that>

以编译器准确的方式(不是字符串黑客,它永远不会对真实代码起作用)。在你的情况下,你想说些什么,

when you see a <write of varX>,
replace it by <store varX to known location, then do write varX>

如何做到这一点的灵感可以在我的技术论文Branch Coverage for Arbitrary Languages made Easy中找到。

要使用C ++执行此操作,请参阅https://softwareengineering.stackexchange.com/a/257441/12135

答案 1 :(得分:1)

我不确定我是否理解了你的问题,你想拦截变量写入的时刻,如果是,那么将写入重定向到其他内存位置,并且读取相同。这个部分理论上可以用调试断点来完成,有一个项目https://github.com/mmorearty/hardware-breakpoints可以给你提示如何完成它。它看起来很过时,但既然你想在VS6.0应用程序上使用它,它实际上可能会工作。您必须使用DLL注入代码才能进入目标应用程序以使用它。

这实际上只是一个工具,它应该允许你在读/写变量时拦截时刻,你仍然需要编写能够适当修改变量的代码。

无论如何看起来像很多黑客。

答案 2 :(得分:1)

虽然语法很乱,但完全有可能引用数组:

char (&TheArray)[256] = *reinterpret_cast<char(*)[256]>(0xDEADBEEF);

在C ++ 11中,您可以使用auto,从而避免重复两次类型:

auto &TheArray = *reinterpret_cast<char(*)[256]>(0xDEADBEEF);

还有一种更简单的方法就是只需要指向地址:

char *TheArray = *reinterpret_cast<char*>(0xDEADBEEF);

由于指针的作用类似于C中的数组(因此也是C ++),因此上面的效果基本相同。

如果你需要的是对任意地址的某个对象的引用,即使它是任意复杂的类型,所以方法确实有效。

如果您要访问的变量不是位于常量地址(这几天变量很少),您可以使用任意复杂的表达式替换常量0xDEADBEEF,该表达式计算出所述变量的地址,这可能涉及调用GetModuleHandle,以获取主要可执行文件的地址。