1

假设我想执行任意 mov 指令。我可以编写以下函数(使用 GCC 内联汇编):

void mov_value_to_eax()
{
    asm volatile("movl %0, %%eax"::"m"(function_parameter):"%eax");
    // will move the value of the variable function_parameter to register eax
}

我可以制作像这样的函数,可以在每个可能的寄存器上工作。我是说 -

void movl_value_to_ebx() { asm volatile("movl %0, %%ebx"::"m"(function_parameter):"%ebx"); }
void movl_value_to_ecx() { asm volatile("movl %0, %%ecx"::"m"(function_parameter):"%ecx"); }
...

以类似的方式,我可以编写将任意地址中的内存移动到特定寄存器的函数,并将特定寄存器移动到内存中的任意地址。(mov eax, [memory_address]mov [memory_address],eax)

现在,我可以随时执行这些基本指令,因此我可以创建其他指令。例如,要将一个寄存器移动到另一个寄存器:

function_parameter = 0x028FC;
mov_eax_to_memory(); // parameter is a pointer to some temporary memory address
mov_memory_to_ebx(); // same parameter

所以我可以解析一条汇编指令,并根据它决定使用哪些函数,如下所示:

if (sourceRegister == ECX) mov_ecx_to_memory();
if (sourceRegister == EAX) mov_eax_to_memory();
...
if (destRegister == EBX) mov_memory_to_ebx();
if (destRegister == EDX) mov_memory_to_edx();
...

如果它可以工作,它允许您执行任意 mov 指令。

另一种选择是制作一个要调用的函数列表,然后遍历列表并调用每个函数。也许它需要更多的技巧来制作像这样的等效指令。

所以我的问题是:是否有可能为所有(或部分)可能的操作码制作这样的东西?它可能需要编写很多函数,但是是否有可能制作一个解析器,它将基于给定的汇编指令以某种方式构建代码,然后执行它,或者那是不可能的?

编辑:您不能更改内存保护或写入可执行内存位置。

4

2 回答 2

3

我真的不清楚你为什么要问这个问题。首先,这个功能...

void mov_value_to_eax()
{
    asm volatile("movl %0, %%eax"::"m"(function_parameter):"%eax");
    // will move the value of the variable function_parameter to register eax
}

...使用 GCC 内联汇编,但函数本身不是内联的,这意味着将有序言和结尾代码包装它,这可能会影响您的预期结果。您可能想要使用 GCC 内联汇编函数(与包含 GCC 内联汇编的函数相反),这可能会让您更接近您想要的,但仍然存在问题.....

好的,假设您为每个可能的 x86 操作码(至少 GCC 汇编器知道的那些)编写了一个 GCC 内联汇编函数。现在假设您想以任意顺序调用这些函数来完成您可能希望完成的任何事情(考虑到哪些操作码在环 3(或您正在编码的任何环中)是合法执行的)。您的示例向您展示了使用 C 语句对逻辑进行编码以确定是否调用内联汇编函数。猜猜看:那些 C 语句正在使用处理器寄存器(甚至可能是 EAX!)来完成它们的任务。无论你想通过调用这些任意的内联汇编函数来做什么,都会被编译器发出的逻辑汇编代码所践踏(if (...), ETC)。反之亦然:您的内联汇编函数任意指令正在踩踏编译器发出的指令期望不会被踩踏的寄存器。结果不太可能在不崩溃的情况下运行。

如果你想用汇编编写代码,我建议你简单地用汇编编写并使用 GCC 汇编器来汇编它。或者,您可以在语句中编写整个 C 可调用汇编函数asm(),并根据需要从您的 C 代码中调用它们。但是您编写的 C 可调用汇编函数需要在您正在使用的调用约定 (ABI) 的规则内运行:如果您的汇编函数使用被调用者保存的寄存器,则您的函数需要将原始值保存在该寄存器中(一般在堆栈上),然后在返回给调用者之前恢复它。

于 2013-08-19T18:28:50.000 回答
1

...好的,根据您的评论Because if it's working it can be a way to execute code if you can't write it to memory. (the OS may prevent it)....

当然,您可以执行任意指令(只要它们对于您正在运行的任何环都是合法的)。JIT 还能如何工作?您只需要调用操作系统系统调用来设置您的指令所在的内存页面的权限......将它们更改为“可执行”,然后调用它们!

于 2013-08-19T18:32:57.047 回答