why do procedures need shadow stack or a frame stack?

Unfortunately, I don’t have much experience with 64-bit code, so I don’t know about the exact details:

Actually, you don’t need a shadow stack or a stack frame. But some 64-bit functions require rsp to be 16-byte-aligned.

This means that the value of rsp must be a multiple of 16 when a function is called.

If your function looks like this:

myFunction:
    lea rcx, QWORD PTR [message]
    call [print_message] ;it covered return address to bad address
    ...

… then rsp is a multiple of 16 before the instruction call myFunction. And call myFunction pushes 8 bytes to the stack, so rsp is no longer a multiple of 16 (but the value of rsp can be written as 16*n+8).

When you perform call [print_message], rsp is not a multiple of 16 and the program crashes if the function print_message requires rsp to be 16-byte-aligned.

The instructions sub rsp, 8 and push rbp will subtract 8 from the rsp so the value of rsp is a multiple of 16 again.

The background are certain CPU instructions that require an address that is a multiple of 16 as argument. Example:

print_message:
    sub rsp, 24
      ; The next instruction will crash if rsp is not
      ; a multiple of 16. This is the case if rsp was
      ; not a multiple of 16 before the
      ; "call print_message" instruction
    paddd xmm0, [rsp]

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top