2

I want to inject a bit-flip fault into a running program. For this purpose, I'm using gdb to insert a breakpoint into the target program and then flipping a single bit in a random-selected register. When I perform this instruction under gdb in Ubuntu, I got this error when trying to manipulate $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)

I can't realize is this a bug in GDB? or a syntax error.

The error only occurs when I try to change the following registers: %eip, %esp, and %ebp. As we can see from the listing, no problem occurs when I change the content of the eax register.

More information...

In safety critical systems that work in harsh environments, the system is more likely susceptible to soft error, i.e. Single Error Upset (SEU) like bit-flip. In this context, the researchers have been developed several techniques to detect such error and keep the system reliable, i.e., Fault-tolerance Techniques. In order to evaluate such techniques, the most powerful method is fault injection. You should inject fault to the most critical parts of architecture at run-time and then monitor the hardened system to assess the fault coverage of the adopted fault-tolerance technique. Generally speaking, we should imitate soft errors using fault injection. I quite understand the eip registrar what its job is and how sensitive it is to the control flow of the program.

The version of the used GDB is like follow:

gdb --version
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.

Some output from the gdb session:

(gdb) p $eip
$1 = (void (*)()) 0x804af34 <main>

(gdb) ptype $eip
type = void (*)()
(gdb) 

In addition, when I cast the void to int, it works without any error, but the result, I think, is not sound, since I only try to toggle single bit by xoring the content of eip with 0x1 !!

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

the value of eip is 0x804af34. So, if we perform a bitwise operation with 0x1, the result should be equal to 0x804AF35 not 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) 
2
  • Can you edit your question and include the output of gdb --version? Commented Jul 3, 2020 at 1:41
  • 1
    Also, are you aware of the purpose of the eip register? It doesn't seem like what you're trying to do to it makes any sense. That said, I can't reproduce the behavior you're seeing. Commented Jul 3, 2020 at 1:58

1 Answer 1

3

You should be using (int) to coerce the pointer to an int. And in your later tests you should not be using * to de-reference the pointer; you are fetching the memory that $eip points to.

(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

Not the answer you're looking for? Browse other questions tagged .