AutoHotkey Community

It is currently May 26th, 2012, 11:46 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: GetCommandLine
PostPosted: February 12th, 2007, 3:56 pm 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
This retrieves a start-up command-line of an application, once getting PID of it. If an application is an interactive service, then need an Debug privilege which I omitted for simplicity. If an application is a non-interactive service, then have to rely on other means.

Code:
/*
Process, Exist, myprog.exe
pid := ErrorLevel
*/

; Replace the WinTitle with the correct one
WinGet, pid, PID, ahk_class TTOTAL_CMD

VarSetCapacity(sFilePath, 260)
VarSetCapacity(sCmdLine, 512)

pFunc := DllCall("GetProcAddress"
   , "Uint", DllCall("GetModuleHandle", "str", "kernel32.dll")
   , "str", "GetCommandLineA")

hProc := DllCall("OpenProcess", "Uint", 0x043A, "int", 0, "Uint", pid)

hThrd := DllCall("CreateRemoteThread", "Uint", hProc, "Uint", 0, "Uint", 0
   , "Uint", pFunc, "Uint", 0, "Uint", 0, "Uint", 0)

DllCall("WaitForSingleObject", "Uint", hThrd, "Uint", 0xFFFFFFFF)
DllCall("GetExitCodeThread", "Uint", hThrd, "UintP", pcl)
DllCall("ReadProcessMemory", "Uint", hProc, "Uint", pcl, "str", sCmdLine, "Uint", 512, "Uint", 0)

DllCall("psapi\GetModuleFileNameExA", "Uint", hProc, "Uint", 0, "str", sFilePath, "Uint", 260)
; DllCall("psapi\GetProcessImageFileNameA", "Uint", hProc, "str", sFilePath, "Uint", 281)

DllCall("CloseHandle", "Uint", hThrd)
DllCall("CloseHandle", "Uint", hProc)

MsgBox % sFilePath . " | " . sCmdLine



Last edited by Sean on February 13th, 2007, 1:38 pm, edited 2 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 12th, 2007, 4:30 pm 
Mmm, it was already there: process list+file names+command lines but it has other features there that might not be wanted, so it is nice to have it isolated. Thanks.


Report this post
Top
  
Reply with quote  
 Post subject: Re: GetCommandLine
PostPosted: February 13th, 2007, 11:24 am 
Offline

Joined: October 14th, 2006, 8:46 am
Posts: 18
Sean wrote:
This retrieves a start-up command-line of an application, once getting PID of it.


This helps a lot! Thanks!


Report this post
Top
 Profile  
Reply with quote  
 Post subject: Re: GetCommandLine
PostPosted: November 19th, 2008, 12:01 am 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8776
Dear Sean, :)

You wrote:
If an application is an interactive service, then need an Debug privilege which I omitted for simplicity.


What happens to script/sCmdLine if my script unknowingly uses the PID of a Service ?

:)


Report this post
Top
 Profile  
Reply with quote  
 Post subject: Re: GetCommandLine
PostPosted: November 19th, 2008, 10:37 am 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
SKAN wrote:
What happens to script/sCmdLine if my script unknowingly uses the PID of a Service ?

Most of the DllCall()'s in the code will (silently) fail, without Debug privilege.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 19th, 2008, 10:41 am 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8776
Thank you Sean :)

One more help please. Have I wrapped it right?

Code:
GetCommandLine( PID ) { ;  by Sean          www.autohotkey.com/forum/viewtopic.php?t=16575
 Static pFunc
 If ! ( hProcess := DllCall( "OpenProcess", UInt,0x043A, Int,0, UInt, PID ) )
        Return 
 If pFunc=
    pFunc := DllCall( "GetProcAddress", UInt
           , DllCall( "GetModuleHandle", Str,"kernel32.dll" ), Str,"GetCommandLineA" )
 hThrd := DllCall( "CreateRemoteThread", UInt,hProcess, UInt,0, UInt,0, UInt,pFunc, UInt,0
        , UInt,0, UInt,0 ),  DllCall( "WaitForSingleObject", UInt,hThrd, UInt,0xFFFFFFFF )
 DllCall( "GetExitCodeThread", UInt,hThrd, UIntP,pcl ), VarSetCapacity( sCmdLine,512 )
 DllCall( "ReadProcessMemory", UInt,hProcess, UInt,pcl, Str,sCmdLine, UInt,512, UInt,0 )
 DllCall( "CloseHandle", UInt,hThrd ), DllCall( "CloseHandle", UInt,hProcess )
Return sCmdLine
}

