Reviewing Debugging with gdb

EditAs you may have noticed, I’m preparing to become an OSCP. In addition to brushing up on assembly, I’ll also be stepping through the debugger.

Let’s review gdb and go over some tips to make sure the course work becomes smooth sailing. This is primarily an introduction to general use of gdb, but there are a few tips and tricks as well.

Introducing gdb

Installing gdb

BackTrack doesn’t come with gdb; I don’t understand why, but it’s a Debian distro, so this will install it:

# apt-get install gdb

Loading a program into gdb

# gdb ./VariableDemo

Debugging symbols

While plenty of gdb features will work on any executable, many of the really useful features require that the executable was assembled with debugging symbols enabled.

A note about 32-bit vs 64-bit

My machine is 64-bit so the example output displayed here is all 64-bit. You’ll notice that the registers are %rax, %rbx, etc. instead of %eax, %ebx, etc. This is because the registers are 64-bit instead of 32-bit, but is generally unimportant in regards to the examples.

Example assembly program

The examples shown here were produced using the following assembly language program:

# Demo program using variables in assembly

.data

	HelloWorld:
		.ascii "Hello World!"

	ByteLocation:
		.byte 10

	Int32:
		.int 2
	Int16:
		.short 3
	Float:
		.float 10.23

	IntegerArray:
		.int 10,20,30,40,50

.bss
		.comm LargeBuffer, 10000

.text

	.globl _start

	_start:
		nop

		# call exit(0)
		movl $1, %eax
		movl $0, %ebx
		int $0x80

Listing the program code

From the current position in the source file (context of what is being executed)

At the (gdb) command prompt:

list

If the program is not running, this will list the first 10 lines of code. If the program is running, this will list the 10 lines surrounding the last line that was executed (in other words, you will see the context in which the program is executing at that time). This is useful when you’re stepping through a program. Press [enter] to continue perusing the next 10 lines of code.

Example

(gdb) list
1	# Demo program using variables in assembly
2
3	.data
4
5		HelloWorld:
6			.ascii "Hello World!"
7
8		ByteLocation:
9			.byte 10
10

A specific line

At the (gdb) command prompt:

list 20

This will list the 10 lines of code surrounding line 20. In other words, you will see lines 15 through 24. Press [enter] to continue perusing the next 10 lines of code.

Example

(gdb) list 20
15		Float:
16			.float 10.23
17
18		IntegerArray:
19			.int 10,20,30,40,50
20
21	.bss
22			.comm LargeBuffer, 10000
23
24	.text

Setting a break point

By line number

At the (gdb) command prompt:

break 10

Example

(gdb) break 10
Breakpoint 1 at 0x4000b0: file VariableDemo.s, line 10.

This will set a break point at line 10.

By function name

At the (gdb) command prompt:

break *_start+1

This will set a break point at the first line of the _start function. The asterisk followed by the method name tells gdb that we are referring to the memory location of that method.

Example

(gdb) break *_start+1
Breakpoint 1 at 0x4000b1: file VariableDemo.s, line 32.

Running the program

At the (gdb) command prompt:

run

The program will execute until it hits a breakpoint, an input operation, an error, or until the program exits.

Example

(gdb) run
Starting program: /root/assembly/VariableDemo 

Breakpoint 1, _start () at VariableDemo.s:32
32			movl $1, %eax

Stepping through the program

At the (gdb) command prompt:

step

The program will execute until it reaches the next source line; the next source line will also be displayed on screen. If you step again the source line displayed on screen will execute. You can also just use s for short instead of step.

Example

(gdb) step
33			movl $0, %ebx

Continuing execution after a breakpoint

At the (gdb) command prompt:

continue

The program will continue executing until it reaches a breakpoint, an input operation, an error, or until the program exits. You can also just use c for short instead of continue.

Example

(gdb) continue
Continuing.

Program exited normally.

Listing variables

At the (gdb) command prompt:

info variables

Print the variables defined by the program.

Example

(gdb) info variables
All defined variables:

Non-debugging symbols:
0x00000000006000c0  HelloWorld
0x00000000006000cc  ByteLocation
0x00000000006000cd  Int32
0x00000000006000d1  Int16
0x00000000006000d3  Float
0x00000000006000d7  IntegerArray
0x00000000006000f0  LargeBuffer

Listing registers

At the (gdb) command prompt:

info registers

Print the registers defined by the program.

Example

(gdb) info registers
rax            0x0	0
rbx            0x0	0
rcx            0x0	0
rdx            0x0	0
rsi            0x0	0
rdi            0x0	0
rbp            0x0	0x0
rsp            0x7fffffffe4b0	0x7fffffffe4b0
r8             0x0	0
r9             0x0	0
r10            0x0	0
r11            0x200	512
r12            0x0	0
r13            0x0	0
r14            0x0	0
r15            0x0	0
rip            0x4000b1	0x4000b1 <_start+1>
eflags         0x202	[ IF ]
cs             0x33	51
ss             0x2b	43
ds             0x0	0
es             0x0	0
fs             0x0	0
gs             0x0	0

Understanding how to examine memory

When examining memory locations you use the x command. The x command requires the format to print the data and the location of the data to print.

At the (gdb) command prompt:

x/FMT ADDRESS

The format includes the data size, data type, and number of objects to print.

Valid Data Types

o(octal)
x(hex)
d(decimal)
u(unsigned decimal)
t(binary)
f(float)
a(address)
i(instruction)
c(char)
s(string)

Valid Data Sizes

b(byte)
h(halfword, 2 bytes, int16)
w(word, 4 bytes, int32)
g(giant, 8 bytes, int64)

Examining memory

By memory location

At the (gdb) command prompt:

x/12cb 0x00000000006000c0

Examine the 12 bytes at memory location 0x00000000006000c0. Print the bytes as characters.

Example

(gdb) x/12cb 0x00000000006000c0
0x6000c0 :	72 'H'	101 'e'	108 'l'	108 'l'	111 'o'	32 ' '	87 'W'	111 'o'
0x6000c8 :	114 'r'	108 'l'	100 'd'	33 '!'

By label name

At the (gdb) command prompt:

x/5dw &IntegerArray

Examine the 5 words at the memory location of label IntegerArray. Print the words as decimals (ints).

Example

(gdb) x/5dw &IntegerArray
0x6000d7 :	10	20	30	40
0x6000e7 :	50

Getting help

At the (gdb) command prompt:

help x

If you forgot how to examine memory, this would return helpful information for the x

Example

(gdb) help x
Examine memory: x/FMT ADDRESS.
ADDRESS is an expression for the memory address to examine.
FMT is a repeat count followed by a format letter and a size letter.
Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),
  t(binary), f(float), a(address), i(instruction), c(char) and s(string).
Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).
The specified number of objects of the specified size are printed
according to the format.

Defaults for format and size letters are those previously used.
Default count is 1.  Default address is following last thing printed
with this command or "print".

More to Come

That’s it for the basics of gdb. As I continue to pick up tips I’ll cover more topics, so expect to see more soon!