我想将位翻转错误注入到正在运行的程序中。为此,我gdb
在目标程序中插入一个断点,然后翻转随机选择的寄存器中的单个位。当我在 Ubuntu 下执行此指令时gdb
,尝试操作时出现此错误$eip
:
(gdb) info r
...
eip 0x804af59 0x804af59 <main+37>
...
(gdb) p/a $eip
$4 = 0x804af59 <main+37>
(gdb) set $eip = $eip ^ 0x800
argument to arithmetic operation not a number or boolean
(gdb) set $eax = $eax ^ 0x1
(gdb)
我不明白这是 GDB 中的错误吗?或语法错误。
仅当我尝试更改以下寄存器时才会发生该错误:%eip
、%esp
和%ebp
。从清单中我们可以看到,当我更改寄存器的内容时没有出现问题eax
。
更多信息...
在恶劣环境下工作的安全关键系统中,系统更容易受到软错误的影响,即单错误翻转(东南大学)就像位翻转一样。在此背景下,研究人员开发了多种技术来检测此类错误并保持系统可靠,即容错技术。为了评估此类技术,最有效的方法是故障注入。您应该在运行时将故障注入架构中最关键的部分,然后监视强化系统以评估所采用的容错技术的故障覆盖率。一般来说,我们应该使用故障注入来模拟软错误。我非常了解eip
注册商的工作是什么以及它对程序的控制流程有多敏感。
使用的GDB版本如下:
gdb --version
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
gdb 会话的一些输出:
(gdb) p $eip
$1 = (void (*)()) 0x804af34 <main>
(gdb) ptype $eip
type = void (*)()
(gdb)
此外,当我将void
to转换为时int
,它可以正常工作,没有任何错误,但我认为结果并不理想,因为我只尝试通过将 eip 的内容与 0x1 进行异或来切换单个位!
(gdb) set $eip=*(int *) $eip ^ 0x1
(gdb) p $eip
$2 = (void (*)()) 0x4244c8c
的值eip
是0x804af34。因此,如果我们执行按位运算0x1,结果应该等于0x804AF35不是0x4244c8c?!
(gdb) p $eip
$8 = (void (*)()) 0x804af34 <main>
(gdb) p *(int *) ($eip)
$9 = 69487757
(gdb) p *(int *) $eip ^0x1
$10 = 69487756
(gdb) p/a *(int *) $eip ^0x1
$11 = 0x4244c8c
(gdb)
答案1
您应该使用(int)
强制指针指向 int。在你以后的测试中你应该不是用于*
取消引用指针;你正在获取$eip
指向的内存。
(gdb) p/x (int)$eip
$4 = 0xf7eb9810
(gdb) p/x (int)$eip^1
$5 = 0xf7eb9811
(gdb) set $eip = (int)$eip^1
(gdb) p/x (int)$eip
$6 = 0xf7eb9811
(gdb) set $eip = (int)$eip^0x800
(gdb) p/x (int)$eip
$7 = 0xf7eb9011