Lab 4: GDBWinter 2023

This lab will introduce you to memory layout and GDB concepts that are critical for performing buffer-overflow attacks in project 4. You will not be actively attacking code in this lab, but instead dissecting an innocent C file to understand how it appears in memory when compiled and during execution.


Memory layout and buffer-overflow exploitation depends on details of the target system. For this lab and the corresponding project, you must create your solutions inside the Project 4 VM, as it has been configured to standardize the stack layout and disable certain security features that would complicate your work.

  • Follow the setup instructions on the Project 4 VM page. You only need to do this once; if you follow the guide for this lab, you can use the same VM and workflow for the project.

  • Check out your starter code from the GitHub template inside the VM. You must do this in a folder in the native Linux filesystem. It won’t work correctly if you use a shared folder located in the host OS.

You do not need to worry about running ./ or ./ for the lab.



You will make use of the GDB debugger for dynamic analysis within the VM, which you should recall from EECS 280. Useful commands that you may not know are disassemble, info reg, x, and stepi. See the GDB help for details, and don’t be afraid to experiment. This quick reference may also be useful:

x86 Assembly

These are many good references for Intel’s assembly language, but note that our project targets use the 32-bit x86 ISA. The stack is organized differently in x86 and x64. If you are reading any online documentation, ensure that it is based on the x86 architecture, not x64.

Big versus Little Endian

The final task in this lab will involve endianness. Refer to this guide if you are unfamiliar with endianness or need a refresher. Also, there are helpful images you can find via Google that visually diagram this concept.


You will write all answers in one file (submit.txt). The line number for each task’s responses is indicated in bolded brackets before each question.

Task 1 - Examine assembly code

Open a terminal within VS Code and start GDB on the lab4 compiled binary ($ gdb lab4). Using GDB’s disas (shorthand for disassemble) command, answer the following questions regarding the assembly code:

[1] Where in memory is the line of assembly code that makes a call to foo()? Record the address on line 1 of submit.txt.

[2] Where in memory does the function foo() begin? Record the address on line 2.

[3] At the top of the C code, we imported various libraries. The methods provided by these libraries appear within our compiled binary, too. Where in memory does the standard library function printf() exist? Record the address on line 3.

Takeaway: Be mindful of the difference between the address of the line that calls a function versus the address of the function itself.

Task 2 - Peer into stack during execution

Project 4 will require extensive use of GDB’s x/ command to look at stack contents at various stages of execution. First, you will need to set a breakpoint at your desired location, then run the binary. Assuming you have opened GDB with the compiled lab4 binary ($ gdb lab4), use the following commands:

(gdb) break [address/function]
(gdb) run

The break parameter can be either an explicit address (such as one of your submissions in the previous task in the form *0x########) or the name of a function.

Refer to the GDB reference sheet ( as well as the lab slides for various ways to print the stack using x/

[4] Set a breakpoint at foo. Run the code. At the start of the foo function, what is the hexadecimal value of the byte stored at 0xfff6ffad? Record the byte value in the form 0x## on line 4 of submit.txt.

Continue to the end of execution

(gdb) c
Remove your previously set breakpoint

(gdb) delete

[5] Set a breakpoint at *0x08049bf5 and run the code. Note the string that is initialized in line 7 of the C code. Locate the address on the stack where the word “THIS” begins. That is, where the capital “T” is stored. Record the address on line 5. Hint: The ASCII hex value corresponding to “!” is 0x21 and “T” is 0x54.

Takeaway: The x/ command is extremely versatile. Make use of its features when constructing and debugging an attack.

Task 3 - Endianness

Keeping track of big versus little endian can get confusing when examining the stack. The final portion of this lab will familiarize you with the output style from different GBD x/ commands regarding endianness. Note that x86 uses little-endian byte ordering.

Continue to the end of previous execution and remove breakpoints again.

Set a breakpoint at foo. Run the code, then examine the stack below the base pointer in the following two ways:

(gdb) x/16bx $ebp
(gdb) x/4wx $ebp

In both cases, we are viewing the same bytes, but you’ll realize they appear to be in a different order. Printing the individual bytes displays how the memory is actually configured (little-endian in our case for x86). Printing the bytes in word form clumps every 4 bytes together, interprets them as a little-endian integer, and displays them as a big-endian word (as numbers are naturally represented).

Using your knowledge of stack convention when a function is called, as well as the output to the previous x/ commands displaying the stack contents beneath the base pointer, answer the following:

[6] What is the value of the input parameter to foo() written in big-endian? Record your answer on line 6 in the form 0x########.

[7] What is the value of the input parameter to foo() written in little-endian? Record your answer on line 7 in the form 0x########.

Takeaway: While word-style is more consise, when in doubt use individual byte-style printing as it shows what the stack space actually looks like.


Submit the following file to the Autograder by the deadline:

  • submit.txt