【发布时间】:2014-09-08 11:55:28
【问题描述】:
我是软件故障注入领域的新研究人员,目前我的最终目标是编写一段能够更改 CPU 寄存器中单个位的简单代码。我正在考虑在 C 中执行此操作(代码中包含一些汇编调用)。考虑到这一点,我在 Stack Overflow 中找到了这个很棒的线程和关于如何访问 32 位 CPU 寄存器内容的简单示例:Is it possible to access 32-bit registers in C? 这样,我就可以编写这个简单的代码:
#include <stdio.h>
int main()
{
register int value;
register int ecx asm("ecx");
printf("Contents of ecx: %d\n", ecx);
asm("movl %%ecx, %0;" : "=r" (value) : ); //Assembly: this stores the ecx value into the variable value
printf("Contents of value: %d\n", value);
return 0;
}
这似乎是对这个主题的一个很好的介绍,那里提供的答案给了我很好的洞察力和信息来源(我已经在阅读 GCC 文档),但现在我需要更进一步,我。例如,我需要了解如何更改 CPU 寄存器中单个位的内容(或者至少,首先要了解一些更简单的内容:如何更改 CPU 寄存器的值?)。如果有人能给我提示或告诉我寻找它的最合适的来源,我将不胜感激。
一切顺利并在此先感谢您, 若昂
P.S.:不知道这是否有帮助,但我正在使用 CentOS 6.5 32 位系统(尽管 CPU 是 64 位系统,更准确地说是 Intel Pentium Dual CPU E2180 @ 2.00 GHz)。另外,我以前接触过 Assembly,但就像 10 年前一样,在一个课程单元上呆了几个月,所以目前我正在尝试复习我对这门语言的了解。
【问题讨论】:
-
是的,大多数编译器都有将汇编程序嵌入到另一种语言中的规定,但具体如何实现取决于编译器本身。
-
我不是软件故障注入领域的研究人员,但我不得不怀疑专注于更改寄存器中的位的决定。为什么选择寄存器而不是变量?变量有可能(如果不常见)永远不会出现在寄存器中。也就是说,gcc 允许您直接访问代码中的程序集,这样您就可以轻松地踩在寄存器上(
asm("mov $0, %%eax":))。显然这种事情通常是一个非常糟糕的想法,但如果你的目标是制造错误,那么你就去吧。要踩位,请查看 i386 程序集(也许是 BTC?)。 -
我会使用
AND eax, 0xFFFE取消设置位 0,OR eax 0x01设置位 0 或XOR eax, ecx用于位翻转(ecx 包含 eax 并屏蔽了一些位)。 -
@dureuill 为什么不只用一个常数异或?顺便说一句,
and eax, 0xFFFE重置了一半以上的位。 -
我认为这不是模拟硬件故障的最佳方式。使用内联汇编将修改程序中固定位置的寄存器,而不是像您期望的硬件故障那样的随机位置。它还会对程序生成产生影响。编译器要么围绕内联程序集生成不同的计数,要么将其优化掉,因为它认为它没有效果。使用调试 API(例如 ptrace)修改另一个正在运行的程序中的寄存器应该会给您带来更像硬件故障的东西。
标签: c gcc assembly inline-assembly cpu-registers