我们如何使用GDB对寄存器进行算术运算?

我们如何使用GDB对寄存器进行算术运算?

我想将位翻转错误注入到正在运行的程序中。为此,我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) 

此外,当我将voidto转换为时int,它可以正常工作,没有任何错误,但我认为结果并不理想,因为我只尝试通过将 eip 的内容与 0x1 进行异或来切换单个位!

(gdb) set $eip=*(int *) $eip ^ 0x1
(gdb) p $eip
$2 = (void (*)()) 0x4244c8c

的值eip0x804af34。因此,如果我们执行按位运算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

相关内容