C++memcpy返回true,没有任何更改

C++ memcpy returning true with no changes

本文关键字:任何更 返回 true C++memcpy      更新时间:2023-10-16

我正在尝试编写一个简单的钩子类,它在目标地址安装一个钩子,并将流迂回到自定义函数中。

Main.cpp

#include "SingleHook.h"
#include <iostream>
using namespace std;
void originalFunction()
{
    cout << "originalFunction()" << endl;
}
void fakeFunction()
{
    cout << "fakeFunction()" << endl;
}
void main()
{
    SingleHook sHook((DWORD)originalFunction, (DWORD)fakeFunction);
    originalFunction(); //Should call the original function
    sHook.InstallHook();
    originalFunction(); //Should call the fake function
    sHook.UninstallHook();
    originalFunction(); //Should again call the original function
    cin.get();
}

SingleHook.h

#pragma once
#define HLength 6
#include <windows.h>
class SingleHook {
private:
    void* hookTarget;
    byte originalBytes[HLength];
    byte hookBytes[HLength];
public:
    SingleHook(DWORD originalFunction, DWORD targetFunction)
    {
        //backing up original bytes
        ::memcpy(originalBytes, &originalFunction, HLength);
        //generating hook bytes
        hookBytes[0] = 0x68; //push
        hookBytes[1] = ((byte*)targetFunction)[0];
        hookBytes[2] = ((byte*)targetFunction)[1];
        hookBytes[3] = ((byte*)targetFunction)[2];
        hookBytes[4] = ((byte*)targetFunction)[3];
        hookBytes[5] = 0xC3; //retn
        //setting up hook target
        hookTarget = &originalFunction;
    }
    void* InvokeOriginalFunction(...);
    void InstallHook();
    void UninstallHook();
};

SingleHook.cpp

#include "SingleHook.h"
void* SingleHook::InvokeOriginalFunction(...)
{
    UninstallHook();
    //TODO INVOKE ORIGINAL SOMEHOW
    InstallHook();
    return nullptr;
}
void SingleHook::InstallHook()
{
    DWORD oldProt;
    ::VirtualProtect(hookTarget, HLength, PAGE_EXECUTE_READWRITE, &oldProt);
    ::memcpy(hookTarget, hookBytes, HLength);
    ::VirtualProtect(hookTarget, HLength, oldProt, nullptr);
}
void SingleHook::UninstallHook()
{
    DWORD oldProt;
    ::VirtualProtect(hookTarget, HLength, PAGE_EXECUTE_READWRITE, &oldProt);
    ::memcpy(hookTarget, originalBytes, HLength);
    ::VirtualProtect(hookTarget, HLength, oldProt, nullptr);
}

现在的问题是,当我安装钩子并尝试调用originalFunction()时,它仍然进入原始函数,并且没有调用fakeFunction()。。。我已经仔细检查了代码,一切似乎都很好,但肯定有什么地方找到了。

看看这里:

SingleHook(DWORD originalFunction, DWORD targetFunction)
{
    //backing up original bytes
    ::memcpy(originalBytes, &originalFunction, HLength);

&originalFunction是堆栈上变量originalFunction的地址。请改用(void*)originalFunction

需要注意的是,C和C++标准与函数指针和对象指针之间的强制转换没有任何意义——如果目标变量足够大,可以容纳整个地址(不能保证,确实存在代码和数据大小不同的系统(,并且您强制转换回原始指针类型,则会返回原始值。任何其他用法都是未定义的行为。

自变异代码也是未定义的行为。

在运行时重定向函数调用的唯一支持机制是使用函数指针间接进行调用以更改函数指针。

由于该语言没有提供任何保证,您正在深入研究编译器生成的实际指令的细节。。。这意味着你最好看看这些指令,看看调用是否是你期望的地址(在各种条件下,&originalFunction可能是蹦床的地址,但编译器仍然可能直接向真实的函数体发出调用,或者内联调用,等等(

您可能还必须使用特定于机器的指令来刷新指令缓存,因为对数据的更改通常被认为不会更改代码。在Windows上,有一个FlushInstructionCache API调用,您需要在修补代码时使用它。阅读关于为什么需要的解释(讨论了非Windows系统,但仍然很好地表达了这个概念(

相关文章: