Jump to content
Sign in to follow this  
ProgAndy

Get CMDLine of a process

Recommended Posts

ProgAndy

I wanted to know, if you can get the CMD-Line of a process in AutoIt, too and so I tried to convert the Code from http://www.winterdom.com/dev/ptk/cmdline.html ( SOURCECODE ) Th result is this:

#include <Array.au3>
#include<Memory.au3>
#include<WinAPI.au3>
#include<Constants.au3>
#include<Security.au3>
#include<StructureConstants.au3>
;AU3 by Prog@ndy after http://www.winterdom.com/dev/ptk/cmdline.c
;~ ####################################################################
;~ ## File: ProcessCMDline.au3
;~ ## Project: CMDLINE
;~ ## Desc: see in next part
;~ ## Revision: Created 10.06.2008
;~ ##
;~ ## Copyright AU3-Code: 2008, Prog@ndy
;~ ##
;~ ####################################################################

;~ ////////////////////////////////////////////////////////////////////
;~ //
;~ // File:         cmdline.c
;~ // Project:  cmdline
;~ //
;~ // Desc:     this is a sample program that shows how to
;~ //               get the command line for almost any process
;~ //               on the system for WinNT 4 and up.
;~ //
;~ // Revisions:    Created 12/02/99
;~ //
;~ // Copyright(C) 1999, Tomas Restrepo. All rights reserved
;~ //
;~ ///////////////////////////////////////////////////////////////////
;~ #define UNICODE
;~ #define _UNICODE

;~ #include <windows.h>
;~ #include <stdio.h>
;~ #include <tchar.h>


;~ #pragma comment(lib, "advapi32.lib")

;~ // found by experimentation this is where the some
;~ // process data block is found in an NT machine.
;~ // On an Intel system, 0x00020000 is the 32
;~ // memory page. At offset 0x0498 is the process
;~ // current directory (or startup directory, not sure yet)
;~ // followed by the system's PATH. After that is the
;~ // process full command command line, followed by
;~ // the exe name and the window
;~ // station it's running on
;~ #define BLOCK_ADDRESS    (LPVOID)0x00020498
;~ // Additional comments:
;~ // From experimentation I've found
;~ // two notable exceptions where this doesn't seem to apply:
;~ // smss.exe : the page is reserved, but not commited
;~ //           which will get as an invalid memory address
;~ //           error
;~ // crss.exe : although we can read the memory, it's filled
;~ //             with 00 comepletely. No trace of command line
;~ //             information


Func ALIGN_DWORD($DWORD)
    If BitAND($DWORD, 0xFFFFFFFC) Then
        Return BitAND($DWORD, 0xFFFFFFFC) + sizeof("DWORD")
    Else
        Return $DWORD
    EndIf
EndFunc   ;==>ALIGN_DWORD

Global Const $READ_CONTROL = 0x20000
Global Const $STANDARD_RIGHTS_ALL = 0x1F0000
Global Const $STANDARD_RIGHTS_EXECUTE = ($READ_CONTROL)
Global Const $STANDARD_RIGHTS_READ = ($READ_CONTROL)
Global Const $STANDARD_RIGHTS_REQUIRED = 0xF0000
Global Const $STANDARD_RIGHTS_WRITE = ($READ_CONTROL)

