Executing an HTA Application via PSEXEC with command line arguments

僤鯓⒐⒋嵵緔 提交于 2020-02-01 09:22:12

问题


I have an .hta application that accepts two command line arguments. Executing the application on the remote machine via command line works just like the following

(command line - cmd)Example:

C:\Users\<user>\Desktop>MSI-BUILDER.hta "MSI_APP" "D:\APP\15.9.98"

But when using my desktop trying to execute the same command on the remote machine via PSEXEC I see the application running in task manager but nothing happens.

The first steps were assigning the command line arguments to variables in PowerShell:

$arg1 = "MSI_APP"
$arg2 = "D:\APP\15.9.98"

and executing this command in PowerShell fails (no errors, just hangs):

.\psexec -s -i \\Srv2012 cmd /c "start /i "MSI-BUILDER" "C:\Users\<user>\Desktop\MSI-BUILDER.hta" $arg1 $arg2"

The application launches just in task manager and I'm assuming in the background but I don't see any changes, so it might just be hanging...

Im not 100% sure if my syntax in this matter is correct for launching an HTA via powershell with command-line arguments.

Also is there a way or switch that I can actually see the application launch and do its thing after remotely executing the code, for testing purposes?


回答1:


The invocation of your *.hta file can be simplified, by passing its path and arguments directly to mshta.exe (this also prevents a console window from appearing briefly if you launch via cmd/ c):

# From PowerShell (-accepteula omitted for brevity)
# IMPORTANT: You must use the *.hta file's FULL PATH.
.\psexec \\SERVER -i -s mshta.exe "D:\path\toapp\app.hta" $arg1 $arg2

By default, psexec runs synchronously, i.e. it doesn't return until the remote process exits, which is necessary if you want to know the process' exit code.[1]

In your case, the process doesn't exit until the HTA application window closes, so I assume that yours automatically closes when invoked with command-line arguments - if it doesn't, psexec wouldn't return until the interactive user closes the window when invoked with -i, or not at all without -i.

In cases where you need asynchronous execution, use the -d option; this makes psexec return after successfully launching the target process, without waiting for it to exit. Since you then by definition cannot know the true exit code of the launched process, all that psexec will tell you is whether the process could be created.

Caveat: Running interactively (-i) with -s, i.e. as the NT AUTHORITY\SYSTEM account, is a security risk - see next section.

However, with proper quoting your original attempt could be made to work too - see the bottom section.


As for:

Also is there a way or switch that I can actually see the application launch?

It is psexec's -i option that makes the specified command run visibly, interactively on the remote target machine, in the session of whatever user happens to be logged on there interactively at the time.[2]

In terms of user identity, psexec generally allows you to launch commands as:

  • either: the SYSTEM account (NT AUTHORITY\SYSTEM) with option -s, which is not recommended with -i, however:

    • NT AUTHORITY\SYSTEM is a highly privileged account that represents the local computer, so its use in an application that the user can control interactively is a a security risk.
  • or: a given, fixed user, with option -u (and -p; see example below)

Note that what you cannot do with -i is to automatically run with the identity of whatever user happens to be logged on to the interactive session on the target computer, as that would be highly problematic from a security perspective. However, explicitly using -u with the same credentials as the currently interactive user (if known) works.

See the documentation for more information.

With -i, it's better to use an account that has only the minimum set of privileges required for the application to function; instead of -s, you would then use the -u (username) and -p (password) parameters; e.g.:

# From PowerShell
.\psexec \\SERVER -i -u user1 -p passwd1 mshta.exe "D:\path\toapp\app.hta" $arg1 $arg2

As for what you tried (in your question):

Your original command probably would have worked, if you had fixed your quoting problems:

.\psexec \\Srv2012 -s -i cmd /c start /i `"MSI-BUILDER`" "C:\Users\<user>\Desktop\MSI-BUILDER.hta" $arg1 $arg2

To avoid problems with nested quoting, the outer quoting around the command passed to cmd /c has been omitted.

Note how the " chars. that enclose MSI-BUILDER must - unfortunately - be escaped as `" so as to ensure that PowerShell passes them through to psexec and, ultimately, cmd /c:

  • PowerShell uses a double-quoting on demand policy behind the scenes, so that even arguments that you originally specified with quotes end up not double-quoted, if the argument value doesn't contain spaces[3] - therefore, your "MSI-BUILDER" argument ends up getting passed as just MSI-BUILDER - without double-quoting - to psexec.

  • Unfortunately, the cmd-internal start command has an awkward syntax: it always requires the argument that is the window title to be enclosed in "..." on the command line, even if the title is a single word (such as MSI-BUILDER in your case).

  • Therefore, in this particular edge case, the " around the window-title argument for start must be escaped as `" to ensure that they are retained.

As shown above, however, there's a simpler way to invoke your *.hta (not requiring an intermediate cmd.exe process).

As an aside: the start command is superfluous, and setting a title for the transient window that launches the *.hta GUI is pointless, as the window will just flash for an instant.


[1] Note that HTA applications don't support setting exit codes explicitly, unless you employ an elaborate workaround. Without it, the exit code would always be 0 - unless the mshta.exe process crashes.

[2] That psexec is capable of doing so may be surprising; it is made possibly by the following clever technique: psexec connects to the target machine's $ADMIN share (typically, C:\Windows), temporarily extracts a service executable in its own executable image (PSEXESVC.exe) to that location, and starts that executable as local service (PSEXESVC) on the target machine. It is this service that launches the command passed to psexec on invocation, optionally (-i) in the current user's session (visible window station). The calling psexec instance on the origin machine communicates with the service via a named pipe (psexecsvc), which is what enables the calling machine to receive the remote process' console output if -i was not specified; on completion of the command (or, with the -d (don't wait) option, on successfully launching the command), the service is stopped and the service executable is deleted - see this article for more information.

[3] There are other, complex criteria relating to " chars. embedded in the value.




回答2:


Okay so finally after hours of trying different things this is the command that worked for me

Edited Command:

.\PSEXEC -accepteula -s -i 2 \\SERVER cmd /c "D:\path\toapp\app.hta" $arg1 $arg2 -u username -p password



来源:https://stackoverflow.com/questions/57978335/executing-an-hta-application-via-psexec-with-command-line-arguments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!