我想编写启动另一个程序(进程)的程序。我正在使用Visual Studio 2015中的MASM64(ml64.exe)。
程序不起作用。没有显示任何内容。在调试器中,我得到了访问冲突。
我不知道我的代码有什么问题。
我的代码:
extrn ExitProcess : proc
extrn MessageBoxA : proc
extrn CreateProcessA : proc
PROCESS_INFORMATION struct
hProcess DWORD ?
hThread DWORD ?
dwProcessId DWORD ?
dwThreadId DWORD ?
PROCESS_INFORMATION ends
STARTUPINFOA struct
cb DWORD ?
lpReserved DWORD ?
lpDesktop DWORD ?
lpTitle DWORD ?
dwX DWORD ?
dwY DWORD ?
dwXSize DWORD ?
dwYSize DWORD ?
dwXCountChars DWORD ?
dwYCountChars DWORD ?
dwFillAttribute DWORD ?
dwFlags DWORD ?
wShowWindow WORD ?
cbReserved2 WORD ?
lpReserved2 DWORD ?
hStdInput DWORD ?
hStdOutput DWORD ?
hStdError DWORD ?
STARTUPINFOA ends
.const
MB_ICONINFORMATION equ 40h
ERROR_ALREADY_EXISTS equ 0B7h
NORMAL_PRIORITY_CLASS equ 020h
.data
szText db "This is first application which creates new process using CreateProcessA.", 00h
szCaption db "Information",00h
processInfo PROCESS_INFORMATION <>
startupInfo STARTUPINFOA <>
szProcName db "D:\Apps\SampleApp.exe", 00h
.code
Main proc
;not sure if correct - begin
lea rax, processInfo
lea rbx, startupInfo
sub rsp, 60h
push rax
push rbx
push 00h
push 00h
push NORMAL_PRIORITY_CLASS
push 00h
mov r9, 00h
mov r8, 00h
mov rdx, 00h
lea rcx, szProcName
call CreateProcessA
add rsp, 60h
;not sure if correct - end
sub rsp, 28h
mov r9, MB_ICONINFORMATION
lea r8, szCaption
lea rdx, szText
xor rcx, rcx
call MessageBoxA
add rsp, 28h
Exit:
xor rcx, rcx
call ExitProcess
Main endp
end
的build.bat
@echo off
ml64.exe prog1.asm /link /entry:Main /subsystem:windows /defaultlib:"kernel32.Lib" /defaultlib:"user32.Lib"
pause
提前感谢您的帮助。
答案 0 :(得分:3)
您应该检查PROCESS_INFORMATION和STARTUPINFO结构的定义,因为它们可能在x86和x64之间有所不同。例如,句柄被定义为指针,而不是DWORD(32位整数)。
答案 1 :(得分:3)
除了初始化STARTUPINFO
并确保使用正确的数据类型(指针在64位Windows中为64位宽,而DWORD
始终为32位),您还需要正确分配参数区域(有时也被称为&#34;影子空间&#34;):
参数区域始终位于堆栈的底部(即使使用了
alloca
),因此在任何函数调用期间它始终与返回地址相邻。
它至少包含四个条目,但始终有足够的空间来容纳可能被调用的任何函数所需的所有参数 请注意,总是为寄存器参数分配空间,即使参数本身从不归属于堆栈也是如此;确保被调用者已为其所有参数分配了空间。
强调我的,here
假设正确初始化了所需的所有数据结构,可能会调用CreateProcessA
:
; Stack is assumed aligned here
push rax ; Not aligned (08h)
push rbx ; Aligned (10h)
push 00h ; Not aligned (18h)
push 00h ; Aligned (20h)
push NORMAL_PRIORITY_CLASS ; Not aligned (28h)
push 00h ; Aligned (30h)
; Make room for the first four (register) parameters
; Stack is aligned, not need to subtract 28h, just 20h (4*8)
sub rsp, 20h
mov r9, 00h
mov r8, 00h
mov rdx, 00h
lea rcx, szProcName
call CreateProcessA
add rsp, 50h
请注意,调用者负责在通话后清理堆栈。
您想要使用sub rsp, ...
在堆栈上保留空间并非完全错误
当然,你必须正确地进行数学计算,但最重要的是,该技术不能立即与push
es兼容。
一旦有sub rsp, ...
,就需要一个或多个mov [rsp+...], ...
类型的间接存储来设置参数。
push
es只会再次移动堆栈指针 ,使以前的所有工作都无用。
答案 2 :(得分:0)
在你的函数中保留足够的空间来调用具有如此多参数的子函数。 在函数序言中使用.ALLOCSTACK
然后只需分配整个参数列表
mov QWORD PTR [rsp+48h], rax
mov QWORD PTR [rsp+40h], rbx
mov QWORD PTR [rsp+38h], 00h
mov QWORD PTR [rsp+30h], 00h
mov QWORD PTR [rsp+28h], NORMAL_PRIORITY_CLASS
mov QWORD PTR [rsp+20h], 00h
xor r9, r9 ; pass 0
xor r8, r8 ; pass 0
xor edx, edx ; pass 0 (higher DWORD becomes always also zero, saving the REX-byte)
lea rcx, szProcName
call CreateProcessA
答案 3 :(得分:0)
这是一个有点老的问题,但因为我刚刚解决了它,所以把它写下来。 现在我正在努力解决同样的问题,但 NASM。 问题是相同的,但语法会有所不同。 您的问题是您的 STARTUPINFOA 和 PROCESS_INFORMATION 不正确,原因有两个:
正确的 NASM 语法结构如下:
; https://msdn.microsoft.com/library/windows/desktop/ms686331.aspx
STRUC _STARTUPINFOA
.cb: resq 1
.lpReserved: resq 1
.lpDesktop: resq 1
.lpTitle: resq 1
.dwX: resd 1
.dwY: resd 1
.dwXSize: resd 1
.dwYSize: resd 1
.dwXCountChars: resd 1
.dwYCountChars: resd 1
.dwFillAttribute: resd 1
.dwFlags: resd 1
.wShowWindow: resd 1
.cbReserved2: resd 1
.lpReserved2: resq 1
.hStdInput: resq 1
.hStdOutput: resq 1
.hStdError: resq 1
ENDSTRUC
; https://msdn.microsoft.com/library/windows/desktop/ms684873.aspx
STRUC _PROCESS_INFORMATION
.hProcess: resq 1
.hThread: resq 1
.dwProcessId: resd 1
.dwThreadId: resd 1
ENDSTRUC
稍微解释一下:
如果遵循结构,大多数字段都可以正确填充,但有几个字段不同。原因是结构填充。 MS 编译器选择结构中最大的元素,然后将所有其他字段填充到它。为了举个例子,STARTUPINFOA案例如下所示:
当我完成正确的填充后,它就像魅力一样。祝你好运! :)