Global Const $TOKEN_USER = 0x8
Global Const $TOKEN_STRING_SIZE = 4608
Global Const $TOKEN_SOURCE_LENGTH = 8
Global Const $TOKEN_READ = BitOR($STANDARD_RIGHTS_READ, $TOKEN_QUERY)
;~ Global Const $TOKEN_QUERY_SOURCE = 0x10
;~ Global Const $TOKEN_QUERY = 0x8
Global Const $TOKEN_PAREN = 0x4
Global Const $TOKEN_OR = 0x2
Global Const $TOKEN_OPERATOR = 0x2
Global Const $TOKEN_OPENPAREN = 0x4
Global Const $TOKEN_NOTIN = 0x20
;~ Global Const $TOKEN_IMPERSONATE = 0x4
Global Const $TOKEN_EXECUTE = $STANDARD_RIGHTS_EXECUTE
Global Const $TOKEN_CLOSEPAREN = 0x5
;~ Global Const $TOKEN_DUPLICATE = 0x2
;~ Global Const $TOKEN_ASSIGN_PRIMARY = 0x1
Global Const $TOKEN_AND = 0x3
;~ Global Const $TOKEN_ADJUST_SESSIONID = 0x100
;~ Global Const $TOKEN_ADJUST_PRIVILEGES = 0x20
;~ Global Const $TOKEN_ADJUST_GROUPS = 0x40
;~ Global Const $TOKEN_ADJUST_DEFAULT = 0x80
;~ Global Const $TOKEN_WRITE As Long = BitOR($STANDARD_RIGHTS_WRITE , $TOKEN_ADJUST_PRIVILEGES , $TOKEN_ADJUST_GROUPS , $TOKEN_ADJUST_DEFAULT)
Global Const $TOKEN_ALL_ACCESS_P = BitOR($STANDARD_RIGHTS_REQUIRED, $TOKEN_ASSIGN_PRIMARY, $TOKEN_DUPLICATE, $TOKEN_IMPERSONATE, $TOKEN_QUERY, $TOKEN_QUERY_SOURCE, $TOKEN_ADJUST_PRIVILEGES, $TOKEN_ADJUST_GROUPS, $TOKEN_ADJUST_DEFAULT)
Global Const $TOKEN_ALL_ACCESS = BitOR($STANDARD_RIGHTS_REQUIRED, $TOKEN_ASSIGN_PRIMARY, $TOKEN_DUPLICATE, $TOKEN_IMPERSONATE, $TOKEN_QUERY, $TOKEN_QUERY_SOURCE, $TOKEN_ADJUST_PRIVILEGES, $TOKEN_ADJUST_GROUPS, $TOKEN_ADJUST_SESSIONID, $TOKEN_ADJUST_DEFAULT)


$x = ProcessList()
$name = StringLeft(@ScriptName, StringInStr(@ScriptName, ".", 1, -1))
$len = StringLen($name)
For $i = 1 To $x[0][0]
    
Next
Func _GetProcessCmdLine($hProcess)
    Local $lpszCmdLine
    Local Const $BLOCK_ADDRESS = Ptr(0x00020498)

    Local $lpBuffer ;LPBYTE
    Local $lpPos ;LPBYTE                         // offset from the start of the buffer
    Local $dwBytesRead; DWORD
    Local $tag_MEMORY_BASIC_INFORMATION = "ptr BaseAddress;ptr AllocationBase; DWORD AllocationProtect; dword RegionSize; DWORD State; DWORD Protect; DWORD Type"
    
    Local $mbi = DllStructCreate($tag_MEMORY_BASIC_INFORMATION);MEMORY_BASIC_INFORMATION
    Local $tagSYSTEMINFO = "DWORD dwOemId;DWORD dwPageSize;ptr lpMinimumApplicationAddress;ptr lpMaximumApplicationAddress; ulong_PTR dwActiveProcessorMask;" & _
            "DWORD dwNumberOfProcessors; DWORD dwProcessorType; DWORD dwAllocationGranularity; ushort wProcessorLevel; ushort wProcessorRevision;"
    Local $sysinfo = DllStructCreate($tagSYSTEMINFO);SYSTEM_INFO
    Local $bError = False;BOOL

