1

我正在尝试在 C(GCC 4.6.3、x86(64 位 CPU)、Ubuntu 12.04 64 位)中进行一些汇编调用,以将寄存器值清零并设置堆栈指针,并最终调用跳转指令。

这就是我得到的:

asm("xor %eax, %eax");
asm("xor %ebx, %ebx");
asm("xor %ecx, %ecx");
asm("xor %edx, %edx");

asm("xor %cs, %cs");
asm("xor %ds, %ds");
asm("xor %es, %es");
asm("xor %fs, %fs");
asm("xor %gs, %gs");
asm("xor %ss, %ss");

asm("xor %esi, %esi");
asm("xor %edi, %edi");
asm("xor %ebp, %ebp");
asm("xor %esp, %esp");

asm("xor %cr0, %cr0");
asm("xor %cr1, %cr1");
asm("xor %cr2, %cr2");
asm("xor %cr3, %cr3");
asm("xor %cr4, %cr4");

asm("xor %cr8, %cr8");

Error: operand type mismatch for 'xor'当我尝试编译时,它表示除了前四个之外的所有寄存器。基本上,我需要将所有寄存器内容归零(不知道该怎么做)。显然有一个rdx关键重要性的登记册?但是我在网上看了一圈,找不到清单。

接下来,我需要将堆栈指针设置为特定的内存位置。我怎样才能做到这一点?

最后,我需要调用一条jump指令并转到特定的内存位置。我怎样才能做到这一点?

感谢您的任何帮助!

4

2 回答 2

3

您不能直接操作 cs,ds,es,fs,gs,ss 寄存器的值,将它们归零从 eax、ebx、ecx、edx、esi、edi、esp 等寄存器中移出一个零值:

asm("xor %eax, %eax");
asm("mov %ds, %eax");

尽管如此,如果您使用 E 前缀将二进制文件编译为 64 位,则您只能访问寄存器的低 32 位。上半部分不会归零。要编码 64 位程序集,请使用 R 前缀,例如 rax。然后,例如,如果您尝试使用自己的调用堆栈完全在汇编中创建自己的 C 风格函数并使用 32 位寄存器并以 64 位模式运行它,它会崩溃。

您绝对应该学习使用推送和弹出指令,并且应该在任何内联汇编之前备份您在 C 代码中更改的所有寄存器,然后在之后恢复它们。如果你不这样做,你的程序集会弄乱你的 C 代码,它或多或少会随机崩溃。例如:

// pack them up
asm("push %eax");
asm("push %ds");
// do something
asm("xor %eax, %eax");
asm("mov %ds, %eax");
// restore them back in opposite order (it's a stack)
asm("pop %ds");
asm("pop %eax");

看这里

接下来,您甚至不能将值移动到 CS:IP 寄存器中,但是您可以使用 jump、call 和 ret 系列指令间接修改它们的值,但是您不能在代码中这样做,因为您的代码会跳转到 (随机)(如果将地址归零,则为零)地址,它将崩溃。

有关 CS:IP 的更多信息,请参阅此链接 :在汇编语言中更改 CS:IP

于 2013-11-05T22:22:15.607 回答
2

主要问题是xor不能对段或控制寄存器进行操作。另请注意,归零控制寄存器只能在内核模式下完成,归零可能对它们没有意义。

此外,gcc inline asm 有它自己独特的语法,将这段代码写在一个单独的 asm 文件中可能是最容易的。

您应该阅读 intel 手册和 gcc 手册。

于 2013-11-05T22:23:02.297 回答