To build a stack buffer overflow based exploit, you first need to understand how variables, function arguments and return values are laid out on the stack.

In this section, you will learn how the clang compiler lays out the stack frame.

Using a file editor, save the contents of the program shown below into a file named stack-layout.c. Save the file in the directory where you ran docker run. You can do this outside the docker container.

    

        
        
            __attribute__((noinline))
long f() {
    volatile char buffer1[4];
    volatile char buffer2[7];
    buffer1[3] = 10;
    buffer2[6] = 20;
    return buffer1[3]+buffer2[6];
}

int main() {
    f();
    return 0;
}
        
    

The file will show up in the docker container under the path /armlearningpaths.

Compile it with the following command at your docker prompt:

    

        
        clang -O1 -S -fno-asynchronous-unwind-tables stack-layout.c

        
    

This produces the disassembly file stack-layout.s. When you open it, you see the following disassembly for function f:

    

        
        
            	sub	sp, sp, #16
	mov	w8, #10
	mov	w9, #20
	strb	w8, [sp, #12]
	strb	w9, [sp, #8]
	ldrb	w8, [sp, #12]
	ldrb	w9, [sp, #8]
	add	x0, x9, x8
	add	sp, sp, #16
	ret
        
    

Here you can see that the first instruction sub sp, sp #16 reserves 16 bytes on the stack as the stack frame for this function. The stack on AArch64 grows downwards, which means it grows towards the lower memory addresses.

The next 4 instructions store value 10 and 20 to buffer1[3] and buffer2[6].

From the offset [sp, #8] and [sp, #12] you can compute the frame layout.

Exercise 1

Draw the frame layout of function f: How are buffer1 and buffer2 laid out in the 16 bytes that are reserved?

The answer to this exercise can be found in the Answers section .

For the main function, clang produces the following assembly:

    

        
        
            	stp	x29, x30, [sp, #-16]!           // 16-byte Folded Spill
	mov	x29, sp
	bl	f
	mov	w0, wzr
	ldp	x29, x30, [sp], #16             // 16-byte Folded Reload
	ret
        
    

The bl f instruction in the middle performs a function call to function f. It writes the address of the instruction after it – in this case mov w0, wzr – to register x30. Then it lets the program continue to the first instruction of function f.

Register x30 is also often called the link register, or lr.

The ret instruction at the end of the main function will branch to the address stored in register x30. The correct address that function main should return to was set by a bl main instruction somewhere else in the program.

Because the bl f instruction overwrites the value in x30, the original value in x30 at the start of function main needs to be saved somewhere. It is saved on the stack by the instruction stp x29, x30, [sp, #-16]!.

The stp instruction is a “store pair” instruction. It stores 2 registers to a location in memory. The location in memory in this case is [sp, #-16]!, that is the address in register sp (also known as the stack pointer), at an offset of -16. The exclamation mark indicates that the value in register sp should be updated to the value with the offset. In other words, after this instruction executes, sp will have a value that is 16 less than before the instruction executes. [sp, #-16]! is a Pre-index addressing mode type of instruction.

Register x29 contains the “ frame pointer ”, and is sometimes called fp. The frame pointer points to a location in the stack frame that contains the “frame record”. The frame record has two fields: a pointer to the frame record of the function that called the current function; and the address the current function needs to return to.

At the start of function main, it contains the value of the frame pointer of the previous function. Since the function f that is being called might change the value of x29, that value also needs to be stored in the function prologue. It will be restored by the instruction ldp x29, x30, [sp], #16 in the function epilogue. [sp], #16 is a post-index addressing mode type of instruction: it specifies to load from the address in register sp, and then to increase the value in sp with 16.

Exercise 2

Draw the frame layout of function main.

  • Which variables or register values are stored on the stack at which location?
  • Where do the frame pointer (x29) and stack pointer (sp) point to just before the call to function f, which is done by instruction bl f?

The answer to this exercise can be found in the Answers section .

Back
Next