我正在尝试调用 crt-shny exp。如果通过jmp跟随标签func,调用exp,需要从rsp(第一版代码)中减去32个字节。如果通过调用(第二个选项),则为 40 个字节,否则 windows 会出错。为什么会这样?
format PE64 console
include 'E:\Fresh\include\win64a.inc'
entry main1
section '.data' data readable writeable
msg db '%lf',10,0
section '.text' code readable executable
main1:
and rsp,-16
sub rsp,32
mov rax,1.0
movq xmm7,rax
jmp func
label1:
mov rcx,msg
movq rdx,xmm7
call [printf]
mov rcx,0
call [ExitProcess]
func:
movsd xmm0,xmm7
sub rsp,32
call [exp_0]
add rsp,32
movsd xmm7,xmm0
jmp label1
section '.idata' import data readable writeable
library kernel32,'KERNEL32.DLL', msvcrt,'MSVCRT.DLL'
import msvcrt, printf,'printf',exp_0,'exp'
import kernel32, ExitProcess, 'ExitProcess'
format PE64 console
include 'E:\Fresh\include\win64a.inc'
entry main1
section '.data' data readable writeable
msg db '%lf',10,0
section '.text' code readable executable
main1:
and rsp,-16
sub rsp,32
mov rax,1.0
movq xmm7,rax
call func
mov rcx,msg
movq rdx,xmm7
call [printf]
mov rcx,0
call [ExitProcess]
func:
movsd xmm0,xmm7
sub rsp,40
call [exp_0]
add rsp,40
movsd xmm7,xmm0
ret
section '.idata' import data readable writeable
library kernel32,'KERNEL32.DLL', msvcrt,'MSVCRT.DLL'
import msvcrt, printf,'printf',exp_0,'exp'
import kernel32, ExitProcess, 'ExitProcess'
jmp
和的区别在于call
它将call
下一条指令的地址压入堆栈,然后跳转到指定的地址。也就是相差8个字节。根据VC++ calling convention
,堆栈必须在 16 个字节上对齐(堆栈对齐)。任何使用未对齐堆栈调用的函数,结果call
都是 ,它要做的第一件事就是对齐堆栈。通常这是push rbp
,但你的程序and rsp,-16
。选项1:
选项 2:
在第二种情况下,它会
sub rsp, 40
补偿这 8 个字节。结论:如果
func
这是一个函数并且通过调用call
,那么它的行为应该像一个函数。