gdb
gdb copied to clipboard
gdb cheat sheet
GDB
- Getting started
- Set
- Show
- eXamine
- Breakpoints
- Watchpoints
- Stepping
- Loop
- Structs
- Buffers
- Buffer filling
- Understanding where you are
- Registers
- Stack
- Memory
- Rat Holes
- Shell
- Cool commands
Getting started
Install the gef extension
https://gef.readthedocs.io/en/master/#setup
gdb version
show version
From command line
gdb my_app
From command line with some A's
gdb --args format_zero AAAA
From command line with lots of A's
gdb --args format_zero $(python -c 'print "A"*10')
Attach after gdb opened to process ID
attach pid
After gdb opened, load file ( symbol table )
file format_zero
Run file
run
Disassemble
disas start_level
Disassemble main from command line, with gdb
gdb -batch -ex 'file format_one' -ex 'disassemble main'
Disassemble and look for compare instructions
gdb -batch -ex 'file format_one' -ex 'disassemble main' | grep -i cmp
Set
Integer
set $foo = 3
String
set $str = "hello world"
Instruction flavor
set disassembly-flavor intel
Environment variable (LD_PRELOAD)
set environment LD_PRELOAD=./mylib.so
Environment variable ( PATH )
set env PATH=``perl -e 'print "A" x 65'
Set environment variable
python gdb.execute("set environment payload=%x%x%x%x")
Show
Show env payload
show env payload
All environment variables
show environment
All one env variable
show environment PATH
gef➤ print &changeme
$2 = (int *) 0x601050 <changeme>
gef➤ print changeme
$3 = 0xff
gef➤ print "foobar"
$1 = "foobar"
gef➤ print $1
$2 = "foobar"
(gdb) p/x $foo
$1 = 0x3
(gdb) p $foo
$2 = 3
(gdb) p 5+5
$5 = 0xa
p/d 0xffffd59c - 0xffffd560
$35 = 60
p/tz $eip // print leading zeroes
$4 = 0x08049201
gef➤ x/s $esp
0xffffd570: "AAAA"
gef➤ p $esp
$1 = (void *) 0xffffd570
gef➤ p (char *) $esp
$2 = 0xffffd570 "AAAA"
(gdb) p $bar = "hello"
$3 = "hello"
(gdb) p/x $bar
$4 = {0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0}
(gdb) p $bar
$5 = "hello"
eXamine
Print stack
x/24wx $esp
Print bytes 4 bytes x 9 addresses starting at 0x6c00
x/9wx 0x6c00
Print 256 individual bytes from address 350
x/256bx 0x350
Print 4-bytes 32 times from address 0x6c00
x/32wx 0x6c00
Print data at memory address as Int
x/d 0x7ffe76d25c50
Print data at memory address as Hex
x/x 0x7ffe76d25c50
Current instruction
x/i $pc
Current next two instructions
x/2i $pc
Current 6 instructions from last instruction ( 113 - 108 = 5)
x/6i $pc-5
0x4006b3 <main+108>: call 0x400540 <sprintf@plt>
=> 0x4006b8 <main+113>: mov eax,DWORD PTR [rbp-0x10]
0x4006bb <main+116>: test eax,eax
0x4006bd <main+118>: je 0x4006cd <main+134>
0x4006bf <main+120>: lea rdi,[rip+0x102] # 0x4007c8
0x4006c6 <main+127>: call 0x400510 <puts@plt>
Breakpoints
Help
help breakpoints
Break on symbol name
b atoi
Breakpoint list
info breakpoints
Disable all
disable breakpoints
Delete breakpoint at current instruction
clear
Delete breakpoint 2
del br 2
Delete breakpoints
delete breakpoints 1-8
Delete ALL breakpoints
d br
Break on address
b *0x04006b3
Break on start of function + 24
b *start_level + 24
Disassemble. Then break after interesting call
br *main + 113
Break on mangled name
b _ZN8password11checkLengthEi
Break if Register ( Second Argument: RSI ) set to 6
break if $rsi = 0x38
break if
break passwordcheck if 0 == 0
Run debugger commands on Breakpoint 1
command 1
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>print "fluffy foobar"
>end
Watchpoints
Watch memory of stack variables ( no debug symbols )
memory watch 0x7ffca5211480+0x28 8 qword
Hardware watchpoint - with debug symbols - char buffer
watch *(char(*)[32])(locals.dest)
Hardware watchpoint - with debug symbols - int
watch *(int)(locals.changeme)
Stepping
nexti 3 /* run next 3 instructions */
finish /* continue execution of current function and then stop */
Loop
set $loop = 5
while $loop > 0
>output "$loop is "
>output $loop
>echo \n
>set $loop = $loop - 1
>end
"$loop is "0x5
"$loop is "0x4
"$loop is "0x3
"$loop is "0x2
"$loop is "0x1
Malloc
gef> p (int)malloc(6)
$7 = 0xb7ffd020
Structs
(gdb) ptype /o struct locals
Buffers
Find size of buffer ( memset )
disassemble main
and find useful apis
. For example, if memset
is called:
void *memset(void *b, int c, size_t len);
If you break on the memset
call, you find two useful things; the address of buffer
and the length
of the buffer.
memset@plt (
$rdi = 0x00007fffffffe440 → 0x0000000000000000,
$rsi = 0x0000000000000000,
$rdx = 0x0000000000000100,
$rcx = 0x00007ffff7af4154 → 0x5477fffff0003d48 ("H="?)
)
The third value, the buffer length is represented in hex. You can see the buffer
is 256
chars long.
gef➤ p/d 0x100
$4 = 256
Find size of buffer ( strncpy )
The second API call is strncpy
. This is less famous than strcpy
. The latter doesn't have the strncpy's len
argument to mitigate buffer overflows:
char * strncpy(char * dst, const char * src, size_t len);
If we break on strncpy
. It was passed:
strncpy@plt (
$rdi = 0x00007fffffffe440 → 0x0000000000000000,
$rsi = 0x00007fffffffe851 → "%256xAAAAAAAAAAAAAAAA",
$rdx = 0x0000000000000100 <-- 256 char buffer
)
That re-confirms the address of the buffer and it's length of 256
characters.
Target register
0x00007fffffffe440
Watch buffer
memory watch p/x 0x00007fffffffe440 10 qword
Print each byte
x/256bx 0x00007fffffffe440
Print only the buffer
x/64wx 0x00007fffffffe440
Buffer filling
argv[1]
Prepare input outside of debugger ( and reverse bytes )
python -c 'print "\x08\x04\xa0\x30"[::-1] + "%p"*14 + "%n"' > change_me_bytes.hex
Check the bytes
# xxd change_me_bytes.hex
00000000: 30a0 0408 2570 2570 2570 2570 2570 2570 0...%p%p%p%p%p%p
00000010: 2570 2570 2570 2570 2570 2570 2570 2570 %p%p%p%p%p%p%p%p
00000020: 256e 0a %n.
Inside of gdb
run $(cat change_me_bytes.hex)
Overfill a buffer with gets() or strcpy() or Environment Variable
$ python -c 'print "A"*(80) + "\x44\x05\x01\x00"' | ./stack-four
$ cat ~/128chars | ./stack-five
Works with sprintf() or gets()
# python -c 'print "%p"*10' > payload.txt
# gdb format_zero
r < ~/payload.txt
inside gdb. Passing in arguments values ( for scanf
, strcpy
etc )
r payload.txt
run $(python -c 'print "A" * 20')
run $(python -c 'print "%268x" + "\x41\x41\x41\x41"')
run `printf "\x54\x10\x60"`%.fx%4\$hn%.ex%5\$hn
run $(echo -e "\x54\x10\x60\x00%x%x%x%x%x%x%x%x%x%x%x%n.")
Troubleshooting python3 buffer filling
When you hit a non-readable ASCII character. Reference here.
Understanding where you are
main info sec
whatis
gef> whatis 0x000106d8
type = int
[961d8f92]: https://stackoverflow.com/questions/42884251/why-is-the-output-of-print-in-python2-and-python3-different-with-the-same-string "python3_byte_str"
gef> whatis "hello"
type = char [6]
Shared Libraries
info sharedlibrary
Locations of system calls
gef> x/x strcpy
0xffffb7f72050 <strcpy>: 0xf3
gef> x/x system
0xffffb7f9fee4 <system>: 0xff
gef> x/x printf
0xffffb7faafa4 <printf>: 0xff
Set and Print Variable
gef> p getenv ("PATH")
'getenv' has unknown return type; cast the call to its declared return type
gef> p (char *) getenv ("PATH")
$8 = 0xffffffffffa2 "/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games"
// https://sourceware.org/gdb/onlinedocs/gdb/Calling.html
(gdb) p ((char * (*) (const char *)) getenv) ("PATH")
gef> set env FooBarEnvVariables=`perl -e 'print "A" x 65'`
gef> x/s *((char **)environ)
0xfffefed4: "LS_COLORS="
Registers
reg
info registers
Stack
Get stack size
set $stack_size = $rbp - $rsp
# 272
Calculate max overflow
p/d $stack_size -256
# 16
Print stack
x/272wx $rsp
Memory
gef> x/100wx $sp-200 // check overflowed Stack
gef> x/24x $sp // read hex address from Stack pointer
gef> x/2w $sp <--- print from stack pointer
0xfffefd00: 0xfffefd84 0x00000001 0x00000011 0xf77f0288
gef> x/wx 0xfffefd84 <--- print memory address
0xfffefd84: 0xfffefe8e
gef> x/s 0xfffefe8e <-- string
0xfffefe8e: "/opt/phoenix/arm/stack-two"
gef> find $sp, +96,0x000105bc // find Return address on Stack
0xfffefd64
1 pattern found.
Calculate Sizes
gef> p 0xfffefd74 - 0xfffefd20
$9 = 0x54
gef> p/u 0x54
$10 = 84
gef> p/u 0xfffefd74 - 0xfffefd20
$11 = 84
Rat Holes
Careful not to mix frames!
When debugging, it is important to be aware of what frame you are in. I created a rat hole by mixing frames. This is how I went down the rat hole:
I was running in the main frame
:
p/x $rbp - 0x100
$5 = 0x7fffffffe410
I then used the same shortcut. But I was inside another frame
:
p/x $rbp - 0x100
0x7fffffffe300
Special characters
Any of the following characters in a memory address could cause a C API to choke when it tried to write to the address:
- \x00 (Null)
- \x09 (Tab)
- \x0a (New line)
- \x0d (Carriage return)
- \x20 (Space)
GEF commands
gef> shellcode search linux arm
gef> shellcode get 698
[+] Downloading shellcode id=698
[+] Shellcode written to '/tmp/sc-fd1r2cvr.txt'
gef> vmmap
Start End Offset Perm Path
0x00010000 0x00011000 0x00000000 r-x /opt/phoenix/arm/stack-four
0x00020000 0x00021000 0x00000000 rwx /opt/phoenix/arm/stack-four
0xf7752000 0xf77df000 0x00000000 r-x /opt/phoenix/arm-linux-musleabihf/lib/libc.so
0xf77ee000 0xf77ef000 0x0008c000 rwx /opt/phoenix/arm-linux-musleabihf/lib/libc.so
0xf77ef000 0xf77f1000 0x00000000 rwx
0xfffcf000 0xffff0000 0x00000000 rwx [stack]
0xffff0000 0xffff1000 0x00000000 r-x [vectors]
gef> check
checkpoint checksec
gef> checksec
[+] checksec for '/opt/phoenix/arm/stack-four'
Canary : No
NX : No
PIE : No
Fortify : No
RelRO : No
gef> xinfo 0xfffcf000
────────────────────────────── xinfo: 0xfffcf000 ──────────────────────────────
Page: 0xfffcf000 → 0xffff0000 (size=0x21000)
Permissions: rwx
Pathname: [stack]
Offset (from page): 0x0
Inode: 0
Shell
Get a shell
gdb) shell
List files in present working directory
gdb) shell ls
Cat a file
gdb) shell cat payload.txt
Playing
gdb) shell echo "hello there" | sed "s/hello/hi/" | sed "s/there/robots/"
Drop into shell
gef> shell
Back to gdb
$ exit`
What type of shell
# find -L /bin -samefile /bin/sh
Bash is not the default shell for Ubuntu
https://stackoverflow.com/questions/2462317/bash-syntax-error-redirection-unexpected
Cool commands
what is the current instruction
where
Set architecture to 32 bit Intel machine
set architecture i386
Set architecture to Auto
set architecture auto
disable ASLR in host machine
sysctl -w kernel.randomize_va_space=0
// whoami=root
disable ASLR
gef➤ set disable-aslr
Follow process forking
set follow-fork-mode {parent, child, ask}
Setup on macOS
https://timnash.co.uk/getting-gdb-to-semi-reliably-work-on-mojave-macos/
// NO `brew install gdb`
// NO `set startup-with-shell enable` inside of ~/.gdbinit
Create an Entitlements file
Create a Signing Certificate in KeyChain
codesign --entitlements gdb.xml -fs gdbcert /usr/local/bin/gdb
References
https://github.com/AnasAboureada/Penetration-Testing-Study-Notes/blob/master/cheatSheets/Cheatsheet_GDB.txt
https://www.exploit-db.com/papers/13205
https://sourceware.org/gdb/onlinedocs/gdb/Symbols.html
https://darkdust.net/files/GDB%20Cheat%20Sheet.pdf
https://blogs.oracle.com/linux/8-gdb-tricks-you-should-know-v2