Assembly Debugging with gdb

Introduction

Over the last couple of months I’ve spent quite a lot of time in gdb whilst working through the SLAE certification exam assignments. The question I had was how I could become more efficient when working in gdb? I wanted to have easier access to the register values and generally save myself time whilst debugging or analysing shellcode written in nasm assembly. I’ve been running gdb on an Ubuntu 16.04 LTS 32-bit system.

Disabling the Copyright Message on startup

I know this isn’t really a big deal but I wanted to be able to disable the copyright message when gdb started. I know you can use the ‘-q’ argument each time gdb is started but again that just seems like extra effort that isn’t really necessary. The solution I found was to add an command alias within the bash configuration file. The bash configuration file is located in the users’s home directory and called .bashrc.

  • Open a terminal session and ensure it is in the home directory by entering
cd ~/
  • Use vim to open the bash configuration file:
vim .bashrc
  • Scroll to the ‘Alias definitions’ section. Add the following line:
alias gdb='gdb -q'
  • Save the file and exit vim by pressing ‘escape’ and then typing
:wq
  • For the settings to apply either close the terminal session or use the following command:
source ~/.bashrc

What I’ve done is setup an alias so that when gdb is types the actual command that is executed is ‘gdb -q’. Aliases can be used for lots of things, for example if you use multiple versions of python installed and want to set the version which will start when ‘python’ is typed then just add an alias.

User-Defined Commands

The first thing I found was that I was editing the assembly source file a lot and recompiling which meant I was restarting gdb a lot. So I started looking into what I could do to save myself repeating the same tasks over and over. It turns out that gdb has a configuration file called ‘.gdbinit’ that can be to setup how it will run. The file is located in the folder which holds the executable being debugged or in the users home folder. Where this really comes into it’s own is it provides the ability to create user-defined commands. The current user defined commands  can be listed by running gdb and typing:

help user-defined

Saving and loading Break Points to a file

I wanted to be able to save the breakpoints I was setting up and this can easily be done be creating a user-defined command. The definition below is in two parts.

  • Define the command – ‘define bsave
  • Document the command usage – document bsave
# Save breakpoints to a file
define bsave
    save breakpoints .breakpoint
end
document bsave
Saves all current defined breakpoints to the file .breakpoint in the PWD
Usage: bsave
end

Using the user-define commands

  • To run the command the name is simply entered into gdb
  • The document about how to use the command is displayed by typing help bsave

Now we can create a couple of other commands

  • bload: loads breakpoints from the file .breakpoint
  • bsavef: Saves breakpoints to the specified file
  • bloadf: Loads breakpoints from the specified files
# Restore breakpoints from a file
define bload
    source .breakpoint
end
document bload
Loads all breakpoints from the file .breakpoint in the PWD
Usage: bload
end


# Save breakpoints to a defined file
define bsavef
    if $argc != 1
        help bsave
    else
        save breakpoints $arg0
    end
end
document bsavef
Saves all current defined breakpoints to the defined file in the PWD
Usage: bsavef 
end


# Restore breakpoints from a defined file
define bloadf
    if $argc != 1
        help bloadf
    else
        source $arg0
    end
end
document bloadf
Loads all breakpoints from the defined file in the PWD
Usage: bloadf 
end

Using gdb to debug Assembly

Whilst I was searching for information on how to configure gdb I found the following .gdbinit file

https://gist.github.com/CocoaBeans/1879270

It contains a lot of user-defined commands and other configuration to optimise gdb. Interestingly it doesn’t include user-defined commands to save and load breakpoints to and from a file, so I added the commands above to this file.

I can only thank the author of this file as it is absolutely superb. It includes so much functionality that I’m not going to the whole file as this would take a very long time. Here a couple of examples of

When a program stops at a breakpoint gdb automatically displays the register values, flags and 8 lines of disassembled code:

gdb-debugging

I found this incredibly useful, not only does it display all the information it’s nicely formatted and flag values will capitalise when they are set, in the screenshot above none of the flag values are set.

gdb-debugging-2

It also tells you when a jump will or won’t be taken. Also, it can be seen in the example above the ‘I’ flag is set.

Sometime I’ve been looking at values on the stack or trying to workout why something isn’t working and the information in the screenshot above was now way up the terminal and finding it is going to take a bit of time. No problem just type ‘context’ and it will be displayed.

The vast majority of the configuration included within the .gdbinit file are user-define commands, so as mentioned earlier to find out what it includes just download the file, put it the home folder, start gdb and type help user-defined

List of commands from the version I was using 7.3 with my additional commands from above:

List of commands:

32bits -- Set gdb to work with 32bits binaries
64bits -- Set gdb to work with 64bits binaries
argv -- Print program arguments
ascii_char -- Print ASCII value of byte at address ADDR
assemble -- Assemble instructions using nasm
assemble_gas -- Assemble instructions to binary opcodes
bhb -- Set hardware assisted breakpoint
bload -- Loads all breakpoints from the file .breakpoint in the PWD
bloadf -- Loads all breakpoints from the defined file in the PWD
bp -- Set breakpoint
bpc -- Clear breakpoint
bpd -- Disable breakpoint with number NUM
bpe -- Enable breakpoint with number NUM
bpl -- List all breakpoints
bpm -- Set a read/write breakpoint on EXPRESSION
bpt -- Set a temporary breakpoint
bsave -- Saves all current defined breakpoints to the file .breakpoint in the PWD
bsavef -- Saves all current defined breakpoints to the defined file in the PWD
cfa -- Change Auxiliary Carry Flag
cfc -- Change Carry Flag
cfd -- Change Direction Flag
cfi -- Change Interrupt Flag
cfo -- Change Overflow Flag
cfp -- Change Parity Flag
cfs -- Change Sign Flag
cft -- Change Trap Flag
cfz -- Change Zero Flag
cls -- Clear screen
context -- Print context window
context-off -- Disable display of context on every program break
context-on -- Enable display of context on every program break
contextsize-code -- Set code window size to NUM lines
contextsize-data -- Set data dump window size to NUM lines
contextsize-stack -- Set stack dump window size to NUM lines
datawin -- Display valid address from one register in data window
dd -- Display 16 lines of a hex dump of address starting at ADDR
ddump -- Display NUM lines of hexdump for address in $data_addr global variable
dis -- Disassemble a specified section of memory
disablecpuregisters -- Disable display of cpu registers in the context window
disabledatawin -- Disable display of data window in the context window
disableobjectivec -- Disable display of objective-c information in the context window
disablesolib -- Shortcut to disable stop-on-solib-events trick!
disablestack -- Disable display of stack information in the context window
dump_binfile -- Write a range of memory to a binary file
dump_hexfile -- Write a range of memory to a file in Intel ihex (hexdump) format
dumpjump -- Display if conditional jump will be taken or not
eflags -- Print eflags register
enablecpuregisters -- Enable display of cpu registers in the context window
enabledatawin -- Enable display of data window in the context window
enableobjectivec -- Enable display of objective-c information in the context window
enablesolib -- Shortcut to enable stop-on-solib-events trick!
enablestack -- Enable display of stack in the context window
flags -- Print flags register
frame -- Print stack frame
func -- Print all function names in target
get_insn_type -- Recognize instruction type at address ADDR
go -- Step one instruction exactly
hex_quad -- Print eight hexadecimal bytes starting at address ADDR
hexdump -- Display a 16-byte hex/ASCII dump of memory at address ADDR
hook-stop -- !!! FOR INTERNAL USE ONLY - DO NOT CALL !!!
init -- Run program and break on _init()
int3 -- Patch byte at address ADDR to an INT3 (0xCC) instruction
lib -- Print shared libraries linked to target
main -- Run program and break on main()
n -- Step one instruction
nop -- Usage: nop ADDR1 [ADDR2]
null -- Usage: null ADDR1 [ADDR2]
pret -- Execute until selected stack frame returns (step out of current call)
print_insn_type -- Print human-readable mnemonic for the instruction type (usually $INSN_TYPE)
reg -- Print CPU registers
sig -- Print what debugger does when program gets various signals
smallregisters -- Create the 16 and 8 bit cpu registers (gdb doesn't have them by default)
sstart -- Run program and break on __libc_start_main()
stack -- Print backtrace of the call stack
start -- Run program and break on _start()
step_to_call -- Single step until a call instruction is found
stepo -- Step over calls (interesting to bypass the ones to msgSend)
threads -- Print threads in target
tip_display -- Tips on automatically displaying values when a program stops
tip_patch -- Tips on patching memory and binary files
tip_strip -- Tips on dealing with stripped binaries
tip_syntax -- Summary of Intel and AT&T syntax differences
tips -- Provide a list of tips from users on various topics
trace_calls -- Create a runtime trace of the calls made by target
trace_run -- Create a runtime trace of target
var -- Print all global and static variable names (symbols)

I hope this is useful and might save some time when using gdb.

Advertisements
This entry was posted in SLAE and tagged , , , , . Bookmark the permalink.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s