C++ malloc不分配内存

C++ malloc不分配内存,c++,winapi,memory,C++,Winapi,Memory,当调试我的代码时,我看到它跳入ram的未定义部分,似乎malloc不起作用。下面的代码旨在创建一个蹦床,并将realFunction挂接到fakeFunction void patch() { PINT trampoline = (PINT)malloc(15); DWORD oldProtect; *((PBYTE)trampoline) = 0xE8; *((PDWORD)trampoline + 1) = ((DWORD)fakeFunction - (DW

当调试我的代码时,我看到它跳入ram的未定义部分,似乎malloc不起作用。下面的代码旨在创建一个蹦床,并将realFunction挂接到fakeFunction

void patch()
{
    PINT trampoline = (PINT)malloc(15);
    DWORD oldProtect;
    *((PBYTE)trampoline) = 0xE8;
    *((PDWORD)trampoline + 1) = ((DWORD)fakeFunction - (DWORD)trampoline -5);
    memcpy(trampoline, realFunction, 6);
    *((PDWORD)trampoline + 7) = 0xE9;
    *((PDWORD)trampoline + 8) = ((DWORD)fakeFunction - (DWORD)realFunction - 5);
    VirtualProtect((LPVOID)realFunction, 6, PAGE_EXECUTE_READWRITE, &oldProtect);
    *((PBYTE)realFunction) = 0xE9;
    *((PDWORD)realFunction + 1) = ((DWORD)trampoline - (DWORD)realFunction - 5);
    VirtualProtect((LPVOID)realFunction, 6, oldProtect, NULL);
}
更新:我解决了问题,下面是解释的代码:

#include <iostream>
#include <windows.h>

using namespace std;

void realFunction()
{
    MessageBox(NULL, "realFunction()", "Trace", MB_OK);
}

void fakeFunction()
{
    MessageBox(NULL, "fakeFunction()", "Trace", MB_OK);
}

//I wrote this generic function (although not using it below) to ease the writing to memory process
template<typename T>
void writeMemory(DWORD address, T value)
{
    *((T*)address) = value;
}

void main()
{
    BYTE originalPrologue[sizeof(DWORD[2])]; //Why DWORD[2]... meh it is just 2*4 = bytes not a big deal.
    DWORD oldProtection;
    DWORD addr = (DWORD)realFunction;

    for (int i = 0; i < sizeof(DWORD[2]); i++) {
        originalPrologue[i] = (*(PBYTE)(addr + i));
    }

    //(DWORD)((DWORD)fakeFunction - (DWORD)realFunction - 5) note that we do target - source - 5, why - 5 ? because the size of jump instruction is 5, and the destination of jump is relative to it's address.
    //Implement Hook
    VirtualProtect(realFunction, sizeof(DWORD[3]), PAGE_EXECUTE_READWRITE, &oldProtection);
    *((PBYTE)addr) = 0xE9; E9 is JMP instruction
    *((PDWORD)(addr + 1)) = (DWORD)((DWORD)fakeFunction - (DWORD)realFunction - 5);
    VirtualProtect(realFunction, sizeof(DWORD[3]), oldProtection, NULL);

    realFunction(); //Boom, we now jump to our fake function instead of the original one.

    //Unimplement hook by restoring the original prologue
    VirtualProtect(realFunction, sizeof(DWORD[3]), PAGE_EXECUTE_READWRITE, &oldProtection);
    memcpy(realFunction, originalPrologue, sizeof(DWORD[2]));
    VirtualProtect(realFunction, sizeof(DWORD[3]), oldProtection, NULL);

    realFunction(); //Test it and we have the original function back!

    while (true){
        cin.get();
    }
}

这段代码充满了错误。正如在注释中指出的,您根本没有考虑指针算法,所以您在不正确的内存地址中写入值。您也没有进行任何错误处理,甚至没有正确设置迂回和蹦床功能。您显然没有阅读关于绕道实际实施方式的文档:

特别是:

为了绕行目标函数,如果没有提供静态蹦床,则绕行首先为动态蹦床函数分配内存,然后启用对目标和蹦床的写访问。从第一条指令开始,Detours将指令从目标复制到蹦床,直到至少复制了5个字节,足以执行无条件跳转指令。如果目标函数小于5个字节,则迂回将中止并返回 返回一个错误代码。为了复制指令,Detours使用一个简单的表驱动反汇编程序。Detours在结束时添加跳转指令 蹦床到第一个非复制指令 目标函数的属性。Detours将无条件跳转指令写入Detours函数,作为目标函数的第一条指令 作用最后,Detours将恢复目标函数和trampoline函数的原始页面权限,并通过调用FlushInstructionCache刷新CPU指令缓存

CPU指令长度可变。不同的指令具有不同的字节长度。您可能需要将超过5个字节复制到您的蹦床中才能获得完整的说明。您不能假设每个函数中使用的字节数正好是6个,因为您可能会复制多字节指令的一部分。因此,您必须分析正在绕道的原始函数的指令,并根据需要复制正确的字节数,以便trampoline始终包含完整的指令,然后您必须在trampoline内部的正确偏移处插入JMP指令,并使其跳转到原始函数的正确偏移量

更糟糕的是,你的蹦床跳进了你的绕行功能而不是原来的功能,你正在修补原来的功能,跳进蹦床而不是原来的绕行功能


简而言之,这段代码的每一行都是在每一步都做错事。如果你要解决这样一个先进的技术,那么至少要足够聪明,使用一个预先制作的库,避免你犯所有这些错误。您的错误代码有可能导致严重的内存损坏和运行时错误。

您的代码存在大量未定义的行为。假设一个DWORD是4字节,大多数是在WIN32上,但如果它更大,情况只会更糟,您可能需要考虑像PDWORDtrampoline+7这样的东西实际上是做什么的。指针数学表示获取15字节分配的地址,从该地址偏移28字节,然后使用该地址在不确定内存中写入DWORD。我推测15只应该与某种大小的倍数交配。检查一下你从哪个网站偷来的,很可能他们没有犯同样的错误。malloc很好,这是你的代码。我必须同意@WhozCraig。这是我一生中见过的最恐怖的密码之一。说真的……我还在学习,伙计们,请耐心听我说,@WhozCraig,那么为什么要从所说的地址偏移28字节呢?@malloc确实在exe中创建了一个空间,让我们编写一些自定义代码,对吗?@DanielEugen,这是键入的指针算法,如果你不知道那是什么,启动搜索引擎,因为你不应该在没有彻底理解C语言的概念的情况下管理指针,尤其是在类似这样的情况下。@DanielEugen:你显然不理解指针,因为你正在犯一些根本性的错误。显然,您根本不了解设置函数迂回的正确方法。有很多现有的迂回库为你处理复杂的细节,你需要停止你正在做的事情,去挑选其中一个来使用。这段代码不会在白宫执行:D,我只是在学习,顺便说一句,我会更好地理解事情。这就是为什么每当我遇到问题时,我都会问你们堆栈溢出的问题。。。是的,我已经读了很多关于函数挂钩和内存地址,汇编和我在这里提供的例子只是一个粗略的尝试,使一些工作,然后我会完善它。这不是你应该学习编程的代码类型。这是一种一旦你已经知道你在做什么而你不知道的代码。有更好更安全的方法来学习如何公关
我没有学习如何编程:正如我之前提到的,我已经用C语言编程6年了,我非常了解编程语言是如何工作的。然而,C++对我来说还是有点奇怪,因为你知道GC收藏家正在为C和Javalok做我们所有的备忘录相关的工作人员。请不要只是关上门的人。相反,为人们打开它们,因为他们可能真的需要帮助。我已经进一步了解了一些,现在我可以复制函数的序言,并在钩子之后恢复它。我分享了我的知识,以便其他人可以从中受益,即使它很小,但它可能会帮助初学者。您的实现仍然是失败的和有风险的。现在您正在复制12个字节,而不是6个字节,这很容易太多。如果目标函数小于12字节怎么办?您只需要替换5个字节,尽管您可能需要将超过5个字节复制到蹦床中。必须分析目标函数以计算要复制的正确字节数和要跳转到的正确内存偏移量。你没有这样做。人们不会帮你写危险的代码,你所做的是危险的。