假设我有一个这样的函数(完全随机,我只是在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指针然后dereferance来获取我们试图读取的当前字节行的值然后存储在functionByteArray
中,但它似乎无法正常工作。我究竟做错了什么?我想要完成的是什么?
答案 0 :(得分:4)
理论上(根据C ++ 11标准),您甚至无法将函数指针转换为数据指针(在Harvard architectures代码上,数据位于不同的存储器和不同的地址空间中)。某些操作系统或处理器可能还禁止读取可执行文件code segments(请阅读NX bit)。
实际上,在运行某些操作系统(如Linux或Windows)的x86-64(或32位x86)上,功能代码是 bytes 的序列,可以是未对齐的,并且位于( common)其进程的虚拟地址空间。所以你至少应该char functionByteArray[40];
,你可以使用<string>
中的std::memcpy来做一些
std::memcpy(functionByteArray, (char*)&exampleAuthetnication,
sizeof(functionByteArray));
最后你的代码是错误的,因为-on x86-64值得注意 - int
与指针的大小不同(因此(int)&exampleAuthetnication
正在丢失地址的高位字节)。你应该至少使用intptr_t
。并且int
具有比代码更强的对齐约束。
exampleAhtetnication
编译g++ -O -fverbose-asm -S
C ++代码并查看生成的.s
文件。
请注意,C ++编译器可能optimize到&#34;删除&#34;来自代码段的一些函数(例如,因为该函数已在任何地方内联),或者将函数代码分成几部分,或者将其放入
exampleAhtetnication
代码&#34;内部&#34;另一个功能......
答案 1 :(得分:-1)
C ++源代码不是计算机执行的指令列表;它是描述程序含义的语句集合。
您的编译器会解释这些语句并生成实际的指令序列(通过汇编阶段),这些指令实际上可以在我们的物理现实中执行。
用于执行此操作的语言不提供用于检查组成编译程序的字节的任何工具。你通过未定义行为的魔力,你所有试图转换函数指针等的尝试可能会随机地给你一些类似的数据,但结果就是:undefined。
如果要检查已编译的可执行文件,请从程序外部执行此操作。例如,您可以使用十六进制编辑器。