O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.
Introduction to Debuggers<br />The first bug - documented by Grace Hopper<br />
Introduction<br />
# who am i<br />Saumil Shah<br />CEO Net-square.<br />Hacker, Speaker, Trainer, Author.<br />M.S. Computer Science<br />Pu...
Preview<br />
Debuggers<br />
What is a debugger?<br />
What is a debugger?<br />A program used for debugging other programs or process. It provides...<br />
What is a debugger?<br />A program used for debugging other programs or process. It provides...<br />Fine grained control ...
A debugger lets you...<br />
Popular debuggers<br />gdb<br />windbg<br />
Working with programs<br />
A debugging example<br />
crash1.c<br />int main(int argc, char *argv[])<br />{<br />   int number;<br />   int *pointer;<br />   number = atoi(argv...
What does crash1.c do?<br />
What does crash1.c do?<br />crash1 takes the first command line argument and converts it to an integer<br />
What does crash1.c do?<br />crash1 takes the first command line argument and converts it to an integer<br />It then assign...
What does crash1.c do?<br />crash1 takes the first command line argument and converts it to an integer<br />It then assign...
Using gdb<br />
gdb<br />We shall debug crash1.c using gdb.<br />
gdb<br />We shall debug crash1.c using gdb.<br />gdb is a command line debugger.<br />
gdb<br />We shall debug crash1.c using gdb.<br />gdb is a command line debugger.<br />It is very unfriendly at first...<br...
Compiling crash1.c<br />Before we debug crash1.c, we need to compile it.<br />We shall then run crash1 from within gdb its...
Compile crash1.c and load it using gdb<br />$ gcc crash1.c -o crash1<br />
Compile crash1.c and load it using gdb<br />$ gcc crash1.c -o crash1<br />$ gdb crash1<br />GNU gdb (GDB) 7.2<br />Copyrig...
Now run it...<br />
Now run it...<br />...with no command line arguments.<br />
Now run it...<br />...with no command line arguments.<br />(gdb) run<br />Starting program: /home/user0/crash1 <br />Progr...
Now run it...<br />...with no command line arguments.<br />(gdb) run<br />Starting program: /home/user0/crash1 <br />Progr...
Now run it...<br />...with no command line arguments.<br />(gdb) run<br />Starting program: /home/user0/crash1 <br />Progr...
Now run it...<br />...with no command line arguments.<br />(gdb) run<br />Starting program: /home/user0/crash1 <br />Progr...
Use gdb command "backtrace"<br />
Use gdb command "backtrace"<br />It tries to reconstruct frames on the stack.<br />We can find out the sequence of functio...
Use gdb command "backtrace"<br />It tries to reconstruct frames on the stack.<br />We can find out the sequence of functio...
Use gdb command "backtrace"<br />It tries to reconstruct frames on the stack.<br />We can find out the sequence of functio...
Use gdb command "backtrace"<br />It tries to reconstruct frames on the stack.<br />We can find out the sequence of functio...
"x" to examine memory<br />
"x" to examine memory<br />(gdb) x/10i $eip<br />=> 0x40044c2e: movzx  ecx,BYTE PTR [edi]<br />   0x40044c31: mov    eax,D...
"x" to examine memory<br />(gdb) x/10i $eip<br />=> 0x40044c2e: movzx  ecx,BYTE PTR [edi]<br />   0x40044c31: mov    eax,D...
"x" to examine memory<br />(gdb) x/10i $eip<br />=> 0x40044c2e: movzx  ecx,BYTE PTR [edi]<br />   0x40044c31: mov    eax,D...
"x" - Examine Memory<br />
Where did the fault occur?<br />
Where did the fault occur?<br />Let us see the faulting instruction again.<br />
Where did the fault occur?<br />Let us see the faulting instruction again.<br />(gdb) x/10i $eip<br />=> 0x40044c2e: movzx...
Where did the fault occur?<br />Let us see the faulting instruction again.<br />(gdb) x/10i $eip<br />=> 0x40044c2e: movzx...
Where did the fault occur?<br />Let us see the faulting instruction again.<br />(gdb) x/10i $eip<br />=> 0x40044c2e: movzx...
Where did the fault occur?<br />Let us see the faulting instruction again.<br />(gdb) x/10i $eip<br />=> 0x40044c2e: movzx...
Use the "info registers" command.<br />
Use the "info registers" command.<br />(gdb) info registers<br />eax            0x40136660	0x40136660<br />ecx            ...
Use the "info registers" command.<br />(gdb) info registers<br />eax            0x40136660	0x40136660<br />ecx            ...
Use the "info registers" command.<br />(gdb) info registers<br />eax            0x40136660	0x40136660<br />ecx            ...
Let us try and inspect local variables and arguments, if any.<br />
Let us try and inspect local variables and arguments, if any.<br />Use the "info locals" and "info args" commands.<br />
Let us try and inspect local variables and arguments, if any.<br />Use the "info locals" and "info args" commands.<br />(g...
Let us try and inspect local variables and arguments, if any.<br />Use the "info locals" and "info args" commands.<br />(g...
Let us try and inspect local variables and arguments, if any.<br />Use the "info locals" and "info args" commands.<br />(g...
Let us try and inspect local variables and arguments, if any.<br />Use the "info locals" and "info args" commands.<br />(g...
Quit the debugger<br />(gdb) q<br />
Quit the debugger<br />(gdb) q<br />Recompile with debugging information enabled.<br />$ gcc -g crash1.c -o crash1<br />
Quit the debugger<br />(gdb) q<br />Recompile with debugging information enabled.<br />$ gcc -g crash1.c -o crash1<br />Th...
Load crash1 in gdb again<br />
Load crash1 in gdb again<br />$ gdb crash1<br />GNU gdb (GDB) 7.2<br />Copyright (C) 2010 Free Software Foundation, Inc.<b...
Load crash1 in gdb again<br />$ gdb crash1<br />GNU gdb (GDB) 7.2<br />Copyright (C) 2010 Free Software Foundation, Inc.<b...
Use gdb's "list" command<br />
Use gdb's "list" command<br />(gdb) list<br />1	#include <stdio.h><br />2	<br />3	void printnum(int *x);<br />4	<br />5	in...
Use gdb's "list" command<br />(gdb) list<br />1	#include <stdio.h><br />2	<br />3	void printnum(int *x);<br />4	<br />5	in...
Use gdb's "list" command<br />(gdb) list<br />1	#include <stdio.h><br />2	<br />3	void printnum(int *x);<br />4	<br />5	in...
Recap<br />We know that the program crashed when executing atoi(argv[1]).<br />
Recap<br />We know that the program crashed when executing atoi(argv[1]).<br />We shall now set a breakpoint at the statem...
Recap<br />We know that the program crashed when executing atoi(argv[1]).<br />We shall now set a breakpoint at the statem...
Use gdb's "break" command to set a breakpoint.<br />
Use gdb's "break" command to set a breakpoint.<br />(gdb) break 10<br />Breakpoint 1 at 0x804837c: file crash1.c, line 10....
Use gdb's "break" command to set a breakpoint.<br />(gdb) break 10<br />Breakpoint 1 at 0x804837c: file crash1.c, line 10....
Use gdb's "break" command to set a breakpoint.<br />(gdb) break 10<br />Breakpoint 1 at 0x804837c: file crash1.c, line 10....
Use gdb's "break" command to set a breakpoint.<br />(gdb) break 10<br />Breakpoint 1 at 0x804837c: file crash1.c, line 10....
Use gdb's "break" command to set a breakpoint.<br />(gdb) break 10<br />Breakpoint 1 at 0x804837c: file crash1.c, line 10....
gdb's "print" command lets us inspect variables.<br />
gdb's "print" command lets us inspect variables.<br />(gdb) print argv[1]<br />$1 = 0x0<br />
gdb's "print" command lets us inspect variables.<br />(gdb) print argv[1]<br />$1 = 0x0<br />argv[1] is the culprit NULL p...
gdb's "print" command lets us inspect variables.<br />(gdb) print argv[1]<br />$1 = 0x0<br />argv[1] is the culprit NULL p...
gdb's "print" command lets us inspect variables.<br />(gdb) print argv[1]<br />$1 = 0x0<br />argv[1] is the culprit NULL p...
gdb's "print" command lets us inspect variables.<br />(gdb) print argv[1]<br />$1 = 0x0<br />argv[1] is the culprit NULL p...
Bug #1 - Null pointer<br />To fix this problem the programmer needs to check the number of command line arguments before u...
Bug #1 - Null pointer<br />To fix this problem the programmer needs to check the number of command line arguments before u...
Bug #1 - Null pointer<br />To fix this problem the programmer needs to check the number of command line arguments before u...
Load crash1 in gdb again.<br />$ gdb crash1<br />GNU gdb (GDB) 7.2<br />...<br />Reading symbols from /home/user0/crash1.....
Load crash1 in gdb again.<br />$ gdb crash1<br />GNU gdb (GDB) 7.2<br />...<br />Reading symbols from /home/user0/crash1.....
Load crash1 in gdb again.<br />$ gdb crash1<br />GNU gdb (GDB) 7.2<br />...<br />Reading symbols from /home/user0/crash1.....
What do we do now?<br />
What do we do now?<br />I thought I asked the questions!<br />
What do we do now?<br />I thought I asked the questions!<br />We see where we crashed by examining frames from the stack. ...
What do we do now?<br />I thought I asked the questions!<br />We see where we crashed by examining frames from the stack. ...
What do we do now?<br />I thought I asked the questions!<br />We see where we crashed by examining frames from the stack. ...
What do we do now?<br />I thought I asked the questions!<br />We see where we crashed by examining frames from the stack. ...
That's right. x is an integer pointer, set to 0xff.<br />
That's right. x is an integer pointer, set to 0xff.<br />So it points to memory address 0x000000ff?<br />
That's right. x is an integer pointer, set to 0xff.<br />So it points to memory address 0x000000ff?<br />Yes. This memory ...
That's right. x is an integer pointer, set to 0xff.<br />So it points to memory address 0x000000ff?<br />Yes. This memory ...
That's right. x is an integer pointer, set to 0xff.<br />So it points to memory address 0x000000ff?<br />Yes. This memory ...
That's right. x is an integer pointer, set to 0xff.<br />So it points to memory address 0x000000ff?<br />Yes. This memory ...
gdb's "frame <n>" command lets you switch context to other frames.<br />
gdb's "frame <n>" command lets you switch context to other frames.<br />(gdb) frame 1<br />#1  0x080483a3 in main (argc=0x...
gdb's "frame <n>" command lets you switch context to other frames.<br />(gdb) frame 1<br />#1  0x080483a3 in main (argc=0x...
gdb's "frame <n>" command lets you switch context to other frames.<br />(gdb) frame 1<br />#1  0x080483a3 in main (argc=0x...
gdb's "frame <n>" command lets you switch context to other frames.<br />(gdb) frame 1<br />#1  0x080483a3 in main (argc=0x...
gdb's "frame <n>" command lets you switch context to other frames.<br />(gdb) frame 1<br />#1  0x080483a3 in main (argc=0x...
Absolutely correct. What should we do instead?<br />
Absolutely correct. What should we do instead?<br />Make the pointer POINT to the number.<br />
Absolutely correct. What should we do instead?<br />Make the pointer POINT to the number.<br />Set the pointer's value to ...
Bug #2 - Pointer mess-up<br />The faulting statement is:<br />pointer = number;<br />
Bug #2 - Pointer mess-up<br />The faulting statement is:<br />pointer = number;<br />Instead it should be:<br />pointer = ...
Bug #2 - Pointer mess-up<br />The faulting statement is:<br />pointer = number;<br />Instead it should be:<br />pointer = ...
(gdb) frame 0<br />
(gdb) frame 0<br />(gdb) x/10i $eip<br />=> 0x80483b4 <printnum+12>:	push   DWORD PTR [eax]<br />   0x80483b6 <printnum+14...
(gdb) frame 0<br />(gdb) x/10i $eip<br />=> 0x80483b4 <printnum+12>:	push   DWORD PTR [eax]<br />   0x80483b6 <printnum+14...
(gdb) frame 0<br />(gdb) x/10i $eip<br />=> 0x80483b4 <printnum+12>:	push   DWORD PTR [eax]<br />   0x80483b6 <printnum+14...
There are two PUSHes. The first pushes the contents at address EAX onto the stack.<br />
There are two PUSHes. The first pushes the contents at address EAX onto the stack.<br />EAX stores the address of the poin...
There are two PUSHes. The first pushes the contents at address EAX onto the stack.<br />EAX stores the address of the poin...
There are two PUSHes. The first pushes the contents at address EAX onto the stack.<br />EAX stores the address of the poin...
There are two PUSHes. The first pushes the contents at address EAX onto the stack.<br />EAX stores the address of the poin...
There are two PUSHes. The first pushes the contents at address EAX onto the stack.<br />EAX stores the address of the poin...
printf()<br />printf("The number supplied is %dn", *x);<br />
printf()<br />printf("The number supplied is %dn", *x);<br /> push   DWORD PTR [eax]<br />
printf()<br />printf("The number supplied is %dn", *x);<br /> push   DWORD PTR [eax]<br /> push   0x8048488<br />
printf()<br />printf("The number supplied is %dn", *x);<br /> push   DWORD PTR [eax]<br /> push   0x8048488<br /> call   0...
printf()<br />printf("The number supplied is %dn", *x);<br /> push   DWORD PTR [eax]<br /> push   0x8048488<br /> call   0...
So where does address 0x08048488 point to?<br />
So where does address 0x08048488 point to?<br />It should point to the string:<br />"The number supplied is %dn"<br />
So where does address 0x08048488 point to?<br />It should point to the string:<br />"The number supplied is %dn"<br />Let ...
So where does address 0x08048488 point to?<br />It should point to the string:<br />"The number supplied is %dn"<br />Let ...
Disassembling printnum()<br />To wrap this up, let us dive into the assembly code of function printnum().<br />We shall ma...
Use the "disassemble" command<br />
Use the "disassemble" command<br />(gdb) disassemble printnum<br />Dump of assembler code for function printnum:<br />   0...
Use the "disassemble" command<br />(gdb) disassemble printnum<br />Dump of assembler code for function printnum:<br />   0...
printnum() disassembly<br />Prologue<br />  push   ebp<br />  mov    ebp,esp<br />  sub    esp,0x8<br />  sub    esp,0x8<b...
printnum() disassembly<br />Prologue<br />  push   ebp<br />  mov    ebp,esp<br />  sub    esp,0x8<br />  sub    esp,0x8<b...
printnum() disassembly<br />Prologue<br />  push   ebp<br />  mov    ebp,esp<br />  sub    esp,0x8<br />  sub    esp,0x8<b...
Before printnum() is called<br />  push  ebp<br />  mov   ebp,esp<br />  sub   esp,0x8<br />  sub   esp,0x8<br />  mov   e...
Before printnum() is called<br />> push  ebp<br />  mov   ebp,esp<br />  sub   esp,0x8<br />  sub   esp,0x8<br />  mov   e...
Prologue<br />push  ebp<br />> mov   ebp,esp<br />  sub   esp,0x8<br />  sub   esp,0x8<br />  mov   eax,DWORD PTR [ebp+0x8...
Prologue<br />push  ebp<br />mov   ebp,esp<br />> sub   esp,0x8<br />  sub   esp,0x8<br />  mov   eax,DWORD PTR [ebp+0x8]<...
Prologue<br />push  ebp<br />mov   ebp,esp<br />  sub   esp,0x8<br />  sub   esp,0x8<br />> mov   eax,DWORD PTR [ebp+0x8]<...
Body<br />push  ebp<br />mov   ebp,esp<br />  sub   esp,0x8<br />  sub   esp,0x8<br />mov   eax,DWORD PTR [ebp+0x8]<br />>...
Segmentation Fault!<br />push  ebp<br />mov   ebp,esp<br />  sub   esp,0x8<br />  sub   esp,0x8<br />mov   eax,DWORD PTR [...
Segmentation Fault!<br />push  ebp<br />mov   ebp,esp<br />  sub   esp,0x8<br />  sub   esp,0x8<br />mov   eax,DWORD PTR [...
Examine stack memory and registers<br />
Examine stack memory and registers<br />(gdb) x/16xw $esp<br />0xbffff938: 0x0000000a 0x00000000 0x40042550 0x40012df8<br ...
Examine stack memory and registers<br />(gdb) x/16xw $esp<br />0xbffff938: 0x0000000a 0x00000000 0x40042550 0x40012df8<br ...
Examine stack memory and registers<br />(gdb) x/16xw $esp<br />0xbffff938: 0x0000000a 0x00000000 0x40042550 0x40012df8<br ...
Recap<br />We have seen how to analyze crashes and identify causes of errors.<br />We also saw a lot of gdb commands and w...
Summary of gdb commands<br />
A few gdb commands<br />
A few more gdb commands<br />
Review<br />
END<br />photo: Brian Searle - bit.ly/fpcxY9<br />
Próximos SlideShares
Carregando em…5
×

Introduction to Debuggers

A quick tutorial on what debuggers are and how to use them. We present a debugging example using GDB. At the end of this tutorial, you will be able to work your way through a crash and analyze the cause of the error responsible for the crash.

  • Entre para ver os comentários

Introduction to Debuggers

  1. 1. Introduction to Debuggers<br />The first bug - documented by Grace Hopper<br />
  2. 2. Introduction<br />
  3. 3. # who am i<br />Saumil Shah<br />CEO Net-square.<br />Hacker, Speaker, Trainer, Author.<br />M.S. Computer Science<br />Purdue University.<br />Google: "saumil"<br />LinkedIn: saumilshah<br />
  4. 4. Preview<br />
  5. 5. Debuggers<br />
  6. 6. What is a debugger?<br />
  7. 7. What is a debugger?<br />A program used for debugging other programs or process. It provides...<br />
  8. 8. What is a debugger?<br />A program used for debugging other programs or process. It provides...<br />Fine grained control over process execution<br />Inspection of CPU state<br />Inspection of process memory<br />
  9. 9. A debugger lets you...<br />
  10. 10. Popular debuggers<br />gdb<br />windbg<br />
  11. 11. Working with programs<br />
  12. 12.
  13. 13. A debugging example<br />
  14. 14. crash1.c<br />int main(int argc, char *argv[])<br />{<br /> int number;<br /> int *pointer;<br /> number = atoi(argv[1]);<br /> pointer = number;<br /> printnum(pointer);<br />}<br />void printnum(int *x)<br />{<br /> printf("The number supplied is %dn", *x);<br />}<br />
  15. 15. What does crash1.c do?<br />
  16. 16. What does crash1.c do?<br />crash1 takes the first command line argument and converts it to an integer<br />
  17. 17. What does crash1.c do?<br />crash1 takes the first command line argument and converts it to an integer<br />It then assigns a pointer to this integer...<br />...and passes it to a function - printnum()<br />
  18. 18. What does crash1.c do?<br />crash1 takes the first command line argument and converts it to an integer<br />It then assigns a pointer to this integer...<br />...and passes it to a function - printnum()<br />There are TWO bugs in this program<br />Can you spot them?<br />
  19. 19. Using gdb<br />
  20. 20. gdb<br />We shall debug crash1.c using gdb.<br />
  21. 21. gdb<br />We shall debug crash1.c using gdb.<br />gdb is a command line debugger.<br />
  22. 22. gdb<br />We shall debug crash1.c using gdb.<br />gdb is a command line debugger.<br />It is very unfriendly at first...<br />...but very powerful!<br />
  23. 23. Compiling crash1.c<br />Before we debug crash1.c, we need to compile it.<br />We shall then run crash1 from within gdb itself.<br />
  24. 24. Compile crash1.c and load it using gdb<br />$ gcc crash1.c -o crash1<br />
  25. 25. Compile crash1.c and load it using gdb<br />$ gcc crash1.c -o crash1<br />$ gdb crash1<br />GNU gdb (GDB) 7.2<br />Copyright (C) 2010 Free Software Foundation, Inc.<br />License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html><br />This is free software: you are free to change and redistribute it.<br />There is NO WARRANTY, to the extent permitted by law. Type "show copying"<br />and "show warranty" for details.<br />This GDB was configured as "i686-pc-linux-gnu".<br />For bug reporting instructions, please see:<br /><http://www.gnu.org/software/gdb/bugs/>...<br />Reading symbols from /home/user0/crash1...done.<br />(gdb)<br />
  26. 26. Now run it...<br />
  27. 27. Now run it...<br />...with no command line arguments.<br />
  28. 28. Now run it...<br />...with no command line arguments.<br />(gdb) run<br />Starting program: /home/user0/crash1 <br />Program received signal SIGSEGV, Segmentation fault.<br />0x40044c2e in __strtol_internal () from /lib/i686/libc.so.6<br />
  29. 29. Now run it...<br />...with no command line arguments.<br />(gdb) run<br />Starting program: /home/user0/crash1 <br />Program received signal SIGSEGV, Segmentation fault.<br />0x40044c2e in __strtol_internal () from /lib/i686/libc.so.6<br />The program crashes.<br />
  30. 30. Now run it...<br />...with no command line arguments.<br />(gdb) run<br />Starting program: /home/user0/crash1 <br />Program received signal SIGSEGV, Segmentation fault.<br />0x40044c2e in __strtol_internal () from /lib/i686/libc.so.6<br />The program crashes.<br />Where in the code did it crash?<br />
  31. 31. Now run it...<br />...with no command line arguments.<br />(gdb) run<br />Starting program: /home/user0/crash1 <br />Program received signal SIGSEGV, Segmentation fault.<br />0x40044c2e in __strtol_internal () from /lib/i686/libc.so.6<br />The program crashes.<br />Where in the code did it crash?<br />Let us find out where exactly it has crashed.<br />
  32. 32. Use gdb command "backtrace"<br />
  33. 33. Use gdb command "backtrace"<br />It tries to reconstruct frames on the stack.<br />We can find out the sequence of function calls at the time of the crash.<br />
  34. 34. Use gdb command "backtrace"<br />It tries to reconstruct frames on the stack.<br />We can find out the sequence of function calls at the time of the crash.<br />(gdb) backtrace<br />#0 0x40044c2e in __strtol_internal () from /lib/i686/libc.so.6<br />#1 0x40042579 in atoi () from /lib/i686/libc.so.6<br />#2 0x0804838c in main ()<br />
  35. 35. Use gdb command "backtrace"<br />It tries to reconstruct frames on the stack.<br />We can find out the sequence of function calls at the time of the crash.<br />(gdb) backtrace<br />#0 0x40044c2e in __strtol_internal () from /lib/i686/libc.so.6<br />#1 0x40042579 in atoi () from /lib/i686/libc.so.6<br />#2 0x0804838c in main ()<br />Looks like it crashed after calling atoi().<br />
  36. 36. Use gdb command "backtrace"<br />It tries to reconstruct frames on the stack.<br />We can find out the sequence of function calls at the time of the crash.<br />(gdb) backtrace<br />#0 0x40044c2e in __strtol_internal () from /lib/i686/libc.so.6<br />#1 0x40042579 in atoi () from /lib/i686/libc.so.6<br />#2 0x0804838c in main ()<br />Looks like it crashed after calling atoi().<br />That's right. Let us check out the instructions in the code where it has crashed. EIP points to the last instruction executed.<br />
  37. 37. "x" to examine memory<br />
  38. 38. "x" to examine memory<br />(gdb) x/10i $eip<br />=> 0x40044c2e: movzx ecx,BYTE PTR [edi]<br /> 0x40044c31: mov eax,DWORD PTR [esi]<br /> 0x40044c33: movsx edx,cl<br /> 0x40044c36: movzx eax,WORD PTR [eax+edx*2]<br /> 0x40044c3a: and eax,0x2000<br /> 0x40044c3f: test ax,ax<br />
  39. 39. "x" to examine memory<br />(gdb) x/10i $eip<br />=> 0x40044c2e: movzx ecx,BYTE PTR [edi]<br /> 0x40044c31: mov eax,DWORD PTR [esi]<br /> 0x40044c33: movsx edx,cl<br /> 0x40044c36: movzx eax,WORD PTR [eax+edx*2]<br /> 0x40044c3a: and eax,0x2000<br /> 0x40044c3f: test ax,ax<br />So what is x/10i ?<br />
  40. 40. "x" to examine memory<br />(gdb) x/10i $eip<br />=> 0x40044c2e: movzx ecx,BYTE PTR [edi]<br /> 0x40044c31: mov eax,DWORD PTR [esi]<br /> 0x40044c33: movsx edx,cl<br /> 0x40044c36: movzx eax,WORD PTR [eax+edx*2]<br /> 0x40044c3a: and eax,0x2000<br /> 0x40044c3f: test ax,ax<br />So what is x/10i ?<br />"x" displays memory contents in various formats. "i" is for instructions (disassembly). 10 is the count of instructions to disassemble.<br />Here are some more options for "x"<br />
  41. 41. "x" - Examine Memory<br />
  42. 42. Where did the fault occur?<br />
  43. 43. Where did the fault occur?<br />Let us see the faulting instruction again.<br />
  44. 44. Where did the fault occur?<br />Let us see the faulting instruction again.<br />(gdb) x/10i $eip<br />=> 0x40044c2e: movzx ecx,BYTE PTR [edi]<br />
  45. 45. Where did the fault occur?<br />Let us see the faulting instruction again.<br />(gdb) x/10i $eip<br />=> 0x40044c2e: movzx ecx,BYTE PTR [edi]<br />movzx ecx, byte ptr [edi] takes the byte at memory address stored within EDI and copies it into the ECX register.<br />
  46. 46. Where did the fault occur?<br />Let us see the faulting instruction again.<br />(gdb) x/10i $eip<br />=> 0x40044c2e: movzx ecx,BYTE PTR [edi]<br />movzx ecx, byte ptr [edi] takes the byte at memory address stored within EDI and copies it into the ECX register.<br />I see no apparent error here.<br />
  47. 47. Where did the fault occur?<br />Let us see the faulting instruction again.<br />(gdb) x/10i $eip<br />=> 0x40044c2e: movzx ecx,BYTE PTR [edi]<br />movzx ecx, byte ptr [edi] takes the byte at memory address stored within EDI and copies it into the ECX register.<br />I see no apparent error here.<br />It depends on where EDI points to. Let us inspect the registers.<br />
  48. 48. Use the "info registers" command.<br />
  49. 49. Use the "info registers" command.<br />(gdb) info registers<br />eax 0x40136660 0x40136660<br />ecx 0x0 0x0<br />edx 0x0 0x0<br />ebx 0x40148f50 0x40148f50<br />esp 0xbffff8d0 0xbffff8d0<br />ebp 0xbffff928 0xbffff928<br />esi 0x4014b8b8 0x4014b8b8<br />edi 0x0 0x0<br />eip 0x40044c2e 0x40044c2e <__strtol_internal+142><br />eflags 0x10206 [ PF IF RF ]<br />
  50. 50. Use the "info registers" command.<br />(gdb) info registers<br />eax 0x40136660 0x40136660<br />ecx 0x0 0x0<br />edx 0x0 0x0<br />ebx 0x40148f50 0x40148f50<br />esp 0xbffff8d0 0xbffff8d0<br />ebp 0xbffff928 0xbffff928<br />esi 0x4014b8b8 0x4014b8b8<br />edi 0x0 0x0<br />eip 0x40044c2e 0x40044c2e <__strtol_internal+142><br />eflags 0x10206 [ PF IF RF ]<br />I see that EDI is 0.<br />
  51. 51. Use the "info registers" command.<br />(gdb) info registers<br />eax 0x40136660 0x40136660<br />ecx 0x0 0x0<br />edx 0x0 0x0<br />ebx 0x40148f50 0x40148f50<br />esp 0xbffff8d0 0xbffff8d0<br />ebp 0xbffff928 0xbffff928<br />esi 0x4014b8b8 0x4014b8b8<br />edi 0x0 0x0<br />eip 0x40044c2e 0x40044c2e <__strtol_internal+142><br />eflags 0x10206 [ PF IF RF ]<br />I see that EDI is 0.<br />EDI is a NULL pointer. It points to non-existent memory. Hence the crash.<br />
  52. 52. Let us try and inspect local variables and arguments, if any.<br />
  53. 53. Let us try and inspect local variables and arguments, if any.<br />Use the "info locals" and "info args" commands.<br />
  54. 54. Let us try and inspect local variables and arguments, if any.<br />Use the "info locals" and "info args" commands.<br />(gdb) info locals <br />No symbol table info available.<br />(gdb) info args <br />No symbol table info available.<br />
  55. 55. Let us try and inspect local variables and arguments, if any.<br />Use the "info locals" and "info args" commands.<br />(gdb) info locals <br />No symbol table info available.<br />(gdb) info args <br />No symbol table info available.<br />What does this mean?<br />
  56. 56. Let us try and inspect local variables and arguments, if any.<br />Use the "info locals" and "info args" commands.<br />(gdb) info locals <br />No symbol table info available.<br />(gdb) info args <br />No symbol table info available.<br />What does this mean?<br />The compiled binary does not contain debugging information to resolve symbols. <br />
  57. 57. Let us try and inspect local variables and arguments, if any.<br />Use the "info locals" and "info args" commands.<br />(gdb) info locals <br />No symbol table info available.<br />(gdb) info args <br />No symbol table info available.<br />What does this mean?<br />The compiled binary does not contain debugging information to resolve symbols. <br />We need to compile the binary again, this time with proper debugging information.<br />
  58. 58. Quit the debugger<br />(gdb) q<br />
  59. 59. Quit the debugger<br />(gdb) q<br />Recompile with debugging information enabled.<br />$ gcc -g crash1.c -o crash1<br />
  60. 60. Quit the debugger<br />(gdb) q<br />Recompile with debugging information enabled.<br />$ gcc -g crash1.c -o crash1<br />The "-g" flag tells the compiler to include symbolic debugging information in the compiled binary.<br />
  61. 61. Load crash1 in gdb again<br />
  62. 62. Load crash1 in gdb again<br />$ gdb crash1<br />GNU gdb (GDB) 7.2<br />Copyright (C) 2010 Free Software Foundation, Inc.<br />License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html><br />This is free software: you are free to change and redistribute it.<br />There is NO WARRANTY, to the extent permitted by law. Type "show copying"<br />and "show warranty" for details.<br />This GDB was configured as "i686-pc-linux-gnu".<br />For bug reporting instructions, please see:<br /><http://www.gnu.org/software/gdb/bugs/>...<br />Reading symbols from /home/user0/crash1...done.<br />(gdb)<br />
  63. 63. Load crash1 in gdb again<br />$ gdb crash1<br />GNU gdb (GDB) 7.2<br />Copyright (C) 2010 Free Software Foundation, Inc.<br />License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html><br />This is free software: you are free to change and redistribute it.<br />There is NO WARRANTY, to the extent permitted by law. Type "show copying"<br />and "show warranty" for details.<br />This GDB was configured as "i686-pc-linux-gnu".<br />For bug reporting instructions, please see:<br /><http://www.gnu.org/software/gdb/bugs/>...<br />Reading symbols from /home/user0/crash1...done.<br />(gdb)<br />Let us look at the program listing, which is now available from the debugging information. <br />
  64. 64. Use gdb's "list" command<br />
  65. 65. Use gdb's "list" command<br />(gdb) list<br />1 #include <stdio.h><br />2 <br />3 void printnum(int *x);<br />4 <br />5 int main(int argc, char *argv[])<br />6 {<br />7 int number;<br />8 int *pointer;<br />9 <br />10 number = atoi(argv[1]);<br />
  66. 66. Use gdb's "list" command<br />(gdb) list<br />1 #include <stdio.h><br />2 <br />3 void printnum(int *x);<br />4 <br />5 int main(int argc, char *argv[])<br />6 {<br />7 int number;<br />8 int *pointer;<br />9 <br />10 number = atoi(argv[1]);<br />But there are more than 10 lines in this program.<br />
  67. 67. Use gdb's "list" command<br />(gdb) list<br />1 #include <stdio.h><br />2 <br />3 void printnum(int *x);<br />4 <br />5 int main(int argc, char *argv[])<br />6 {<br />7 int number;<br />8 int *pointer;<br />9 <br />10 number = atoi(argv[1]);<br />But there are more than 10 lines in this program.<br />Press Enter on a blank gdb prompt to get another screenful of program listing.<br />
  68. 68. Recap<br />We know that the program crashed when executing atoi(argv[1]).<br />
  69. 69. Recap<br />We know that the program crashed when executing atoi(argv[1]).<br />We shall now set a breakpoint at the statement where atoi() is called.<br />
  70. 70. Recap<br />We know that the program crashed when executing atoi(argv[1]).<br />We shall now set a breakpoint at the statement where atoi() is called.<br />atoi() is called in line #10:<br />7 int number;<br />8 int *pointer;<br />9 <br />10 number = atoi(argv[1]);<br />
  71. 71. Use gdb's "break" command to set a breakpoint.<br />
  72. 72. Use gdb's "break" command to set a breakpoint.<br />(gdb) break 10<br />Breakpoint 1 at 0x804837c: file crash1.c, line 10.<br />
  73. 73. Use gdb's "break" command to set a breakpoint.<br />(gdb) break 10<br />Breakpoint 1 at 0x804837c: file crash1.c, line 10.<br />Now let us run the program.<br />
  74. 74. Use gdb's "break" command to set a breakpoint.<br />(gdb) break 10<br />Breakpoint 1 at 0x804837c: file crash1.c, line 10.<br />Now let us run the program.<br />(gdb) run<br />Starting program: /home/user0/crash1 <br />Breakpoint 1, main (argc=0x1, argv=0xbffff9b4) at crash1.c:10<br />10 number = atoi(argv[1]);<br />
  75. 75. Use gdb's "break" command to set a breakpoint.<br />(gdb) break 10<br />Breakpoint 1 at 0x804837c: file crash1.c, line 10.<br />Now let us run the program.<br />(gdb) run<br />Starting program: /home/user0/crash1 <br />Breakpoint 1, main (argc=0x1, argv=0xbffff9b4) at crash1.c:10<br />10 number = atoi(argv[1]);<br />Process execution is suspended when it reaches the breakpoint. Control is transferred to gdb.<br />
  76. 76. Use gdb's "break" command to set a breakpoint.<br />(gdb) break 10<br />Breakpoint 1 at 0x804837c: file crash1.c, line 10.<br />Now let us run the program.<br />(gdb) run<br />Starting program: /home/user0/crash1 <br />Breakpoint 1, main (argc=0x1, argv=0xbffff9b4) at crash1.c:10<br />10 number = atoi(argv[1]);<br />Process execution is suspended when it reaches the breakpoint. Control is transferred to gdb.<br />Let us now look at argv[1]. gdb will now allow us to inspect variables symbolically.<br />
  77. 77. gdb's "print" command lets us inspect variables.<br />
  78. 78. gdb's "print" command lets us inspect variables.<br />(gdb) print argv[1]<br />$1 = 0x0<br />
  79. 79. gdb's "print" command lets us inspect variables.<br />(gdb) print argv[1]<br />$1 = 0x0<br />argv[1] is the culprit NULL pointer! This is what gets loaded into the EDI register (remember?)<br />
  80. 80. gdb's "print" command lets us inspect variables.<br />(gdb) print argv[1]<br />$1 = 0x0<br />argv[1] is the culprit NULL pointer! This is what gets loaded into the EDI register (remember?)<br />Let us continue with the process execution.<br />
  81. 81. gdb's "print" command lets us inspect variables.<br />(gdb) print argv[1]<br />$1 = 0x0<br />argv[1] is the culprit NULL pointer! This is what gets loaded into the EDI register (remember?)<br />Let us continue with the process execution.<br />(gdb) continue<br />Continuing.<br />Program received signal SIGSEGV, Segmentation fault.<br />0x40044c2e in __strtol_internal () from /lib/i686/libc.so.6<br />
  82. 82. gdb's "print" command lets us inspect variables.<br />(gdb) print argv[1]<br />$1 = 0x0<br />argv[1] is the culprit NULL pointer! This is what gets loaded into the EDI register (remember?)<br />Let us continue with the process execution.<br />(gdb) continue<br />Continuing.<br />Program received signal SIGSEGV, Segmentation fault.<br />0x40044c2e in __strtol_internal () from /lib/i686/libc.so.6<br />As expected, here's the segmentation fault. Verify the value of EDI using "info registers" and the disassembly of the crash using "x/10i $eip"<br />
  83. 83. Bug #1 - Null pointer<br />To fix this problem the programmer needs to check the number of command line arguments before using argv[1] in the program.<br />
  84. 84. Bug #1 - Null pointer<br />To fix this problem the programmer needs to check the number of command line arguments before using argv[1] in the program.<br />For now, we shall run the program with a valid argv[1] supplied.<br />
  85. 85. Bug #1 - Null pointer<br />To fix this problem the programmer needs to check the number of command line arguments before using argv[1] in the program.<br />For now, we shall run the program with a valid argv[1] supplied.<br />On to bug #2.<br />Quit gdb and load crash1 again.<br />
  86. 86. Load crash1 in gdb again.<br />$ gdb crash1<br />GNU gdb (GDB) 7.2<br />...<br />Reading symbols from /home/user0/crash1...done.<br />(gdb)<br />
  87. 87. Load crash1 in gdb again.<br />$ gdb crash1<br />GNU gdb (GDB) 7.2<br />...<br />Reading symbols from /home/user0/crash1...done.<br />(gdb)<br />Run it with argument 1 as 255 (or any number)<br />(gdb) run 255<br />Starting program: /home/user0/crash1 255<br />Program received signal SIGSEGV, Segmentation fault.<br />0x080483b4 in printnum (x=0xff) at crash1.c:17<br />17 printf("The number supplied is %dn", *x);<br />
  88. 88. Load crash1 in gdb again.<br />$ gdb crash1<br />GNU gdb (GDB) 7.2<br />...<br />Reading symbols from /home/user0/crash1...done.<br />(gdb)<br />Run it with argument 1 as 255 (or any number)<br />(gdb) run 255<br />Starting program: /home/user0/crash1 255<br />Program received signal SIGSEGV, Segmentation fault.<br />0x080483b4 in printnum (x=0xff) at crash1.c:17<br />17 printf("The number supplied is %dn", *x);<br />Another segmentation fault. Another crash.<br />
  89. 89. What do we do now?<br />
  90. 90. What do we do now?<br />I thought I asked the questions!<br />
  91. 91. What do we do now?<br />I thought I asked the questions!<br />We see where we crashed by examining frames from the stack. The "backtrace" command.<br />(gdb) backtrace<br />#0 0x080483b4 in printnum (x=0xff) at crash1.c:17<br />#1 0x080483a3 in main (argc=0x2, argv=0xbffff9b4) at crash1.c:12<br />
  92. 92. What do we do now?<br />I thought I asked the questions!<br />We see where we crashed by examining frames from the stack. The "backtrace" command.<br />(gdb) backtrace<br />#0 0x080483b4 in printnum (x=0xff) at crash1.c:17<br />#1 0x080483a3 in main (argc=0x2, argv=0xbffff9b4) at crash1.c:12<br />We crashed inside printnum(). Let us inspect the arguments passed to printnum().<br />
  93. 93. What do we do now?<br />I thought I asked the questions!<br />We see where we crashed by examining frames from the stack. The "backtrace" command.<br />(gdb) backtrace<br />#0 0x080483b4 in printnum (x=0xff) at crash1.c:17<br />#1 0x080483a3 in main (argc=0x2, argv=0xbffff9b4) at crash1.c:12<br />We crashed inside printnum(). Let us inspect the arguments passed to printnum().<br />(gdb) info args<br />x = 0xff<br />
  94. 94. What do we do now?<br />I thought I asked the questions!<br />We see where we crashed by examining frames from the stack. The "backtrace" command.<br />(gdb) backtrace<br />#0 0x080483b4 in printnum (x=0xff) at crash1.c:17<br />#1 0x080483a3 in main (argc=0x2, argv=0xbffff9b4) at crash1.c:12<br />We crashed inside printnum(). Let us inspect the arguments passed to printnum().<br />(gdb) info args<br />x = 0xff<br />Isn't x a pointer to an integer (int *x)?<br />
  95. 95. That's right. x is an integer pointer, set to 0xff.<br />
  96. 96. That's right. x is an integer pointer, set to 0xff.<br />So it points to memory address 0x000000ff?<br />
  97. 97. That's right. x is an integer pointer, set to 0xff.<br />So it points to memory address 0x000000ff?<br />Yes. This memory cannot be referenced. Fetching its contents (*x) results in an error.<br />
  98. 98. That's right. x is an integer pointer, set to 0xff.<br />So it points to memory address 0x000000ff?<br />Yes. This memory cannot be referenced. Fetching its contents (*x) results in an error.<br />How did x get set to 0x000000ff?<br />
  99. 99. That's right. x is an integer pointer, set to 0xff.<br />So it points to memory address 0x000000ff?<br />Yes. This memory cannot be referenced. Fetching its contents (*x) results in an error.<br />How did x get set to 0x000000ff?<br />The answer lies in how printnum() was called.<br />
  100. 100. That's right. x is an integer pointer, set to 0xff.<br />So it points to memory address 0x000000ff?<br />Yes. This memory cannot be referenced. Fetching its contents (*x) results in an error.<br />How did x get set to 0x000000ff?<br />The answer lies in how printnum() was called.<br />Let us switch to its calling frame - frame 1 - and inspect frame 1's local variables.<br />
  101. 101. gdb's "frame <n>" command lets you switch context to other frames.<br />
  102. 102. gdb's "frame <n>" command lets you switch context to other frames.<br />(gdb) frame 1<br />#1 0x080483a3 in main (argc=0x2, argv=0xbffff9b4) at crash1.c:12<br />12 printnum(pointer);<br />
  103. 103. gdb's "frame <n>" command lets you switch context to other frames.<br />(gdb) frame 1<br />#1 0x080483a3 in main (argc=0x2, argv=0xbffff9b4) at crash1.c:12<br />12 printnum(pointer);<br />Inspect frame 1's local variables.<br />
  104. 104. gdb's "frame <n>" command lets you switch context to other frames.<br />(gdb) frame 1<br />#1 0x080483a3 in main (argc=0x2, argv=0xbffff9b4) at crash1.c:12<br />12 printnum(pointer);<br />Inspect frame 1's local variables.<br />(gdb) info locals<br />number = 0xff<br />pointer = 0xff<br />
  105. 105. gdb's "frame <n>" command lets you switch context to other frames.<br />(gdb) frame 1<br />#1 0x080483a3 in main (argc=0x2, argv=0xbffff9b4) at crash1.c:12<br />12 printnum(pointer);<br />Inspect frame 1's local variables.<br />(gdb) info locals<br />number = 0xff<br />pointer = 0xff<br />Do you see the second bug now?<br />
  106. 106. gdb's "frame <n>" command lets you switch context to other frames.<br />(gdb) frame 1<br />#1 0x080483a3 in main (argc=0x2, argv=0xbffff9b4) at crash1.c:12<br />12 printnum(pointer);<br />Inspect frame 1's local variables.<br />(gdb) info locals<br />number = 0xff<br />pointer = 0xff<br />Do you see the second bug now?<br />We are reading the number 255 (0xff) and assigning it to the pointer directly.<br />
  107. 107. Absolutely correct. What should we do instead?<br />
  108. 108. Absolutely correct. What should we do instead?<br />Make the pointer POINT to the number.<br />
  109. 109. Absolutely correct. What should we do instead?<br />Make the pointer POINT to the number.<br />Set the pointer's value to be the ADDRESS of the number and not its value.<br />
  110. 110. Bug #2 - Pointer mess-up<br />The faulting statement is:<br />pointer = number;<br />
  111. 111. Bug #2 - Pointer mess-up<br />The faulting statement is:<br />pointer = number;<br />Instead it should be:<br />pointer = &number; //address of number<br />
  112. 112. Bug #2 - Pointer mess-up<br />The faulting statement is:<br />pointer = number;<br />Instead it should be:<br />pointer = &number; //address of number<br />Let us see what happens at assembly level.<br />Dump instructions at EIP and inspect the registers.<br />
  113. 113. (gdb) frame 0<br />
  114. 114. (gdb) frame 0<br />(gdb) x/10i $eip<br />=> 0x80483b4 <printnum+12>: push DWORD PTR [eax]<br /> 0x80483b6 <printnum+14>: push 0x8048488<br /> 0x80483bb <printnum+19>: call 0x804828c <printf@plt><br /> 0x80483c0 <printnum+24>: add esp,0x10<br /> 0x80483c3 <printnum+27>: leave <br /> 0x80483c4 <printnum+28>: ret <br />
  115. 115. (gdb) frame 0<br />(gdb) x/10i $eip<br />=> 0x80483b4 <printnum+12>: push DWORD PTR [eax]<br /> 0x80483b6 <printnum+14>: push 0x8048488<br /> 0x80483bb <printnum+19>: call 0x804828c <printf@plt><br /> 0x80483c0 <printnum+24>: add esp,0x10<br /> 0x80483c3 <printnum+27>: leave <br /> 0x80483c4 <printnum+28>: ret <br />(gdb) info registers<br />eax 0xff 0xff<br />ecx 0x0 0x0<br />edx 0x0 0x0<br />ebx 0x40148f50 0x40148f50<br />esp 0xbffff938 0xbffff938<br />ebp 0xbffff948 0xbffff948<br />esi 0x40012780 0x40012780<br />edi 0xbffff9b4 0xbffff9b4<br />eip 0x80483b4 0x80483b4 <printnum+12><br />eflags 0x10292 [ AF SF IF RF ]<br />
  116. 116. (gdb) frame 0<br />(gdb) x/10i $eip<br />=> 0x80483b4 <printnum+12>: push DWORD PTR [eax]<br /> 0x80483b6 <printnum+14>: push 0x8048488<br /> 0x80483bb <printnum+19>: call 0x804828c <printf@plt><br /> 0x80483c0 <printnum+24>: add esp,0x10<br /> 0x80483c3 <printnum+27>: leave <br /> 0x80483c4 <printnum+28>: ret <br />(gdb) info registers<br />eax 0xff 0xff<br />ecx 0x0 0x0<br />edx 0x0 0x0<br />ebx 0x40148f50 0x40148f50<br />esp 0xbffff938 0xbffff938<br />ebp 0xbffff948 0xbffff948<br />esi 0x40012780 0x40012780<br />edi 0xbffff9b4 0xbffff9b4<br />eip 0x80483b4 0x80483b4 <printnum+12><br />eflags 0x10292 [ AF SF IF RF ]<br />We are trying to push a value whose address is stored in EAX. This address is 0x000000ff.<br />
  117. 117. There are two PUSHes. The first pushes the contents at address EAX onto the stack.<br />
  118. 118. There are two PUSHes. The first pushes the contents at address EAX onto the stack.<br />EAX stores the address of the pointer x.<br />
  119. 119. There are two PUSHes. The first pushes the contents at address EAX onto the stack.<br />EAX stores the address of the pointer x.<br />DWORD PTR [EAX] implies *x (contents at addr x)<br />
  120. 120. There are two PUSHes. The first pushes the contents at address EAX onto the stack.<br />EAX stores the address of the pointer x.<br />DWORD PTR [EAX] implies *x (contents at addr x)<br />What does the second PUSH do? push 0x08048488<br />
  121. 121. There are two PUSHes. The first pushes the contents at address EAX onto the stack.<br />EAX stores the address of the pointer x.<br />DWORD PTR [EAX] implies *x (contents at addr x)<br />What does the second PUSH do? push 0x08048488<br />0x08048488 looks like a memory address. Notice that the next instruction is a CALL to printf.<br />=> 0x80483b4 <printnum+12>: push DWORD PTR [eax]<br /> 0x80483b6 <printnum+14>: push 0x8048488<br /> 0x80483bb <printnum+19>: call 0x804828c <printf@plt><br />
  122. 122. There are two PUSHes. The first pushes the contents at address EAX onto the stack.<br />EAX stores the address of the pointer x.<br />DWORD PTR [EAX] implies *x (contents at addr x)<br />What does the second PUSH do? push 0x08048488<br />0x08048488 looks like a memory address. Notice that the next instruction is a CALL to printf.<br />=> 0x80483b4 <printnum+12>: push DWORD PTR [eax]<br /> 0x80483b6 <printnum+14>: push 0x8048488<br /> 0x80483bb <printnum+19>: call 0x804828c <printf@plt><br />The two PUSHes set up the parameters passed to printf().<br />
  123. 123. printf()<br />printf("The number supplied is %dn", *x);<br />
  124. 124. printf()<br />printf("The number supplied is %dn", *x);<br /> push DWORD PTR [eax]<br />
  125. 125. printf()<br />printf("The number supplied is %dn", *x);<br /> push DWORD PTR [eax]<br /> push 0x8048488<br />
  126. 126. printf()<br />printf("The number supplied is %dn", *x);<br /> push DWORD PTR [eax]<br /> push 0x8048488<br /> call 0x804828c<br />
  127. 127. printf()<br />printf("The number supplied is %dn", *x);<br /> push DWORD PTR [eax]<br /> push 0x8048488<br /> call 0x804828c<br />Remember our discussion in the tutorial<br />"HOW FUNCTIONS WORK?"<br />
  128. 128. So where does address 0x08048488 point to?<br />
  129. 129. So where does address 0x08048488 point to?<br />It should point to the string:<br />"The number supplied is %dn"<br />
  130. 130. So where does address 0x08048488 point to?<br />It should point to the string:<br />"The number supplied is %dn"<br />Let us use the "x" command and find out. We shall use "x/s" to display the output as a string.<br />
  131. 131. So where does address 0x08048488 point to?<br />It should point to the string:<br />"The number supplied is %dn"<br />Let us use the "x" command and find out. We shall use "x/s" to display the output as a string.<br />(gdb) x/s 0x08048488<br />0x8048488: "The number supplied is %dn"<br />
  132. 132. Disassembling printnum()<br />To wrap this up, let us dive into the assembly code of function printnum().<br />We shall map out the concepts discussed in "HOW FUNCTIONS WORK".<br />
  133. 133. Use the "disassemble" command<br />
  134. 134. Use the "disassemble" command<br />(gdb) disassemble printnum<br />Dump of assembler code for function printnum:<br /> 0x080483a8 <+0>: push ebp<br /> 0x080483a9 <+1>: mov ebp,esp<br /> 0x080483ab <+3>: sub esp,0x8<br /> 0x080483ae <+6>: sub esp,0x8<br /> 0x080483b1 <+9>: mov eax,DWORD PTR [ebp+0x8]<br />=> 0x080483b4 <+12>: push DWORD PTR [eax]<br /> 0x080483b6 <+14>: push 0x8048488<br /> 0x080483bb <+19>: call 0x804828c <printf@plt><br /> 0x080483c0 <+24>: add esp,0x10<br /> 0x080483c3 <+27>: leave <br /> 0x080483c4 <+28>: ret <br />End of assembler dump.<br />
  135. 135. Use the "disassemble" command<br />(gdb) disassemble printnum<br />Dump of assembler code for function printnum:<br /> 0x080483a8 <+0>: push ebp<br /> 0x080483a9 <+1>: mov ebp,esp<br /> 0x080483ab <+3>: sub esp,0x8<br /> 0x080483ae <+6>: sub esp,0x8<br /> 0x080483b1 <+9>: mov eax,DWORD PTR [ebp+0x8]<br />=> 0x080483b4 <+12>: push DWORD PTR [eax]<br /> 0x080483b6 <+14>: push 0x8048488<br /> 0x080483bb <+19>: call 0x804828c <printf@plt><br /> 0x080483c0 <+24>: add esp,0x10<br /> 0x080483c3 <+27>: leave <br /> 0x080483c4 <+28>: ret <br />End of assembler dump.<br />Let us map this disassembly to the various components of a function.<br />
  136. 136. printnum() disassembly<br />Prologue<br /> push ebp<br /> mov ebp,esp<br /> sub esp,0x8<br /> sub esp,0x8<br /> mov eax,DWORD PTR [ebp+0x8]<br /> push DWORD PTR [eax]<br /> push 0x8048488<br /> call 0x804828c <printf@plt><br /> add esp,0x10<br /> leave <br /> ret <br />Body<br />Epilogue<br />Return<br />
  137. 137. printnum() disassembly<br />Prologue<br /> push ebp<br /> mov ebp,esp<br /> sub esp,0x8<br /> sub esp,0x8<br /> mov eax,DWORD PTR [ebp+0x8]<br />> push DWORD PTR [eax]<br /> push 0x8048488<br /> call 0x804828c <printf@plt><br /> add esp,0x10<br /> leave <br /> ret <br />Body<br />Epilogue<br />Return<br />Crash occurs at "push dword ptr [eax]".<br />
  138. 138. printnum() disassembly<br />Prologue<br /> push ebp<br /> mov ebp,esp<br /> sub esp,0x8<br /> sub esp,0x8<br /> mov eax,DWORD PTR [ebp+0x8]<br />> push DWORD PTR [eax]<br /> push 0x8048488<br /> call 0x804828c <printf@plt><br /> add esp,0x10<br /> leave <br /> ret <br />Body<br />Epilogue<br />Return<br />Crash occurs at "push dword ptr [eax]".<br />Let us see how the stack is built up.<br />
  139. 139. Before printnum() is called<br /> push ebp<br /> mov ebp,esp<br /> sub esp,0x8<br /> sub esp,0x8<br /> mov eax,DWORD PTR [ebp+0x8]<br /> push DWORD PTR [eax]<br /> push 0x8048488<br /> call 0x804828c <printf@plt><br /> add esp,0x10<br /> leave <br /> ret <br />Pointer x is pushed on the stack...<br />0x000000ff<br />ESP<br />...<br />EBP<br />
  140. 140. Before printnum() is called<br />> push ebp<br /> mov ebp,esp<br /> sub esp,0x8<br /> sub esp,0x8<br /> mov eax,DWORD PTR [ebp+0x8]<br /> push DWORD PTR [eax]<br /> push 0x8048488<br /> call 0x804828c <printf@plt><br /> add esp,0x10<br /> leave <br /> ret <br />...and printnum is CALLed.<br />Saved EIP<br />ESP<br />0x000000ff<br />param 1<br />...<br />EBP<br />
  141. 141. Prologue<br />push ebp<br />> mov ebp,esp<br /> sub esp,0x8<br /> sub esp,0x8<br /> mov eax,DWORD PTR [ebp+0x8]<br /> push DWORD PTR [eax]<br /> push 0x8048488<br /> call 0x804828c <printf@plt><br /> add esp,0x10<br /> leave <br /> ret <br />Old EBP<br />ESP<br />Save the old frame pointer.<br />Saved EIP<br />0x000000ff<br />param 1<br />...<br />EBP<br />
  142. 142. Prologue<br />push ebp<br />mov ebp,esp<br />> sub esp,0x8<br /> sub esp,0x8<br /> mov eax,DWORD PTR [ebp+0x8]<br /> push DWORD PTR [eax]<br /> push 0x8048488<br /> call 0x804828c <printf@plt><br /> add esp,0x10<br /> leave <br /> ret <br />Old EBP<br />EBP<br />ESP<br />Set the EBP to the current frame.<br />Saved EIP<br />0x000000ff<br />param 1<br />...<br />
  143. 143. Prologue<br />push ebp<br />mov ebp,esp<br /> sub esp,0x8<br /> sub esp,0x8<br />> mov eax,DWORD PTR [ebp+0x8]<br /> push DWORD PTR [eax]<br /> push 0x8048488<br /> call 0x804828c <printf@plt><br /> add esp,0x10<br /> leave <br /> ret <br />...<br />ESP<br />...<br />...<br />...<br />Old EBP<br />EBP<br />Leave some space on the stack (16 bytes)<br />Saved EIP<br />0x000000ff<br />param 1<br />...<br />
  144. 144. Body<br />push ebp<br />mov ebp,esp<br /> sub esp,0x8<br /> sub esp,0x8<br />mov eax,DWORD PTR [ebp+0x8]<br />> push DWORD PTR [eax]<br /> push 0x8048488<br /> call 0x804828c <printf@plt><br /> add esp,0x10<br /> leave <br /> ret <br />...<br />ESP<br />...<br />...<br />...<br />Old EBP<br />EBP<br />EAX = 0x000000ff<br />Saved EIP<br />0x000000ff<br />param 1<br />...<br />
  145. 145. Segmentation Fault!<br />push ebp<br />mov ebp,esp<br /> sub esp,0x8<br /> sub esp,0x8<br />mov eax,DWORD PTR [ebp+0x8]<br />>push DWORD PTR [eax]<br /> push 0x8048488<br /> call 0x804828c <printf@plt><br /> add esp,0x10<br /> leave <br /> ret <br />...<br />ESP<br />...<br />...<br />...<br />Old EBP<br />EBP<br />Memory at 0x000000ff cannot be referenced.<br />Saved EIP<br />0x000000ff<br />param 1<br />...<br />
  146. 146. Segmentation Fault!<br />push ebp<br />mov ebp,esp<br /> sub esp,0x8<br /> sub esp,0x8<br />mov eax,DWORD PTR [ebp+0x8]<br />>push DWORD PTR [eax]<br /> push 0x8048488<br /> call 0x804828c <printf@plt><br /> add esp,0x10<br /> leave <br /> ret <br />...<br />ESP<br />...<br />...<br />...<br />Old EBP<br />EBP<br />Memory at 0x000000ff cannot be referenced.<br />Saved EIP<br />0x000000ff<br />param 1<br />What will stack memory contain at this moment?<br />...<br />
  147. 147. Examine stack memory and registers<br />
  148. 148. Examine stack memory and registers<br />(gdb) x/16xw $esp<br />0xbffff938: 0x0000000a 0x00000000 0x40042550 0x40012df8<br />0xbffff948: 0xbffff968 0x080483a3 0x000000ff 0xbffff9b4<br />0xbffff958: 0xbffff968 0x080483dc 0x000000ff 0x000000ff<br />0xbffff968: 0xbffff988 0x4002e7f7 0x00000002 0xbffff9b4<br />
  149. 149. Examine stack memory and registers<br />(gdb) x/16xw $esp<br />0xbffff938: 0x0000000a 0x00000000 0x40042550 0x40012df8<br />0xbffff948: 0xbffff968 0x080483a3 0x000000ff 0xbffff9b4<br />0xbffff958: 0xbffff968 0x080483dc 0x000000ff 0x000000ff<br />0xbffff968: 0xbffff988 0x4002e7f7 0x00000002 0xbffff9b4<br />(gdb) info registers<br />eax 0xff<br />ecx 0x0<br />edx 0x0<br />ebx 0x40148f50<br />esp 0xbffff938<br />ebp 0xbffff948<br />esi 0x40012780<br />edi 0xbffff9b4<br />eip 0x80483b4<br />
  150. 150. Examine stack memory and registers<br />(gdb) x/16xw $esp<br />0xbffff938: 0x0000000a 0x00000000 0x40042550 0x40012df8<br />0xbffff948: 0xbffff968 0x080483a3 0x000000ff 0xbffff9b4<br />0xbffff958: 0xbffff968 0x080483dc 0x000000ff 0x000000ff<br />0xbffff968: 0xbffff988 0x4002e7f7 0x00000002 0xbffff9b4<br />(gdb) info registers<br />eax 0xff<br />ecx 0x0<br />edx 0x0<br />ebx 0x40148f50<br />esp 0xbffff938<br />ebp 0xbffff948<br />esi 0x40012780<br />edi 0xbffff9b4<br />eip 0x80483b4<br />0x0000000a<br />ESP0xbffff938:<br />0x00000000<br />0xbffff93c:<br />0x40042550<br />0xbffff940:<br />0xbffff944:<br />0x40012df8<br />EBP0xbffff948:<br />0xbffff968<br /> Saved EIP 0xbffff94c:<br />0x080483a3<br /> Param 1 0xbffff950:<br />0x000000ff<br />0xbffff954:<br />0xbffff9b4<br />0xbffff958:<br />0xbffff968<br />
  151. 151. Recap<br />We have seen how to analyze crashes and identify causes of errors.<br />We also saw a lot of gdb commands and when to use them.<br />
  152. 152. Summary of gdb commands<br />
  153. 153. A few gdb commands<br />
  154. 154. A few more gdb commands<br />
  155. 155. Review<br />
  156. 156. END<br />photo: Brian Searle - bit.ly/fpcxY9<br />

×