歡迎您光臨本站 註冊首頁

Linux下彙編調試器GDB的使用

←手機掃碼閱讀     火星人 @ 2014-03-08 , reply:0

Linux下彙編調試器GDB的使用


GDB 是GNU開源組織發布的一個強大的Linux/Unix下的程序調試工具.大家是否早已習慣了Windows下圖形界面方式像VC、BCB等IDE的調試器,但如果你是在Linux平台下做軟體調試,你會發現GDB這個調試工具有比VC、BCB的圖形化調試器更強大的功能.
先來看個實例:

  1. reader@cg:~/source $ gdb -q
  2. (gdb) set dis intel
  3. (gdb) quit
  4. reader@cg:~/source $ echo "set dis intel" > ~/.gdbinit
  5. reader@cg:~/source $ cat ~/.gdbinit
  6. set dis intel
  7. reader@cg:~/source $

現在將GDB配置成為了使用英特爾語法,讓我們首先來認識英特爾語法.在英特爾語語法中,彙編指令一般遵循下面這種形式:
operation <destination>, <source>
目的操作數和源操作數可以是寄存器、內存地址或數值.操作通常是直觀的助記符:mov操作會將源操作數中的值移動到目的操作數中,sub操作會減去,inc指令會增加等.例如,下面的指令將會扣ESP中的值移動到EBP中,然後從ESP中減去8(結果存儲在ESP中).
8048375: 89 e5 mov ebp,esp
8048377: 83 ec 08 sub esp,0x8
還有用於控制執行流程的操作.cmp操作用於對數值進行比較,並且基本上所有以j為首字母的操作都用於轉移到代碼的不同部分(轉移到哪一部分取決於比較的結果).下面的例子中,首先將位於EBP中的一個4位元組的值減去4與數值9進行比較.下一條指令是如果小於等於則轉移的簡寫,它參考的是前一個比較的結果.如果那個數小於或等於9,那麼程序就會轉移到Ox8048393處的指令執行.否則,就轉向下一條無條件轉移指令執行.如果那個數不小於或等於9,那麼程序執行就會轉移到Ox80483a6處.


804838b: 83 7d fc 09 cmp DWORD PTR [ebp-4],0x9
804838f: 7e 02 jle 8048393 <main 0x1f>
8048391: eb 13 jmp 80483a6 <main 0x32>
這些例子來自於我們先前的反彙編,並且我們已經將調試工具配置為使用英特爾語法,所以讓我們使用調試工具在彙編指令級別上單步調試第一個程序吧.
GCC編譯程序可以使用-g標記來包含附加的調試信息,這些調試信息會是的GDB能夠訪問源代碼.

  1. reader@cg:~/source $ gcc -g firstprog.c
  2. reader@cg:~/source $ ls -l a.out
  3. -rwxr-xr-x 1 matrix users 11977 Jul 4 17:29 a.out
  4. reader@cg:~/source $ gdb -q ./a.out
  5. Using host libthread_db library "/lib/libthread_db.so.1".
  6. (gdb) list
  7. 1 #include <stdio.h>
  8. 2
  9. 3 int main()
  10. 4 {
  11. 5 int i;
  12. 6 for(i=0; i < 10; i )
  13. 7 {
  14. 8 printf("Hello, world!\n");
  15. 9 }
  16. 10 }
  17. (gdb) disassemble main
  18. Dump of assembler code for function main():
  19. 0x08048384 <main 0>: push ebp
  20. 0x08048385 <main 1>: mov ebp,esp
  21. 0x08048387 <main 3>: sub esp,0x8
  22. 0x0804838a <main 6>: and esp,0xfffffff0
  23. 0x0804838d <main 9>: mov eax,0x0
  24. 0x08048392 <main 14>: sub esp,eax
  25. 0x08048394 <main 16>: mov DWORD PTR [ebp-4],0x0
  26. 0x0804839b <main 23>: cmp DWORD PTR [ebp-4],0x9
  27. 0x0804839f <main 27>: jle 0x80483a3 <main 31>
  28. 0x080483a1 <main 29>: jmp 0x80483b6

    <main 50>
  29. 0x080483a3 <main 31>: mov DWORD PTR [esp],0x80484d4
  30. 0x080483aa <main 38>: call 0x80482a8 <_init 56>
  31. 0x080483af <main 43>: lea eax,[ebp-4]
  32. 0x080483b2 <main 46>: inc DWORD PTR [eax]
  33. 0x080483b4 <main 48>: jmp 0x804839b <main 23>
  34. 0x080483b6 <main 50>: leave
  35. 0x080483b7 <main 51>: ret
  36. End of assembler dump.
  37. (gdb) break main
  38. Breakpoint 1 at 0x8048394: file firstprog.c, line 6.
  39. (gdb) run
  40. Starting program: /cg/a.out
  41. Breakpoint 1, main() at firstprog.c:6
  42. 6 for(i=0; i < 10; i )
  43. (gdb) info register eip
  44. eip 0x8048394 0x8048394
  45. (gdb)

先列出了源代碼,並且顯示了main()函數的反彙編.然後,在main()函數開始的地方設置了一個斷點,並且開始運行程序.這個斷點只是告訴調試工具當程序運行到該點時暫停程序的執行.由於斷點設置在了main()函數開始的地方,實際上在執行main()中的任何指令之前,程序會到達該斷點並且暫停.然後,顯示了EIP(指令指針)的值.
EIP包含一個內存地址,該地址指向main()函數的反彙編指令中的一條指令(以粗體顯示).我們把在這之前的指令(以斜體顯示)一起稱為函數序言,它們由編譯程序生成,用於為main()函數的局部變數設置內存空間.在C語言中需要聲明變數的部分原因就是輔助建立這部分代碼.調試工具知道這部分代碼是自動產生的,並且聰明地將其跳過.我們隨後會詳細討論函數序言,但現在我們可以從GDB中獲得它的一些信息並暫時將其跳過.
GDB調試工具提供了一個直接檢查內存的方法,即使用命令x,它是檢查(examine)的簡寫.對於任何Hacker來說,檢查內存都是一項很關鍵的技術.大多數Hacker的漏洞發掘很像魔術——它們似乎令人驚訝並且不可思議,除非您知道這些戲法和誤導.但是使用像GDB這樣的調試工具,程序執行的每個方面都可以被確定地檢查、暫停、單步跟蹤並且可以隨心所欲地重複.一個正在運行的程序的主體是處理器和若干內存段,所以檢查內存是查看到底正在幹什麼的首要方法.


本文出自 「李晨光原創技術博客」 博客,謝絕轉載!


[火星人 ] Linux下彙編調試器GDB的使用已經有570次圍觀

http://coctec.com/docs/linux/show-post-46711.html