(Sorry for my bad english, because i am from South Korea)
i tried this code
lea rcx, QWORD PTR [message]
call [print_message] ;it covered return address to bad address
xor rcx, rcx
ret
and crashed...
after that happen, i tried another way
sub rsp, 8 ;shadow stack
lea rcx, QWORD PTR [message]
call [print_message]
add rsp, 8
ret
; stack frame
push rbp
mov rbp, rsp
lea rcx, QWORD PTR [message]
call [print_message]
mov rsp, rbp
pop rbp
ret
these 2 codes is working, but the problem is..., why procedure need these thing?
this makes me curious
real code that the problem came from
extern __imp_MessageBoxA : QWORD
.data
message db "1234", 0
.code
entry_point proc
sub rsp, 8
xor ecx, ecx
lea rdx, QWORD PTR [message]
lea r8, QWORD PTR [message]
mov r9, 0
call [__imp_MessageBoxA] ;stdcall
add rsp, 8
ret
entry_point endp
end
CodePudding user response:
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]