SHARE:

x86_64 rflags and understanding a strcmp statement in gdb

Spread the love

So here recently I have been playing around with the GNU debugger (gdb). The best way that I have found to understand things is to create simple programs and see where they take you. So I have created the following piece of code to understand how I can bypass execution streams.

#include <stdio.h>

void main()
{

  char* p = "This is a test";
  if (strcmp("This is not a test", p) == 0)
  {
    printf("The strings are the same... I think\n");
  }
  printf("Exited normally\n");
  exit(0);
}

As you can see the code above, the condition to print out “The strings are the same… I think\n” should never occur under normal operation. However we can make it work using gdb.

Lets begin by compiling the code with GNU debug symbols. 

# Compile by issuing the following.

gcc -ggdb gdb_example01.c -o gdb_example01

Now follow the below to see how it is done.

ubuntu@ip-172-31-90-44:~$ gdb gdb_example01
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from gdb_example01...done.
(gdb) list
1	#include <stdio.h>
2
3	void main()
4	{
5
6		char* p = "This is a test";
7		if (strcmp("This is not a test", p) == 0)
8		{
9			printf("The strings are the same... I think\n");
10		}
(gdb) break 7
Breakpoint 1 at 0x4005c6: file gdb_example01.c, line 7.
(gdb) run
Starting program: /home/ubuntu/gdb_example01

Breakpoint 1, main () at gdb_example01.c:7
7		if (strcmp("This is not a test", p) == 0)
(gdb) info registers
rax            0x4005b6	4195766
rbx            0x0	0
rcx            0x0	0
rdx            0x7fffffffe5b8	140737488348600
rsi            0x7fffffffe5a8	140737488348584
rdi            0x1	1
rbp            0x7fffffffe4c0	0x7fffffffe4c0
rsp            0x7fffffffe4b0	0x7fffffffe4b0
r8             0x400670	4195952
r9             0x7ffff7de7ab0	140737351940784
r10            0x846	2118
r11            0x7ffff7a2d740	140737348032320
r12            0x4004c0	4195520
r13            0x7fffffffe5a0	140737488348576
r14            0x0	0
r15            0x0	0
rip            0x4005c6	0x4005c6 <main+16>
eflags         0x202	[ IF ]
cs             0x33	51
ss             0x2b	43
ds             0x0	0
es             0x0	0
fs             0x0	0
gs             0x0	0
(gdb) disassemble
Dump of assembler code for function main:
   0x00000000004005b6 <+0>:	push   %rbp
   0x00000000004005b7 <+1>:	mov    %rsp,%rbp
   0x00000000004005ba <+4>:	sub    $0x10,%rsp
   0x00000000004005be <+8>:	movq   $0x400688,-0x8(%rbp)
=> 0x00000000004005c6 <+16>:	mov    -0x8(%rbp),%rax
   0x00000000004005ca <+20>:	mov    %rax,%rsi
   0x00000000004005cd <+23>:	mov    $0x400697,%edi
   0x00000000004005d2 <+28>:	callq  0x400490 <strcmp@plt>
   0x00000000004005d7 <+33>:	test   %eax,%eax
   0x00000000004005d9 <+35>:	jne    0x4005e5 <main+47>
   0x00000000004005db <+37>:	mov    $0x4006b0,%edi
   0x00000000004005e0 <+42>:	callq  0x400470 <puts@plt>
   0x00000000004005e5 <+47>:	mov    $0x4006d4,%edi
   0x00000000004005ea <+52>:	callq  0x400470 <puts@plt>
   0x00000000004005ef <+57>:	mov    $0x0,%edi
   0x00000000004005f4 <+62>:	callq  0x4004a0 <exit@plt>
End of assembler dump.
(gdb) stepi
0x00000000004005ca	7		if (strcmp("This is not a test", p) == 0)
(gdb) stepi
0x00000000004005cd	7		if (strcmp("This is not a test", p) == 0)
(gdb) stepi
0x00000000004005d2	7		if (strcmp("This is not a test", p) == 0)
(gdb) disassemble
Dump of assembler code for function main:
   0x00000000004005b6 <+0>:	push   %rbp
   0x00000000004005b7 <+1>:	mov    %rsp,%rbp
   0x00000000004005ba <+4>:	sub    $0x10,%rsp
   0x00000000004005be <+8>:	movq   $0x400688,-0x8(%rbp)
   0x00000000004005c6 <+16>:	mov    -0x8(%rbp),%rax
   0x00000000004005ca <+20>:	mov    %rax,%rsi
   0x00000000004005cd <+23>:	mov    $0x400697,%edi
=> 0x00000000004005d2 <+28>:	callq  0x400490 <strcmp@plt>
   0x00000000004005d7 <+33>:	test   %eax,%eax
   0x00000000004005d9 <+35>:	jne    0x4005e5 <main+47>
   0x00000000004005db <+37>:	mov    $0x4006b0,%edi
   0x00000000004005e0 <+42>:	callq  0x400470 <puts@plt>
   0x00000000004005e5 <+47>:	mov    $0x4006d4,%edi
   0x00000000004005ea <+52>:	callq  0x400470 <puts@plt>
   0x00000000004005ef <+57>:	mov    $0x0,%edi
   0x00000000004005f4 <+62>:	callq  0x4004a0 <exit@plt>
End of assembler dump.
(gdb) nexti
0x00000000004005d7	7		if (strcmp("This is not a test", p) == 0)
(gdb) stepi
0x00000000004005d9	7		if (strcmp("This is not a test", p) == 0)
(gdb) info registers
rax            0xd	13
rbx            0x0	0
rcx            0x0	0
rdx            0x61	97
rsi            0x400688	4195976
rdi            0x400697	4195991
rbp            0x7fffffffe4c0	0x7fffffffe4c0
rsp            0x7fffffffe4b0	0x7fffffffe4b0
r8             0x400670	4195952
r9             0x7ffff7de7ab0	140737351940784
r10            0x838	2104
r11            0x7ffff7aac570	140737348552048
r12            0x4004c0	4195520
r13            0x7fffffffe5a0	140737488348576
r14            0x0	0
r15            0x0	0
rip            0x4005d9	0x4005d9 <main+35>
eflags         0x202	[ IF ]
cs             0x33	51
ss             0x2b	43
ds             0x0	0
es             0x0	0
fs             0x0	0
gs             0x0	0
(gdb) set $eflags = 0x242
(gdb) info registers
rax            0xd	13
rbx            0x0	0
rcx            0x0	0
rdx            0x61	97
rsi            0x400688	4195976
rdi            0x400697	4195991
rbp            0x7fffffffe4c0	0x7fffffffe4c0
rsp            0x7fffffffe4b0	0x7fffffffe4b0
r8             0x400670	4195952
r9             0x7ffff7de7ab0	140737351940784
r10            0x838	2104
r11            0x7ffff7aac570	140737348552048
r12            0x4004c0	4195520
r13            0x7fffffffe5a0	140737488348576
r14            0x0	0
r15            0x0	0
rip            0x4005d9	0x4005d9 <main+35>
eflags         0x242	[ ZF IF ]
cs             0x33	51
ss             0x2b	43
ds             0x0	0
es             0x0	0
fs             0x0	0
gs             0x0	0
(gdb) c
Continuing.
The strings are the same... I think
Exited normally
[Inferior 1 (process 1644) exited normally]
(gdb) quit

The links that were most helpful:

  1. eflags  ## This link shows you how to set the bits in eflags
  2. bin<->hex converter   ## This link will help you know what to set.
  3. Stackoverflow   ## This particular article helped me understand that the two commands set rflags.

 

Written by

gseeto

Technology, Science and Philosophy