;~  __try {
;~      // Get the system page size by using GetSystemInfo()
    _WinAPI_GetSystemInfo($sysinfo)
;~      // allocate one on the heap to retrieve a full page
;~      // of memory
    $lpBuffer = _MemGlobalAlloc(DllStructGetData($sysinfo, "dwPageSize"))
;~      if ( lpBuffer == NULL )
;~          SIGNAL_ERROR ();

;~      // first of all, use VirtualQuery to get the start of the memory
;~      // block
    _WinAPI_VirtualQueryEx($hProcess, $BLOCK_ADDRESS, $mbi)
;~          SIGNAL_ERROR ();
;~
;~      // read memory begining at the start of the page
;~      // after that, we know that the env strings block
;~      // will be 0x498 bytes after the start of the page
    _WinAPI_ReadProcessMemory($hProcess, DllStructGetData($mbi, "BaseAddress"), $lpBuffer, DllStructGetData($sysinfo, "dwPageSize"), $dwBytesRead)
;~      if ( !ReadProcessMemory ( hProcess, mbi.BaseAddress, (LPVOID)lpBuffer,
;~                                sysinfo.dwPageSize, &dwBytesRead ) )
;~           SIGNAL_ERROR ();

;~      // now we've got the buffer on our side of the fence.
;~      // first, lpPos points to a string containing the current directory
;~      /// plus the path.
;~      lpPos = lpBuffer + ((DWORD)BLOCK_ADDRESS - (DWORD)mbi.BaseAddress);

    $pos = DllStructCreate("byte[" & DllStructGetData($sysinfo, "dwPageSize") & "]", $lpBuffer)
    $Data = DllStructGetData($pos, 1)

    $lpPos = (Number($BLOCK_ADDRESS) - Number(DllStructGetData($mbi, "BaseAddress")))
    $x = BinaryMid($Data, $lpPos)
    $z = BinaryLen(StringToBinary(BinaryToString($x, 3), 3))
    $x = BinaryMid($x, BinaryLen(StringToBinary($z, 3)))
;~  MsgBox(0, '', $x)
    $x = StringRegExpReplace($x, "0x.*?00000000.*?0000", "0x", 1)
;~ $x = StringReplace($x,"0000","0021")
    Do
        $x = StringReplace($x, "0x0000", "0x00", 1)
    Until @extended = 0
;~ MsgBox(0, '', $x)
    $z = BinaryToString(BinaryMid($x, 1), 3)
    $pos = ""
    _MemGlobalFree($lpBuffer)
    Return $z
;~ MsgBox(0, '', $Data & @CRLF & $x &  @CRLF & )
;~      lpPos = lpPos + (wcslen ( (LPWSTR)lpPos ) + 1) * sizeof(WCHAR); >
;~      // now goes full path an filename, aligned on a DWORD boundary
;~      // skip it
;~      lpPos = (LPBYTE)ALIGN_DWORD((DWORD)lpPos); >
;~      lpPos = lpPos + (wcslen ( (LPWSTR)lpPos ) + 1) * sizeof(WCHAR);
;~      // hack: Sometimes, there will be another '\0' at this position
;~      // if that's so, skip it
;~      if ( *lpPos == '\0' ) lpPos += sizeof(WCHAR);
;~      // now we have the actual command line
;~      // copy it to the buffer
;~      wcsncpy  ( lpszCmdLine, (LPWSTR)lpPos, MAX_PATH );
;~      // make sure the path is null-terminted
;~      lpszCmdLine[MAX_PATH-1] = L'\0';

;~  }
;~  __finally  {
;~      // clean up
;~      if ( lpBuffer != NULL ) free ( lpBuffer );
;~      return bError ? FALSE : TRUE;
;~  }
;~
EndFunc   ;==>_GetProcessCmdLine
Func _WinAPI_GetSystemInfo(ByRef $SysInfoStruct)
    Local $aResult

    $aResult = DllCall("Kernel32.dll", "int", "GetSystemInfo", "ptr", DllStructGetPtr($SysInfoStruct))
    Return $aResult[0]
EndFunc   ;==>_WinAPI_GetSystemInfo

;~ SIZE_T WINAPI VirtualQueryEx(
;~   __in      HANDLE hProcess,
;~   __in_opt  LPCVOID lpAddress,
;~   __out     PMEMORY_BASIC_INFORMATION lpBuffer,
;~   __in      SIZE_T dwLength
;~ );
Func _WinAPI_VirtualQueryEx(ByRef $hProcess, $BLOCK_ADDRESS, ByRef $buffer)
    Local $aResult

    $aResult = DllCall("Kernel32.dll", "dword", "VirtualQueryEx", "hwnd", $hProcess, "ptr", $BLOCK_ADDRESS, "ptr", DllStructGetPtr($buffer), "dword", DllStructGetSize($buffer))
    Return $aResult[0]
EndFunc   ;==>_WinAPI_VirtualQueryEx



