2

假设我有一个这样的函数(完全随机,我只是在 30 秒内写了一个例子)

bool exampleAuthetnication(char *a, char *b)
{
    bool didAuthenticate = false;
    if(strcmp(a, b) == 0)
    {
        didAuthenticate = true;
    }

    if(didAuthenticate)
    {
        return true;
    }
    else
    {
        stopExecutable();
        return false;
    }
}

我将如何阅读该函数的前几个字节?

我想出了这个

int functionByteArray[10];
for (int i = 0; i < 10; i++)
{
    functionByteArray[i] = *(int*)(((int)&exampleAuthetnication) + (0x04 * i));
}

其背后的逻辑是我们获取函数的内存地址(在这种情况下exampleAuthetnication()),然后我们转换为 int 指针,然后取消引用以获取我们尝试读取的当前字节行的值,然后存储functionByteArray,但它没有似乎工作正常。我究竟做错了什么?我想要完成的事情可能吗?

4

2 回答 2

4

理论上(根据 C++11 标准),您甚至不能将函数指针转换为数据指针(在哈佛架构上,代码和数据位于不同的内存和不同的地址空间中)。一些操作系统或处理器也可能禁止读取可执行代码段(阅读关于NX 位)。

实际上,在运行某些操作系统(如 Linux 或 Windows)的 x86-64(或 32 位 x86)上,功能代码是一个字节序列,可以不对齐,并且位于其进程的(公共)虚拟地址空间中。所以你至少应该有char functionByteArray[40];并且你可以使用std::memcpy from<string>并做一些

std::memcpy(functionByteArray, (char*)&exampleAuthetnication,
            sizeof(functionByteArray));

最后,您的代码是错误的,因为 - 在 x86-64 上 -int与指针的大小不同(因此(int)&exampleAuthetnication丢失了地址的高字节)。你至少应该使用intptr_t. 并且int比代码有更强的对齐约束。

顺便说一句,您可能还要求您的编译器显示生成的汇编代码。使用GCC编译您的exampleAhtetnicationC++ 代码g++ -O -fverbose-asm -S 并查看生成的.s文件。

请注意,C++ 编译器可能会优化到从代码段中“删除”某些函数(例如,因为该函数已在各处内联),或者将函数代码分成几部分,或者将该 exampleAhtetnication代码“放入”另一个函数中。 ..

于 2018-02-28T06:07:04.157 回答
-1

C++ 源代码不是计算机要执行的指令列表;它是描述程序含义的语句的集合。

您的编译器会解释这些语句并生成可以在我们的物理现实中实际执行的实际指令序列(通过汇编阶段)。

用于这样做的语言不提供任何工具来检查构成编译程序的字节。通过未定义行为的魔力,您所有尝试转换函数指针等可能会随机给您一些类似的数据,但结果就是:未定义。

如果您想检查已编译的可执行文件,请从程序外部进行。例如,您可以使用十六进制编辑器。

于 2018-02-28T12:27:49.073 回答