Using GDB to develop exploits - A basic run through by c0ntex | c0ntexb[at]gmail.com www.open-security.org ----------------------------------------------------------------------------- This document provides some useful basic commands to use with GDB during debug of applications for vulnerability development and troubleshooting. From the GDB man page: "The purpose of a debugger such as GDB is to allow you to see what is going on â..â..insideâ..â.. another program while it executes â.. or what another program was doing at the moment it crashed." Launch GDB against either a binary, a core file or a Process ID $ gdb ./vuln $ gdb ./vuln ./core $ gdb -c ./core $ gdb -silent `pidof vuln` Set arguments for the application to execute with (gdb) set args `perl -e 'print "A" x 50000'` Set environment variables (gdb) set env PATH=`perl -e 'print "A" x 50000'` Set breakpoints (gdb) b main // Breaks at main() Breakpoint 1 at 0x8048fd9: file vuln.c, line 627. (gdb) break strcpy // Breaks at strcpy() Breakpoint 2 at 0x42079dd4 (gdb) break vuln.c:vuln_func (gdb) rbreak ^vuln[_]func$ List defined breakpoints (gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x08048fd9 in main at vuln.c:627 Run the binary (gdb) run Starting program: /vuln/vuln `perl -e 'print "A" x 1000'` Breakpoint 3, main (argc=2, argv=0xbfffee54) at vuln.c:627 627 CONSTRUCTGLOBALS(); (gdb) Follow process forking (gdb) set follow-fork-mode {parent, child, ask} Show register addresses (gdb) i r eax 0x49488fa8 1229492136 ecx 0x8074e68 134696552 edx 0x42131300 1108546304 ebx 0x42130a14 1108544020 esp 0xbfffc190 0xbfffc190 ebp 0xbfffc1f8 0xbfffc1f8 esi 0x41414140 1094795584 edi 0x8074e70 134696560 eip 0x420744b0 0x420744b0 Show function dissasembly (gdb) disas Dump of assembler code for function main: 0x08048715 : push %ebp 0x08048716 : mov %esp,%ebp 0x08048718 : sub $0x68,%esp 0x0804871b : and $0xfffffff0,%esp Show stored values on the stack (gdb) print $esp $1 = (void *) 0xbfffc190 (gdb) x/5x $esp-10 // Hex 0xbfffedf6: 0xee084000 0x9442bfff 0x0a140805 0x53604213 0xbfffee06: 0xee284001 (gdb) x/5s $esp-10 //String 0xbfffedf6: "" 0xbfffedf7: "@\b???B\224\005\b\024\n\023B`S\001@(???tU\001B\002" 0xbfffee12: "" 0xbfffee13: "" 0xbfffee14: "T???`???,X\001@\002" (gdb) x/5d $esp-10 //Decimal 0xbfffedf6: -301449216 -1807564801 169084933 1398817299 0xbfffee06: -299352063 (gdb) x/5i $esp-10 //Instructions 0xbfffedf6: add %al,0x8(%eax) 0xbfffedf9: out %al,(%dx) 0xbfffedfa: (bad) 0xbfffedfb: mov $0x8059442,%edi 0xbfffee00: adc $0xa,%al (gdb) set $esp = 0 (gdb) print $esp $3 = (void *) 0x0 Show where in the source file we are (gdb) list 622 int argc; 623 char *argv[]; 624 { 625 int r; 626 627 CONSTRUCTGLOBALS(); 628 p = checkid(argc, argv); 629 DESTROYGLOBALS(); 630 strcpy(id_d, p); 631 while(1) { Show where execution is (gdb) where #0 main (argc=2, argv=0xbfff2764) at vuln.c:627 #1 0x42015574 in __libc_start_main () from /lib/tls/libc.so.6 (gdb) Continue executing (gdb) c //Resume code execution Continuing. Breakpoint 2, 0x42079dd4 in strcpy () from /lib/tls/libc.so.6 (gdb) s //Step into next function Single stepping until exit from function vuln1, which has no line number information. check_vuln () at vuln1.c:259 259 whoUID = (u_id ? sys_UID_secret : (gdb) s 309 usrIDnum = numIDnum = 0; (gdb) c //Continue again Continuing. Breakpoint 2, 0x42079dd4 in strcpy () from /lib/tls/libc.so.6 (gdb) c //Continue again Continuing. Program received signal SIGSEGV, Segmentation fault. 0x41414141 in ?? () Show last frame on the stack (gdb) where 1 #0 0x41414141 in ?? () (More stack frames follow...) Show failing frame info (gdb) info frame 0 Stack frame at 0xbfff3588: eip = 0x41414141; saved eip 0x80530c2 called by frame at 0xbfff35c8 Arglist at 0xbfff3588, args: Locals at 0xbfff3588, Previous frame's sp in esp Saved registers: ebp at 0xbfff3588, eip at 0xbfff358c Show values in some useful registers (gdb) x/x $eip 0x41414141: Cannot access memory at address 0x41414141 (gdb) x/x $ebp 0xbfff3588: 0xbfff35c8 (gdb) x/x $esp 0xbfff354c: 0x08053309 Disassemble strcpy function (gdb) disas strcpy Dump of assembler code for function strcpy: 0x42079dd0 : push %ebp 0x42079dd1 : mov %esp,%ebp 0x42079dd3 : push %esi 0x42079dd4 : mov 0x8(%ebp),%esi 0x42079dd7 : mov 0xc(%ebp),%edx 0x42079dda : mov %esi,%eax 0x42079ddc : sub %edx,%eax 0x42079dde : lea 0xffffffff(%eax),%ecx 0x42079de1 : jmp 0x42079df0 0x42079de3 : nop 0x42079de4 : nop 0x42079dfb : mov %esi,%eax 0x42079dfd : pop %esi 0x42079dfe : pop %ebp 0x42079dff : ret End of assembler dump. Show content pointed to by a pointer 0x08054e2c in blah (p=0x41414141
) at vuln.c:284 284 for (; *p; INCSTR(p)) (gdb) x/x p 0x41414141: Cannot access memory at address 0x41414141 Display executable sections (gdb) main info sec Exec file: `/root/vuln', file type elf32-i386. 0x080480f4->0x08048107 at 0x000000f4: .interp ALLOC LOAD READONLY DATA HAS_CONTENTS 0x08048108->0x08048128 at 0x00000108: .note.ABI-tag ALLOC LOAD READONLY DATA HAS_CONTENTS 0x08048128->0x080482c4 at 0x00000128: .hash ALLOC LOAD READONLY DATA HAS_CONTENTS 0x080482c4->0x080486c4 at 0x000002c4: .dynsym ALLOC LOAD READONLY DATA HAS_CONTENTS 0x080486c4->0x080488ce at 0x000006c4: .dynstr ALLOC LOAD READONLY DATA HAS_CONTENTS 0x080488ce->0x0804894e at 0x000008ce: .gnu.version ALLOC LOAD READONLY DATA HAS_CONTENTS 0x08048950->0x08048990 at 0x00000950: .gnu.version_r ALLOC LOAD READONLY DATA HAS_CONTENTS 0x08048990->0x080489b8 at 0x00000990: .rel.dyn ALLOC LOAD READONLY DATA HAS_CONTENTS 0x080489b8->0x08048b78 at 0x000009b8: .rel.plt ALLOC LOAD READONLY DATA HAS_CONTENTS 0x08048b78->0x08048b8f at 0x00000b78: .init ALLOC LOAD READONLY CODE HAS_CONTENTS 0x08048b90->0x08048f20 at 0x00000b90: .plt ALLOC LOAD READONLY CODE HAS_CONTENTS 0x08048f20->0x080594c0 at 0x00000f20: .text ALLOC LOAD READONLY CODE HAS_CONTENTS 0x080594c0->0x080594db at 0x000114c0: .fini ALLOC LOAD READONLY CODE HAS_CONTENTS 0x080594e0->0x0805f2e9 at 0x000114e0: .rodata ALLOC LOAD READONLY DATA HAS_CONTENTS 0x0805f2ec->0x0805f2f0 at 0x000172ec: .eh_frame ALLOC LOAD READONLY DATA HAS_CONTENTS 0x08060000->0x0806015c at 0x00018000: .data ALLOC LOAD DATA HAS_CONTENTS 0x0806015c->0x08060224 at 0x0001815c: .dynamic ALLOC LOAD DATA HAS_CONTENTS 0x08060224->0x0806022c at 0x00018224: .ctors ALLOC LOAD DATA HAS_CONTENTS 0x0806022c->0x08060234 at 0x0001822c: .dtors ALLOC LOAD DATA HAS_CONTENTS 0x08060234->0x08060238 at 0x00018234: .jcr ALLOC LOAD DATA HAS_CONTENTS 0x08060238->0x08060328 at 0x00018238: .got ALLOC LOAD DATA HAS_CONTENTS 0x08060340->0x08072e18 at 0x00018340: .bss ALLOC 0x00000000->0x00000462 at 0x00018340: .comment READONLY HAS_CONTENTS 0x00000000->0x00000258 at 0x000187a8: .debug_aranges READONLY HAS_CONTENTS 0x00000000->0x000006bf at 0x00018a00: .debug_pubnames READONLY HAS_CONTENTS 0x00000000->0x000448b3 at 0x000190bf: .debug_info READONLY HAS_CONTENTS 0x00000000->0x0000386e at 0x0005d972: .debug_abbrev READONLY HAS_CONTENTS 0x00000000->0x000049d8 at 0x000611e0: .debug_line READONLY HAS_CONTENTS 0x00000000->0x00001640 at 0x00065bb8: .debug_frame READONLY HAS_CONTENTS 0x00000000->0x00004d32 at 0x000671f8: .debug_str READONLY HAS_CONTENTS 0x00000000->0x000006a8 at 0x0006bf2a: .debug_ranges READONLY HAS_CONTENTS Print data in the .plt section (gdb) x/20x 0x08048b84 0x8048b84 <_init+24>: 0x423c35ff 0x25ff0806 0x08064240 0x00000000 0x8048b94 : 0x424425ff 0x00680806 0xe9000000 0xffffffe0 0x8048ba4 : 0x424825ff 0x08680806 0xe9000000 0xffffffd0 0x8048bb4 : 0x424c25ff 0x10680806 0xe9000000 0xffffffc0 0x8048bc4 : 0x425025ff 0x18680806 0xe9000000 0xffffffb0 Print string values in the .bbs section (gdb) x/5s 0x08060340+11000 0x8062e38 : 'A' ... 0x8062f00 : 'A' ... 0x8062fc8 : 'A' ... 0x8063090 : 'A' ... 0x8063158 : 'A' ... (gdb) x/5x 0x08072e18 0x8072e18: 0x41414141 0x41414141 0x41414141 0x41414141 0x8072e28: 0x41414141 Print the address for library system call (gdb) x/x strcpy 0x42079da0 : 0x56e58955 (gdb) x/x system 0x42041e50 : 0x83e58955 (gdb) x/x printf 0x42052390 : 0x83e58955 (gdb) x/x exit 0x4202b0f0 : 0x57e58955 Finding shellcode location at +600 from $esp (gdb) x/100x $esp+600 0xbfff38c4: 0x00000000 0x00000000 0x00000000 0x00000000 0xbfff38d4: 0x00000000 0x36690000 0x2f003638 0x746f6f72 0xbfff38e4: 0x7a6e752f 0x352d7069 0x2f31352e 0x697a6e75 0xbfff38f4: 0x41410070 0x41414141 0x41414141 0x41414141 0xbfff3904: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfff3914: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfff3924: 0x41414141 0x41414141 0x41414141 0x41414141 Finding opcode values at -10 offset of $esp (gdb) x/20bx $esp-10 0xbfff2fc2: 0x06 0x08 0xc0 0xc5 0x05 0x08 0xec 0xc5 0xbfff2fca: 0x05 0x08 0x09 0x33 0x05 0x08 0x60 0x03 0xbfff2fd2: 0x06 0x08 0x18 0x0c Return address (0xbfffc12f) alignment is off (gdb) x/100x $esp-600 0xbfff38c4: 0x00000000 0x00000000 0x00000000 0x00000000 0xbfff38d4: 0x90900070 0x90909090 0x90909090 0x90909090 0xbfff38e4: 0x90900090 0x90909090 0x90909090 0x90909090 0xbfff38f4: 0x90900090 0x90909090 0x90909090 0x90909090 0xbfff3904: 0x90909090 0x90909090 0x90909090 0x90909090 0xbfff3914: 0x90909090 0x90909090 0x90909090 0x90909090 0xbfff3924: 0x2fbfffc1 0x00000000 0x00000000 0x00000000 (gdb) info sources Source files for which symbols have been read in: a=blah.c Source files for which symbols will be read in on demand: (gdb) info functions All defined functions: File blah.c: int attach_trc(int, pid_t); void banner(void); int detach_trc(int, pid_t); int main(int, char **); int show_trc(int, struct user_regs_struct); Non-debugging symbols: 0x080483c0 _init 0x08048488 _start 0x080484ac call_gmon_start 0x080484d0 __do_global_dtors_aux 0x08048504 frame_dummy 0x080488d0 __libc_csu_init 0x08048924 __libc_csu_fini 0x08048968 __do_global_ctors_aux 0x0804898c _fini (gdb) info file Symbols from "/tmp/blah". Local exec file: `/tmp/blah', file type elf32-i386. Entry point: 0x8048488 0x08048114 - 0x08048127 is .interp 0x08048128 - 0x08048148 is .note.ABI-tag 0x08048148 - 0x08048198 is .hash 0x08048198 - 0x08048288 is .dynsym 0x08048288 - 0x08048322 is .dynstr 0x08048322 - 0x08048340 is .gnu.version 0x08048340 - 0x08048360 is .gnu.version_r 0x08048360 - 0x08048370 is .rel.dyn 0x08048370 - 0x080483c0 is .rel.plt 0x080483c0 - 0x080483d7 is .init 0x080483d8 - 0x08048488 is .plt 0x08048488 - 0x0804898c is .text 0x0804898c - 0x080489a6 is .fini 0x080489a8 - 0x08048c36 is .rodata 0x08048c38 - 0x08048c3c is .eh_frame 0x08049c3c - 0x08049c44 is .ctors 0x08049c44 - 0x08049c4c is .dtors 0x08049c4c - 0x08049c50 is .jcr 0x08049c50 - 0x08049d18 is .dynamic 0x08049d18 - 0x08049d1c is .got 0x08049d1c - 0x08049d50 is .got.plt 0x08049d50 - 0x08049d5c is .data 0x08049d5c - 0x08049d64 is .bss EOF # milw0rm.com [2006-04-08]