;~ ////////////////////////////////////////////////////////////////////
;~ //
;~ // Function: EnableTokenPrivilege()
;~ //
;~ // Added: 20/02/99
;~ //
;~ // Description: Enables a specific token privilege
;~ //
;~ ///////////////////////////////////////////////////////////////////
Func EnableTokenPrivilege($privilege)

    Local $hToken;HANDLE                        // process token
    Local $tp = DllStructCreate("int Count;int64 LUID[1];int Attributes[1]")
    ;TOKEN_PRIVILEGES           // token provileges
    Local $dwSize;              DWORD

;~  // initialize privilege structure
;~  ZeroMemory (&tp, sizeof (tp));
    DllStructSetData($tp, "Count", 1)
    Local $hProcess = _WinAPI_GetCurrentProcess()
    $hToken = _Security__OpenProcessToken($hProcess, $TOKEN_ALL_ACCESS)
    If $hToken = 0 Then Return False
;~  // open the process token
;~  if ( !OpenProcessToken ( GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken ) )
;~      return FALSE;


    DllStructSetData($tp, "LUID", _Security__LookupPrivilegeValue("", $privilege))
    If DllStructGetData($tp, "LUID") = 0 Then
        _WinAPI_CloseHandle($hToken)
        Return False
    EndIf
    DllStructSetData($tp, "Attributes", 0x2)
;~  // look up the privilege LUID and enable it
;~  if ( !LookupPrivilegeValue ( NULL, privilege, &tp.Privileges[0].Luid ) )
;~  {
;~      CloseHandle ( hToken);
;~      return FALSE;
;~  }
;~
;~  tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

;~  // adjust token privileges
    _Security__AdjustTokenPrivileges($hToken, False, DllStructGetPtr($tp), 0, 0, $dwSize)
    If @error Then
        _WinAPI_CloseHandle($hToken)
        Return False
    EndIf
;~  if ( !AdjustTokenPrivileges ( hToken, FALSE, &tp, 0, NULL, &dwSize ) )
;~  {
;~      CloseHandle ( hToken);
;~      return FALSE;
;~  }

;~  // clean up
    _WinAPI_CloseHandle($hToken)
    Return True;
EndFunc   ;==>EnableTokenPrivilege


Func sizeof($x)
    Return DllStructGetSize(DllStructCreate($x))
EndFunc   ;==>sizeof

; Internal Funcs End

; Get Debug provilege
EnableTokenPrivilege("SeDebugPrivilege")

; The UDF to call :)
Func _GetCMDLine($pid)
    $pid = ProcessExists($pid)
    If $pid = 0 Then Return SetError(1, 0, "")
    Local $hProcess = _WinAPI_OpenProcess(BitOR($PROCESS_VM_OPERATION, $PROCESS_VM_READ, $PROCESS_QUERY_INFORMATION), False, $pid)
    Local $CMD = _GetProcessCmdLine($hProcess)
    If $CMD = "" Then
        Return SetError(2, 0, "")
        _WinAPI_CloseHandle($hProcess)
    EndIf
    Return $CMD
EndFunc   ;==>_GetCMDLineoÝ÷ Ù«­¢+Øìa5A1(¥¹±ÕÅÕ½ÐíAɽÍÍ
5±¥¹¹ÔÌÅÕ½Ðì)5Í ½à À°ÌäìÌäì°}Ñ
51¥¹ ÅÕ½Ðí¥É½à¹áÅÕ½Ð줤

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites
ProgAndy

Yes, but i wanted to try it without WMI :P


*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites
Michel Claveau

Hi, ProgAndy!

Your solution is good for Windows-2000 (& server).

Because WMI on W-2000 don't give the command-line of a process (this feature come in WMI with XP & +).

I know that, because I use cmdline.exe since several years.

@+

Michel Claveau

Edited by Michel Claveau

Share this post


Link to post
Share on other sites
arcker

already done by PaulIA and me, and implemented in UDF but good UDF then.


-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]

Share this post


Link to post
Share on other sites
UEZ

The example is not working for me!

I get only a window with an unknown character within! Of course Firefox is running!

I'm using Vista.

What's wrong?

UEZ

Getürkter *GERMAN* :mellow:

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites
ProgAndy

Sorry, forgot this post. I think, in Vista, the Data is saved in an other format in mem, so this won't work anymore. Anyway, the the solution from Manko is much better


*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites
UEZ

Thanks for feedback :)

I already saw that from Manko :lmao:

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×