SetDebugPrivilege() {
 ;PROCESS_QUERY_INFORMATION=0x400, TOKEN_ADJUST_PRIVILEGES=0x20, SE_PRIVILEGE_ENABLED:=0x2
 hProcess := DllCall( "OpenProcess", UInt,0x400,Int,0,UInt,DllCall("GetCurrentProcessId"))
 DllCall( "Advapi32.dll\LookupPrivilegeValueA", UInt,0, Str,"SeDebugPrivilege", UIntP,lu )
  ; TOKEN_PRIVILEGES Structure : www.msdn.microsoft.com/en-us/library/aa379630(VS.85).aspx
 VarSetCapacity( TP,16,0), NumPut( 1,TP,0,4 ),  NumPut( lu,TP,4,8 ), NumPut( 0x2,TP,12,4 )
 DllCall( "Advapi32.dll\OpenProcessToken", UInt,hProcess, UInt,0x20, UIntP,hToken )
 Result :=  DllCall( "Advapi32.dll\AdjustTokenPrivileges"
                 , UInt,hToken, UInt,0, UInt,&TP, UInt,0, UInt,0, UInt,0 )
 DllCall( "CloseHandle", UInt,hProcess ), DllCall( "CloseHandle", UInt,hToken )
Return Result
}

SetDebugPrivilege()
MsgBox, % GetCommandLine( DllCall( "GetCurrentProcessId" ) )
Process, Exist, svchost.exe
MsgBox,0, %errorLevel%, % GetCommandLine( errorLevel )


Edit 2009-06-22: Added DelimitParameters()

The following function can convert the obtained command line into pipe delimited string to ease Loop, Parse or StringSplit

Code:
DelimitParameters( CommandLine,D="|" ) {     ; Supplementary function for GetCommandLine()
 tempVar := CommandLine           ; www.autohotkey.com/forum/viewtopic.php?p=232199#232199
 Loop {
 StringReplace,tempVar,tempVar,%Param%
 CommandLine := DllCall( "shlwapi\PathGetArgsA", Str,CommandLine,Str )
 StringReplace,Param,tempVar,%CommandLine%
 DllCall( "shlwapi\PathUnquoteSpacesA", Str,Param )
 IfEqual,Param,,Return SubStr(DelimitedString,2)
 DelimitedString = %DelimitedString%%D%%Param%
}}


Last edited by SKAN on June 22nd, 2009, 9:53 am, edited 2 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 19th, 2008, 12:31 pm 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
SKAN wrote:
Have I wrapped it right?

Yes, looks fine to me.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 19th, 2008, 12:40 pm 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8776
I could not grasp much from shimanov's GetRemoteCommandLine() and then saw your comment.
Thanks for sharing this wonderful code Sean.

:)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 19th, 2008, 1:05 pm 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
SKAN wrote:
I could not grasp much from shimanov's GetRemoteCommandLine() and then saw your comment.

Oh, my comment there was not correct. Looks like he tracked down the procedures of GetCommandLineA in the Debugger. As it's an implementation detail, relying on it should be the last choice.
BTW, my preferred method is indeed utilizing PEB, but it relies on the undocumented features unfortunately.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 19th, 2008, 1:42 pm 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8776
Sean wrote:
As it's an implementation detail, relying on it should be the last choice.


er.. I intend to use this only on all running AHK instances.. Is there a way to ascertain if compiled AHK is running as a service ?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 19th, 2008, 2:27 pm 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
SKAN wrote:
Sean wrote:
As it's an implementation detail, relying on it should be the last choice.
er.. I intend to use this only on all running AHK instances..

I meant it only for GetRemoteCommandLine function. APIs and features my code used are all well-documented (although there is one loop-hole in the code: stack-mismatch after the call in the remote thread).

Quote:
Is there a way to ascertain if compiled AHK is running as a service?

The first one hitting me is retrieving the parent process (identifier) of the target process and checking if it's services.exe, if it's what you meant by service. It can be done using CreateToolhelp32Snapshot and Process32First/Process32Next, with Debug privilege enabled.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 19th, 2008, 3:18 pm 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8776
Sean wrote:
The first one hitting me is retrieving the parent process (identifier) of the target process and checking if it's services.exe, if it's what you meant by service. It can be done using CreateToolhelp32Snapshot and Process32First/Process32Next, with Debug privilege enabled.


Search reveals there are example calls already posted. Thank you very much for the pointer.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 19th, 2008, 3:48 pm 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
SKAN wrote:
Search reveals there are example calls already posted. Thank you very much for the pointer.

After reading your post more carefully, I now noticed this:
Quote:
only on all running AHK instances

As AHK can't be started as a service by itself, meaning that AHK can't be a (direct) child process of services.exe, I guess what you're really after is obtaining the user's name of a process and checking if it's NT AUTHORITY/SYSTEM. If turned out so, may use OpenProcess -> OpenProcessToken -> GetTokenInformation -> LookupAccountSid.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 19th, 2008, 4:08 pm 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8776
Sean wrote:
what you're really after is obtaining the user's name of a process and checking if it's NT AUTHORITY/SYSTEM.


Almost exactly, except I thought of comparing it to A_Username. Would it not work? :roll:

Quote:
may use OpenProcess -> OpenProcessToken -> GetTokenInformation -> LookupAccountSid.


Thank you.. That looks simple.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 19th, 2008, 4:34 pm 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
SKAN wrote:
Almost exactly, except I thought of comparing it to A_Username. Would it not work? :roll:

It depends. If want to rule out not only services but also all ones run as other accounts than the current user, then A_UserName should be used than SYSTEM.


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: Bing [Bot], oldbrother, Rajat and 61 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group