(很抱歉我的英语不好,因为我来自韩国(
我试过这个代码
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, 8
和push 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]