MASM64(ml64.exe)调用CreateProcessA触发访问冲突问题排查
问题分析
- 第一个错误:
STARTUPINFOA结构体的cb字段类型定义错误
Windows API定义中STARTUPINFOA的cb是4字节DWORD类型,你代码中定义为qword(8字节),直接导致整个结构体内存布局偏移错误,API读取结构体参数完全异常。 - 第二个错误:x64调用约定参数传递规则错误
Windows x64采用fastcall调用约定,前4个参数依次通过rcx、rdx、r8、r9传递,剩余参数按从右往左的顺序压栈。你当前压栈的参数顺序完全颠倒,且多分配了不需要的栈空间,导致API读取到的栈参数全部错误。 - 第三个错误:栈16字节对齐规则违反
Windows x64要求调用API前RSP必须16字节对齐,你代码中压栈和额外减20h的操作打破了栈对齐,movaps是SSE指令,要求操作数地址必须16字节对齐,地址不对齐就会直接触发访问违规,这是你报错的直接原因。 - 第四个错误:未预留前4个参数的32字节影子空间
Windows x64调用约定要求调用者必须为前4个寄存器传递的参数预留32字节的栈空间,供被调用函数临时保存寄存器使用,你代码中没有预留该空间,会导致API运行时覆盖栈上的有效数据。
修正后的代码示例
;ml64.exe CreateProcessA.asm /link /subsystem:console /entry:main /LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\um\x64" /defaultlib:kernel32.lib extrn CreateProcessA : proc extrn ExitProcess : proc PROCESS_INFORMATION struct hProcess qword ? hThread qword ? dwProcessId dword ? dwThreadId dword ? PROCESS_INFORMATION ends STARTUPINFOA struct cb dword sizeof ( STARTUPINFOA ) ; 修正为DWORD类型 lpReserved qword ? lpDesktop qword ? lpTitle qword ? dwX dword ? dwY dword ? dwXSize dword ? dwYSize dword ? dwXCountChars dword ? dwYCountChars dword ? dwFillAttribute dword ? dwFlags dword ? wShowWindow word ? cbReserved2 word 3 dup ( ? ) lpReserved2 qword ? hStdInput qword ? hStdOutput qword ? hStdError qword ? STARTUPINFOA ends .const NORMAL_PRIORITY_CLASS equ 020h .data processInfo PROCESS_INFORMATION <> startupInfo STARTUPINFOA <> szProcName db "C:\Windows\System32\cmd.exe", 00h .code main proc ; 先预留32字节影子空间 + 对齐调整,保证调用时RSP 16字节对齐 sub rsp, 28h ; 32字节影子空间 + 8字节对齐调整,满足16字节对齐要求 ; 前4个参数通过寄存器传递 lea rcx, szProcName ; 参数1:lpApplicationName mov rdx, 00h ; 参数2:lpCommandLine mov r8, 00h ; 参数3:lpProcessAttributes mov r9, 00h ; 参数4:lpThreadAttributes ; 剩余参数从右往左压栈 push rax ; 占位保证压栈后栈对齐 lea rax, processInfo push rax ; 参数10:lpProcessInformation lea rax, startupInfo push rax ; 参数9:lpStartupInfo push 00h ; 参数8:lpCurrentDirectory push 00h ; 参数7:lpEnvironment push NORMAL_PRIORITY_CLASS ; 参数6:dwCreationFlags push 00h ; 参数5:bInheritHandles call CreateProcessA ; 调用完平衡栈 add rsp, 28h + 6*8 ; 正常退出 mov ecx, 0 call ExitProcess main endp end
内容的提问来源于stack exchange,提问作者Slava
相关产品推荐
相关产品推荐

