Whenever I try to do CreateProcess, it gives me an error "MOD_NOT_FOUND". This is the line of code I'm using:
invoke CreateProcess,NULL,addr process,NULL,NULL,TRUE,0,NULL,NULL,addr si_info,addr pi_info
Where process is "cmd.exe".
Why does it give me this error and how can I fix it?
Try specifying the full path to CMD.EXE as long as you are running NT, 2K or later otherwise MD.EXE is not available on earlier versions.
Shouldn't cmd.exe be enough?
lpCommandLine
[in, out] Pointer to a null-terminated string that specifies the command line to execute. The maximum length of this string is 32K characters.
It seems all I need to specify is the command to execute on the command line and that is "cmd.exe". I don't want to have to specify the whole path because it can be different on different machines.
Use ShellExecute instead
With ShellExecute, don't you have to use the full path to the exe?
If you use %SystemRoot%\, it will correctly expand to c:\windows\ or c:\winnt\ or whatever. This will solve the problem of cmd.exe being in differing places on differing machines.
so, %SystemRoot%\system32\cmd.exe could expand to c:\windows\system32\cmd.exe or c:\winnt\system32\cmd.exe depending on the installation.
hth,
Paul
And if you want to use CreateProcess, then GetSystemDirectory will get you the directory where cmd.exe resides.
MSDN web site says this old-fashion call should be replaced by a call to SHGetFolderPath. There is a CSIDL_SYSTEM constant that can be used to get the system folder path.
If I give CreateProcess the full path of cmd.exe, it doesn't give any errors, but it doesn't start cmd.exe and when I debug it in Olly, it stops at some "repne" line right after CreateProcessA is called.
..voila!
.386
.model flat, stdcall
option casemap:none
include windows.inc
include kernel32.inc
includelib kernel32.lib
include shell32.inc
includelib shell32.lib
.data
cmd_exe db "cmd.exe",0
.code
start:
invoke ShellExecute, NULL,NULL,ADDR cmd_exe,NULL,NULL,SW_SHOWNORMAL
invoke ExitProcess, NULL
end start
(You may want to fill in some of the other parameters, for parent window and default directory)
And obviously it will only work on machines where cmd.exe is available ::)
I want to use CreateProcess over ShellExecute because I need to use si to capture the output on the screen when I execute commands like ipconfig or netstat.
And I really want to know what that mod not found error means. What causes it?
Add your whole program and we'll take a look :U
I haven't done anything else to the program except the CreateProcess part. I put a MessageBox in there to show the return value, but it returns NULL.
.486
.model flat, stdcall
option casemap :none
StartCmd proto
; includes
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
.data
cmdexe db "cmd.exe",0
.code
start:
invoke StartCmd
invoke ExitProcess,eax
StartCmd Proc
LOCAL stin:STARTUPINFO
LOCAL prin:PROCESS_INFORMATION
mov stin.cb,sizeof stin
mov stin.wShowWindow,SW_HIDE
mov stin.dwFlags,STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW
invoke CreateProcess,NULL,addr cmdexe,NULL,NULL,TRUE,0,NULL,NULL,addr stin,addr prin
invoke MessageBox,NULL,eax,0,MB_OK
invoke CloseHandle,prin.hProcess
invoke CloseHandle,prin.hThread
ret
StartCmd endp
end start
EarlCrapstone,
Here is a program I picked up somewhere that uses CreateProcess to start cmd.exe
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
MyProc PROTO
.DATA
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CommandLine db "cmd.exe",0
;
.CODE
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
start:
invoke MyProc
invoke ExitProcess,0
MyProc PROC
LOCAL rect:RECT
LOCAL hRead:DWORD
LOCAL hWrite:DWORD
LOCAL hRead2:DWORD
LOCAL hWrite2:DWORD
LOCAL startupinfo:STARTUPINFO
LOCAL pinfo:PROCESS_INFORMATION
LOCAL buffer[1024]:byte
LOCAL buffer2[1024]:byte
LOCAL bytesRead:DWORD
LOCAL bytesWritten:DWORD
LOCAL hdc:DWORD
LOCAL sat:SECURITY_ATTRIBUTES
mov sat.nLength,sizeof SECURITY_ATTRIBUTES
mov sat.lpSecurityDescriptor,NULL
mov sat.bInheritHandle,TRUE
invoke CreatePipe,addr hRead,addr hWrite,addr sat,NULL
invoke CreatePipe,addr hRead2,addr hWrite2,addr sat,NULL
mov startupinfo.cb,sizeof STARTUPINFO
invoke GetStartupInfo,addr startupinfo
mov eax, hWrite
mov startupinfo.hStdOutput,eax
mov startupinfo.hStdError,eax
mov startupinfo.dwFlags, STARTF_USESHOWWINDOW+ STARTF_USESTDHANDLES
mov startupinfo.wShowWindow,SW_HIDE
invoke CreateProcess, NULL, addr CommandLine, NULL, NULL, TRUE, NULL, NULL, NULL, addr startupinfo, addr pinfo
invoke CloseHandle,hWrite
.while 1
.while TRUE
invoke RtlZeroMemory,addr buffer,1024
invoke ReadFile,hRead,addr buffer,1023,addr bytesRead,NULL
.if eax==NULL
.break
.endif
invoke StdOut,addr buffer
.endw
invoke CloseHandle,hRead2
.while TRUE
invoke RtlZeroMemory,addr buffer2,1024
invoke StdIn,addr buffer2,sizeof buffer2
invoke WriteFile,hWrite2,addr buffer2,sizeof buffer2,addr bytesWritten,NULL
.IF eax==NULL
.break
.endif
.endw
.endw
invoke ExitProcess,0
invoke CloseHandle,hRead
invoke CloseHandle,hWrite
ret
MyProc ENDP
end start
EDIT: Added a batch file to build the project.
hth,
Paul
[attachment deleted by admin]
Hmmm. If I try to recompile pipe.asm with no changes, the new pipe.exe does not execute cmd.exe and gives the error MOD_NOT_FOUND. The problem must be on my side, but I don't know what it could be.
EDIT: If I try to compile it with the batch file it works fine. The problem was that I was compiling it like a regular exe file, but it's a console exe. When I run it though, cmd.exe does not show up in task manager as running. Is it suppose to do that? When I compile mine as a console app, I can't tell if cmd.exe is actually started. When I debug it, it still stops on a "rep" line, so I don't think its working.
Earl,
It sounds to me like your path variable is incorrect, corrupt or missing. Go to the Device Manager, Advainced, then Environment Variables and scope it out.
Mine looks like this...
Quote
%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;D:\PBWin80\BIN;D:\PBCC40\BIN
hth,
Paul
Here's mine:
%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;C:\Program Files\QuickTime\QTSystem\
Looks fine.
Yes it does.
Make this change to the program...
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CommandLine db "c:\windows\system32\cmd.exe",0
If this does not work then go to the system32 directory and make very sure that cmd.exe resides there.
Paul
Earl,
Ijust noticed you got it to work. About not seeing it in the TaskManager, when it runs correctly; you will see Pipe.exe running as an Application and also as a Process. The Application is Pipe.exe, but the Process is really CMD.EXE, okay.
Also, the console thing, I thought that might be a part of your problem and is why I modified my attachment. Tale a close look at the batch file it is my version of Mark's excellent batch file and should serve all your needs.
Paul
I got the pipe.exe program to work, but mine still stops on a line that starts with "rep" and I have to hold SHIFT+F8 in OllyDbg to get it to continue on with the program. It does this whether I compile it as a console app or not.
EarlCrapstone,
With one addition and one change, I was able to get your program to work.
.486
.model flat, stdcall
option casemap :none
StartCmd proto
; includes
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
.data
cmdexe db "cmd.exe",0
.code
start:
invoke StartCmd
invoke ExitProcess,eax
StartCmd Proc
LOCAL stin:STARTUPINFO
LOCAL prin:PROCESS_INFORMATION
invoke GetStartupInfo, addr stin ; You forgot this
mov stin.cb,sizeof stin
mov stin.wShowWindow,SW_HIDE
mov stin.dwFlags,STARTF_USESHOWWINDOW ; The other flag that was here refuses to work
invoke CreateProcess,NULL,addr cmdexe,NULL,NULL,TRUE,0,NULL,NULL,addr stin,addr prin
invoke CloseHandle,prin.hProcess
invoke CloseHandle,prin.hThread
ret
StartCmd endp
end start
I also removed the Message Box as eax would need to be converted before display and cmd.exe is working, anyway.
Paul
[attachment deleted by admin]
Thank you so much! It works perfectly now.
Earl,
No problem. Right now, the program has no error checking. I am sure you will add it now that you have gotten it to work.
Happy coding! :U
Paul
Do you know why STARTF_USESTDHANDLES doesn't work in the line:
mov stin.dwFlags,STARTF_USESHOWWINDOW+ STARTF_USESTDHANDLES
It works in the Pipe example.
Earl,
It is because of the fundamental difference between the two programs. Yours creates a process but does not create a pipe.
With a pipe you need to use standard handles so STDInput and STDOutput will work properly. For your purposes, it is not important. Also, in the Pipe example, I am using CreatePipe.
hth,
Paul
So it wont work unless I create a pipe?
Earl,
Yes, also, take a look at Iczelion's Tutorial 21.
hth,
Paul