淺談gdb在漏洞發掘中的使用
作者:s5Eal
現在越來越多的人開始學習緩衝區溢位方面的原理和應用,這是一件好事,我們在使用別人寫的Exploit去Hacker這兒Hacker那兒的時候,應該努力做到知其然,知其所以然。但是很多人在看了幾篇即使是看上去很簡單的棧溢出方面的文章後便敲起了退堂鼓,因為通篇大量gdb調試的命令和彙編代碼讓學習看上去變得枯燥無比,但是這方面知識的學習就是這樣的。我寫這篇文章的目的是總結一下在漏洞發掘中常用的一些gdb命令,降低一下新手入門時的門檻,希望能對大家有所協助。這篇文章與一般的介紹gdb使用的文章有一定區別,因為那些文章的側重點是使用gdb去調試一般的應用程式,而本文的則偏重於使用gdb去發掘漏洞時候常用的一些命令。鑒於本人大愚若智,本文如有疏漏之處,敬請mail to me.
運行 gdb
在 shell中,可以使用 'gdb' 命令並指定程式名作為參數來運行 gdb,例如 ‘gdb ./vuln'或者直接是‘gdb vuln’;或者在 gdb 中,可以使用 file 命令來裝入要調試的程式,例如 'file vuln'。這兩種方式都假設您是在包含程式的目錄中執行命令。如果是為了調試core檔案,則應用程式命令‘gdb `executable-file` `core-file`’,例如‘gdb ./vuln core’,如果系統不產生core檔案,則可以使用命令‘ulimit -c 9999’開啟這個功能。裝入程式之後,可以用 gdb 命令 'run' 來啟動程式。
綁定一個已有的進程
在shell中,一般使用ps -ax命令來查看目前系統裡正在run的所有進程,最前面的一列就是對應的進程號,在gdb裡我們可以這樣綁定一個正在run的程式進行調試,首先利用上面的那個命令取得進程號,然後開啟gdb:
[s5Eal@Heart]# gdb
GNU gdb Red Hat Linux (5.2.1-4)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux".
(gdb) attach 734 <-你要調試的程式的進程號
Attaching to process 734
查詢記憶體
(gdb) x/d ‘地址’ 或者 x '地址' 顯示10進位內容
(gdb) x/100s '地址' 顯示由此地址開始的100個位元組的十進位內容
(gdb) x 0x0804846c 顯示0x0804846c處的十進位內容
(gdb) x/s '地址' 顯示此地址內容對應的字串
(gdb) x/105 0x0804846c 顯示0x0804846c處開始的105個位元組對應的字 符串內容
(gdb) x/x '地址' 顯示16進位的地址內容
(gdb) x/10x 0x0804846c 顯示0x0804846c處開始的10個位元組的地址內容
(gdb) x/b 0x0804846c 顯示0x0804846c處一個byte的內容
(gdb) x/10b 0x0804846c-10 顯示0x0804846c-10處10個byte的內容
(gdb) x/10b 0x0804846c+20 顯示0x0804846c+20處20個byte的內容
(gdb) x/20i 0x0804846c 顯示0x0804846c 處開始的20個彙編指令的內容
顯示可執行檔的所有分段的地址
(gdb) maintenance info sections 或者
(gdb) mai i s
例子:
[s5Eal@lHeart]# gdb vul
GNU gdb Red Hat Linux (5.2.1-4)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...
(gdb) maintenance info sections
Exec file:
`/root/vul', 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 DATAHAS_CONTENTS
0x08048128->0x08048158 at 0x00000128: .hash ALLOC LOAD READONLY DATA HAS_CONTENTS
0x08048158->0x080481c8 at 0x00000158: .dynsym ALLOC LOAD READONLY DATA HAS_CONTENTS
0x080481c8->0x08048222 at 0x000001c8: .dynstr ALLOC LOAD READONLY DATA HAS_CONTENTS
0x08048222->0x08048230 at 0x00000222: .gnu.version ALLOC LOAD READONLY DATAHAS_CONTENTS
0x08048230->0x08048250 at 0x00000230: .gnu.version_r ALLOC LOAD READONLY DATA HAS_CONTENTS
0x08048250->0x08048258 at 0x00000250: .rel.dyn ALLOC LOAD READONLY DATA HAS_CONTENTS
0x08048258->0x08048278 at 0x00000258: .rel.plt ALLOC LOAD READONLY DATA HAS_CONTENTS
0x08048278->0x08048290 at 0x00000278: .init ALLOC LOAD READONLY CODE HAS_CONTENTS
0x08048290->0x080482e0 at 0x00000290: .plt ALLOC LOAD READONLY CODE HAS_CONT
搜尋heap,bss,got區的內容
(gdb) maintenance info sections
0x08049570->0x08049588 at 0x00000570: .bss ALLOC
0x00000000->0x00000654 at 0x00000570: .stab READONLY HAS_CONTENTS
0x00000000->0x00001318 at 0x00000bc4: .stabstr READONLY HAS_CONTENTS
0x00000000->0x000000e4 at 0x00001edc: comment READONLY HAS_CONTENTS
0x08049588->0x08049600 at 0x00001fc0: .note READONLY HAS_CONTENTS
(gdb) x/1000s 0x08049600 // 顯示 heap內容
(gdb) x/1000s 0x08049570 // 顯示 bss 內容
...
下斷點
(gdb) disassemble main
Dump of assembler code for function main:
0x8048400 <main>: push %ebp
0x8048401 <main+1>: mov %esp,%ebp
0x8048403 <main+3>: sub $0x408,%esp
0x8048409 <main+9>: add $0xfffffff8,%esp
0x804840c <main+12>: mov 0xc(%ebp),%eax
0x804840f <main+15>: add $0x4,%eax
0x8048412 <main+18>: mov (%eax),%edx
0x8048414 <main+20>: push %edx
0x8048415 <main+21>: lea 0xfffffc00(%ebp),%eax
...
(gdb) break *0x8048414
Breakpoint 1 at 0x8048414
(gdb) break main
Breakpoint 2 at 0x8048409
(gdb)
刪除斷點
(gdb) delete breakpoints // or
(gdb) d b
Delete all breakpoints? (y or n) y
(gdb)
在stack區搜尋shellcode或者返回地址或者其他內容
(gdb) break '函數名或者地址'
(gdb) break main
Breakpoint 1 at 0x8048409
(gdb) run
Starting program: /root/vuln
Breakpoint 1, 0x8048409 in main ()
(gdb) x/1000s '地址' // 列印此地址開始的100個字串
(gdb) p $esp // 查看寄存器esp的內容
$2 = (void *) 0xbffff454
(gdb) x/1000s $esp // 搜尋從esp開始向後的1000個字串的內容
(gdb) x/1000s $esp-1000 // 搜尋從esp開始向前面的1000個字串的內容
(gdb) x/1000s 0xbffff4b4 // 搜尋從0xbffff4b4開始向後的1000個字串的內容
顯示寄存器內容
(gdb) break main
Breakpoint 7 at 0x8048409
(gdb) r
Starting program: /home/hack/homepage/challenge/buf/basic
Breakpoint 7, 0x8048409 in main ()
(gdb) info registers
eax 0x1 1
ecx 0x8048298 134513304
edx 0x8048400 134513664
ebx 0x400f6618 1074751000
esp 0xbffff4b4 0xbffff4b4
ebp 0xbffff8bc 0xbffff8bc
esi 0x4000aa20 1073785376
edi 0xbffff924 -1073743580
eip 0x8048409 0x8048409
eflags 0x286 646
cs 0x23 35
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x0 0
gs 0x0 0
(gdb)
顯示動態函數指標地址 (常用在return into libc exploits的構造中):
(gdb) break main
Breakpoint 1 at 0x8048409
(gdb) r
Starting program: /home/hack/homepage/challenge/buf/./basic
Breakpoint 1, 0x8048409 in main ()
(gdb) p system
$1 = {<text variable, no debug info>} 0x40052460 <system>
(gdb) p strcpy
$5 = {char *(char *, char *)} 0x4006e880 <strcpy>
顯示堆棧
(gdb) backtrace
(gdb) bt
#0 0x8048476 in main ()
#1 0x40031a5e in __libc_start_main () at ../sysdeps/generic/libc-start.c:93