0

(对不起我的英语不好,因为我来自韩国)

我试过这段代码

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
4

1 回答 1

0

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

实际上,您不需要影子堆栈或堆栈帧。但是一些 64 位函数需要rsp16 字节对齐。

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

如果您的函数如下所示:

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

... thenrsp是指令前 16 的倍数call myFunction。并将call myFunction8 个字节压入堆栈,因此rsp不再是 16 的倍数(但 的值rsp可以写为 16*n+8)。

当你执行call [print_message],rsp不是 16 的倍数时,如果函数print_message需要rsp16 字节对齐,程序就会崩溃。

指令sub rsp, 8andpush rbp将从中减去 8,rsp因此 的值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]
于 2022-01-03T10:24:15.313 回答