Jump to content

Can't get process command line with _WinAPI_GetProcessCommandLine


Recommended Posts

I tryed _WinAPI_GetProcessCommandLine example from Help file, and it works great for most computers.

But on one computer I got @error=40 and empty string as a result.

It's Win10x64 with admin rights, but I have Win10x64 too and for me script works fine.

Could you give me advice please?

Thank you!

Link to comment
Share on other sites

#include <WinAPIProc.au3>
#include <WinAPI.au3>
#include <StringConstants.au3>
#RequireAdmin

Global $aAdjust

Func ImproveMainCaptions($aProcList)

    $iProcessNumer = $aProcList[0][0]
    For $i = 1 To $iProcessNumer

        $ID = $aProcList[$i][1]

        $sCmdLine = _WinAPI_GetProcessCommandLine($ID)
        $str = "Err:" & @error & " Line:" & $sCmdLine
        MsgBox($MB_SYSTEMMODAL, "Important1CParametersLine", $str)
        ; here @error is 40 and &str is empty string
        ; but only on one computer. All others are fine.
    Next
EndFunc

; Main Entry point
While 1
    $hToken = _WinAPI_OpenProcessToken(BitOR($TOKEN_ADJUST_PRIVILEGES, $TOKEN_QUERY))
    _WinAPI_AdjustTokenPrivileges($hToken, $SE_DEBUG_NAME, $SE_PRIVILEGE_ENABLED, $aAdjust)
    If Not (@error Or @extended) Then
        $aProcList = ProcessList("1cv8.exe")
        ImproveMainCaptions($aProcList)

        _WinAPI_AdjustTokenPrivileges($hToken, $aAdjust, 0, $aAdjust)
        _WinAPI_CloseHandle($hToken)
    Else
        Exit
    EndIf
WEnd

 

Link to comment
Share on other sites

Yep, as I tryed to say (sorry for bad english) it works fine everywhere except one concrete computer.

So maybe there is another way to get process command line?

Or maybe someone know what @error = 40 is?

Link to comment
Share on other sites

Try displaying the error message in the message box using winapi_getlasterrormessage()

Edit:    Make sure autoit is set to run as administrator in both the shortcut and all executables and add #RequireAdmin to the top of the script.

Edit edit!!  Upon further evaluation of your posted code. .. .

The token of the calling process should have the same access rights as the user who started the process so if its failing then you may not have the necessary rights to access the process.

 

edit edit edit.  I'm fairly certain its a rights issue.  I ran into similar problems with readprocessmemory.

;this is from the winapi function that reads the commandline information.  It sets up a couple dllstructs then proceeds to start pulling ;information from them
;
;this is the second call that attempts to read the process memory...

$aRet = DllCall('kernel32.dll', 'bool', 'ReadProcessMemory', 'handle', $hProcess, _
                'ptr', DllStructGetData($tPBI, 'PebBaseAddress'), 'struct*', $tPEB, _
                'ulong_ptr', DllStructGetSize($tPEB), 'ulong_ptr*', 0)
        If @error Or Not $aRet[0] Or (Not $aRet[5]) Then
            $iError = @error + 40
            ExitLoop
        EndIf
        
;$iError is set to @error+40 which @error is zero by default so i'd assume that would equal 40

You definitely need the required privileges to read a different process memory so im fairly certain that is the issue

Edited by markyrocks
Link to comment
Share on other sites

#RequireAdmin
#include <WinAPIProc.au3>
#include <WinAPI.au3>
#include <StringConstants.au3>

Global $aAdjust

Func ImproveMainCaptions($aProcList)

    $iProcessNumer = $aProcList[0][0]
    For $i = 1 To $iProcessNumer

        $ID = $aProcList[$i][1]

        $sCmdLine = _WinAPI_GetProcessCommandLine($ID)
        $str = "Err:" & @error & " Line:" & $sCmdLine
        MsgBox($MB_SYSTEMMODAL, "Important1CParametersLine", $str)
        ; here @error is 40 and &str is empty string
        ; but only on one computer. All others are fine.
    Next
EndFunc

; Main Entry point
$hToken = _WinAPI_OpenProcessToken(BitOR($TOKEN_ADJUST_PRIVILEGES, $TOKEN_QUERY))
_WinAPI_AdjustTokenPrivileges($hToken, $SE_DEBUG_NAME, $SE_PRIVILEGE_ENABLED, $aAdjust)
If Not (@error Or @extended) Then
    $aProcList = ProcessList("1cv8.exe")
    ImproveMainCaptions($aProcList)

    _WinAPI_AdjustTokenPrivileges($hToken, $aAdjust, 0, $aAdjust)
    _WinAPI_CloseHandle($hToken)
EndIf

markyrocks, thank you for usefull info. I scented that it's a privilege issue.

Now, I moved #RequireAdmin to first line and run script again on that computer. Definetly As Administrator. But nothing changed :( Can I try something else?

Link to comment
Share on other sites

Maybe this will work better and enlighten you why this particular computer does not answer correctly :

