为什么程序需要堆栈帧或阴影堆栈



(很抱歉我的英语不好,因为我来自韩国(

我试过这个代码

lea rcx, QWORD PTR [message]
call [print_message] ;it covered return address to bad address
xor rcx, rcx
ret

然后坠毁了
在那之后,我尝试了另一种方法

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

这两个代码是有效的,但问题是…,为什么程序需要这些东西
这让我很好奇

问题来自的真实代码

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

不幸的是,我对64位代码没有太多经验,所以我不知道确切的细节:

实际上,您不需要阴影堆栈或堆栈框架。但是一些64位函数要求rsp是16字节对齐的。

这意味着当调用函数时,rsp的值必须是16的倍数。

如果你的功能是这样的:

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

则CCD_ 3在指令CCD_。并且call myFunction将8个字节推送到堆栈,因此rsp不再是16的倍数(但rsp的值可以写为16*n+8(。

执行call [print_message]时,rsp不是16的倍数,如果函数print_message要求rsp为16字节对齐,则程序崩溃。

指令sub rsp, 8push rbp将从rsp中减去8,因此rsp的值再次是16的倍数。

背景是某些CPU指令,它们需要一个16的倍数的地址作为自变量。示例:

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]

相关内容

  • 没有找到相关文章

最新更新