While running an ELF program with GDB, I am currently witnessing a rather unexpected behavior for a specific add instruction:
Intel syntax: add cl,BYTE PTR [eax]
AT&T syntax: add (%eax),%cl
I expect this instruction to have the same meaning as gdb's set $cl=$cl+*((char*) $eax)
(regardless of the triggered flags). But the behavior is not the same for a certain debugging session (see below): the value of (char) *$eax is 0xb8 and the value of $cl is 0, but the resulting value of $cl is 0xcc.
My question is: where does this 0xcc comes from? Why is the result not 0xb8?
Note: The program is just another crackme program from https://www.root-me.org/.
To answer Jester's comment below, the following gdb session works as expected though:
(gdb) b *0x08048119
Breakpoint 1 at 0x8048119
(gdb) r
Starting program: /tmp/ch20.bin
Welcome to Root-Me Challenges
Pass: foo
Breakpoint 1, 0x08048119 in ?? ()
(gdb) x/i $eip
=> 0x8048119: add (%eax),%cl
(gdb) x/bx $eax
0x8048080: 0xb8
(gdb) p/x $cl
$1 = 0x0
(gdb) si
0x0804811b in ?? ()
(gdb) p/x $cl
$2 = 0xb8
But I don't understand why the following one does not give the same result:
(gdb) b *0x8048080
Breakpoint 1 at 0x8048080
(gdb) r
Starting program: /home/baz1/Downloads/ch20.bin
Breakpoint 1, 0x08048080 in ?? ()
(gdb) ni
0x08048085 in ?? ()
(gdb)
0x0804808a in ?? ()
(gdb)
0x0804808f in ?? ()
(gdb)
0x08048094 in ?? ()
(gdb)
Welcome to Root-Me Challenges
Pass: 0x08048096 in ?? ()
(gdb)
0x0804809b in ?? ()
(gdb)
0x0804809d in ?? ()
(gdb)
0x080480a2 in ?? ()
(gdb)
0x080480a7 in ?? ()
(gdb)
0x080480a9 in ?? ()
(gdb)
0x080480ab in ?? ()
(gdb)
0x080480b0 in ?? ()
(gdb)
0x080480b5 in ?? ()
(gdb)
0x08048115 in ?? ()
(gdb)
0x08048117 in ?? ()
(gdb)
0x08048119 in ?? ()
(gdb) x/i $eip
=> 0x8048119: add (%eax),%cl
(gdb) x/bx $eax
0x8048080: 0xb8
(gdb) p/x $cl
$1 = 0x0
(gdb) si
0x0804811b in ?? ()
(gdb) p/x $cl
$2 = 0xcc
Thank you very much for your help.
The b *0x8048080
places a software breakpoint into memory which happens to be the int3
instruction with opcode 0xcc
. The add
instruction will then read this instead of the original memory content. You can delete the breakpoint after it got hit or use hardware breakpoints that don't modify the code.