#RequireAdmin

#include <Array.au3>
#include <WinAPIHObj.au3>
#include <WinAPIProc.au3>

Local $aAdjust, $aProcess[200][10], $iCount = 0
Local $hToken = _WinAPI_OpenProcessToken($TOKEN_ALL_ACCESS)
_WinAPI_AdjustTokenPrivileges($hToken, $SE_DEBUG_NAME, $SE_PRIVILEGE_ENABLED, $aAdjust)

Local $objWMIService = ObjGet("winmgmts:\\" & @ComputerName & "\root\CIMV2")
Local $colItems = $objWMIService.ExecQuery('SELECT * FROM Win32_Process')
If Not IsObj($colItems) Then Exit MsgBox(0, "", "Not an object")
If Not $colItems.count Then Exit MsgBox(0, "", "Not found")
For $oItem In $colItems
  $aProcess[$iCount][0] = $oItem.ProcessId
  $aProcess[$iCount][1] = $oItem.SessionId
  $aProcess[$iCount][2] = $oItem.Caption
  $aProcess[$iCount][3] = $oItem.CSName
  $aProcess[$iCount][4] = $oItem.CreationClassName
  $aProcess[$iCount][5] = $oItem.Description
  $aProcess[$iCount][6] = $oItem.CSCreationClassName
  $aProcess[$iCount][7] = $oItem.CommandLine
  $aProcess[$iCount][8] = _WinAPI_GetProcessCommandLine($oItem.ProcessId)
  $aProcess[$iCount][9] = @error
  $iCount += 1
Next
ReDim $aProcess[$iCount][10]
_WinAPI_AdjustTokenPrivileges($hToken, $aAdjust, 0, $aAdjust)
_WinAPI_CloseHandle($hToken)
_ArrayDisplay($aProcess)

In the SELECT statement, you can add a WHERE clause.

Link to comment
Share on other sites

I was also getting error 40 on some processes after _WinAPI_GetProcessCommandLine.  It means that some part of the processReadMemory was out of reach.  After debugging the WinAPI function I found on MSDN that x64 process cannot be read from another x86 process.  In order to have a successful return you must run your script x64 (or use WMI like I did).  Don't know if that will solve your issue though...But it is a crucial information that is not documented in help file.

Edited by Nine
Link to comment
Share on other sites

9 hours ago, Nine said:

I was also getting error 40 on some processes after _WinAPI_GetProcessCommandLine.  It means that some part of the processReadMemory was out of reach.  After debugging the WinAPI function I found on MSDN that x64 process cannot be read from another x86 process.  In order to have a successful return you must run your script x64 (or use WMI like I did).  Don't know if that will solve your issue though...But it is a crucial information that is not documented in help file.

my thought process had went down this path but i retracted my statement bc i wan't 100% sure that was the issue and didn't want to throw too many things out at once i had originally wrote a wall of text.  Where did you find the bit about 86 not being able to read from a 64bit process?  I know that certain functions have 32 and 64bit versions but it doesn't appear that readprocessmemory does.  I'd assume the difference is how the data is interpreted after its retrieved(or the required args variable types and sizes) .  Like when a function is called and bytes sent back a 64bit version is written to handle specific types of variables and buffer sizes associated with them.  With readprocessmemory the only difference would be the values of the memory addresses which should just be bytes from previously executed function call unless your entering them in manually which either way i don't think that windows would care as long as the address is valid and readable.  The only real hitch i could see with this is on the return.  if autoit would be able to make the conversion or not automatically.  it really just depends on what the returned bytes are supposed to be after the fact.  I guess if they were just regular chars it would be fine if it was unicode....idk but it should still return something even if it was gibberish instead of erroring out.  Anyway this is probably way beyond the scope.

@sulfur are you 100% certain that both the autoit3.exe and the scite.exe are checked as run as admin in the core autoit directory?  Probably even hit up the 64 bit versions when you are in there.  Im speaking from experience bc i actually tested this out in different configurations in regards to mem reads and  it won't work right unless this is setup correctly regardless if its an x86 trying to read a 64  bit process or whatever, that may be the issue but i know for a fact if both of these are not both set to run as admin you can't read memory from another process ESPECIALLY if that process is running as administrator and autoit is running at lesser privileges.  I've tested this out in a variety of ways a few months ago and it will either just return random gibberish or it will fail entirely.  I can't remember exactly but it may have even spit out a access denied error from windows.  

Use a message box that looks like this after the call.....

;call for command line etc...
MsgBox('','WinLastError',_WinAPI_GetLastErrorMessage())

this is what that call is for, gives more insight into what is happening.  

 

 

autoit admin.png

scite admin.png

Edited by markyrocks
Link to comment
Share on other sites

Link to comment
Share on other sites

On 4/8/2020 at 3:39 PM, Nine said:

x64 process cannot be read from another x86 process

looks like it's the right answer :)

I added #AutoIt3Wrapper_UseX64=Y to the script and now it works well. Problem solved, thanks!

Edited by sulfur
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...