使用命令行参数通过 PSEXEC 执行 HTA 应用程序

Executing an HTA Application via PSEXEC with command line arguments

我有一个接受两个命令行参数的 .hta 应用程序。通过命令行在远程机器上执行应用程序就像下面这样

(命令行 - cmd)示例:

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

但是当使用我的桌面尝试通过 PSEXEC 在远程计算机上执行相同的命令时,我在任务管理器中看到了应用程序 运行,但没有任何反应。

第一步是将命令行参数分配给 PowerShell 中的变量:

$arg1 = "MSI_APP"
$arg2 = "D:\APP.9.98"

并且在 PowerShell 中执行此命令失败(没有错误,只是挂起):

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

应用程序仅在任务管理器中启动,我假设在后台运行,但我没有看到任何变化,所以它可能只是挂起...

我不是 100% 确定我在这件事上的语法对于通过带有命令行参数的 powershell 启动 HTA 是否正确。

还有什么方法或开关可以让我实际看到应用程序启动并在远程执行代码后执行它的操作,以进行测试?

好吧,经过几个小时尝试不同的事情,这就是对我有用的命令

编辑命令:

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

调用您的 *.hta 文件可以简化,方法是将其路径和参数直接传递给 mshta.exe(如果您通过 cmd/ c 启动,这也可以防止控制台 window 短暂出现):

# 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

默认情况下,psexec运行s 同步,即不return 直到远程进程退出,如果你想知道进程'退出代码.[1][,这是必需的=213=]

在您的情况下,进程不会退出 直到 HTA 应用程序 window 关闭 ,所以我假设您的 自动关闭 当使用 command-line 参数调用时 - 如果没有,psexec 不会 return 直到交互式用户在使用 [=18= 调用时关闭 window ],或者根本没有 -i.

如果您需要异步执行,请使用-d选项;这使得 psexec return 在成功 启动 目标进程后,无需等待它退出。因为根据定义,您无法知道已启动进程的真实 exit 代码,因此 psexec 会告诉您该进程是否可以 created.

警告:运行 -s 交互 (-i),即作为NT AUTHORITY\SYSTEM 帐户存在 安全风险 - 请参阅下一节。

然而,通过适当的引用,您最初的尝试也可以奏效 - 请参阅底部。


至于:

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

psexec-i选项使指定的命令运行可见,在远程目标机器上 在 session 中 session 任何用户恰好在当时 以交互方式登录。 [2]

根据用户身份psexec 通常允许您启动命令为:

  • 任一:SYSTEM 帐户 (NT AUTHORITY\SYSTEM) 选项 -s 推荐 -i,但是:

    • NT AUTHORITY\SYSTEM 是代表本地计算机的高特权 帐户,因此它在用户可以交互控制的应用程序中使用 存在 安全风险
  • 或:a 给定的固定用户,带有选项-u(和-p;见下面的例子)

注意不能-i做的是自动运行 使用 的身份,无论用户碰巧登录到目标计算机 上的交互式session,因为从安全角度来看,这将是一个很大的问题。然而,显式使用-u和当前交互用户(如果已知)相同的凭证是有效的。

有关详细信息,请参阅 the documentation

使用-i,最好使用仅具有所需最低权限集的帐户 应用程序运行;然后,您将使用 -u(用户名)和 -p(密码)参数,而不是 -s;例如:

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

至于你尝试了什么(在你的问题中):

如果您解决了引用问题,您的原始命令可能会起作用:

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

为了避免 嵌套 引用出现问题,传递给 cmd /c 的命令周围的外部引用已被省略。

注意 " 是如何字符化的。不幸的是,包含 MSI-BUILDER 的内容必须转义为 `",以便 确保 PowerShell 将它们传递给 psexec,并最终 cmd /c:

  • PowerShell 在幕后使用 double-quoting 按需 策略,因此即使是您 最初指定的参数 引号结束 not double-quoted, 如果参数值不包含空格[3 ] - 因此,您的 "MSI-BUILDER" 参数最终仅作为 MSI-BUILDER - 没有 double-quoting - 传递给 psexec.

  • 不幸的是,cmd-internal start 命令有一个笨拙的语法:它 always 需要的参数是 window title 在命令行中包含在 "..." 中,即使标题是单个单词(如您的情况下的 MSI-BUILDER)。

  • 因此,在这种特殊情况下,start 的 window-title 参数周围的 " 必须转义为 `" 以确保它们被保留。

然而,如上所示,有一种更简单的方法来调用您的 *.hta(不需要中间 cmd.exe 过程)。

顺便说一句:start 命令是多余的,并为 tr 设置 title启动 *.hta GUI 的 nsient window 毫无意义,因为 window 会瞬间闪烁。


[1] 请注意,HTA 应用程序不支持显式设置退出代码,除非您使用 an elaborate workaround。没有它,退出代码将始终是 0 - 除非 mshta.exe 进程 崩溃 .

[2] psexec 能够做到这一点可能令人惊讶;它可以通过以下巧妙的技术实现:psexec 连接到目标机器的 $ADMIN 共享(通常是 C:\Windows),临时 提取服务将其自己的可执行映像 (PSEXESVC.exe) 中的可执行文件复制到该位置,并在目标机器上将可执行文件作为 local service (PSEXESVC) 启动。正是此服务在调用时启动传递给 psexec 的命令,可选地 (-i) 在当前用户的 session(可见 window 站)。源机器上的调用 psexec 实例通过命名管道 (psexecsvc) 与服务通信,这使调用机器能够接收远程进程的 控制台输出 如果 -i 未指定的 ;命令完成后(或者,使用-d(不要等待)选项,成功启动命令),服务停止,服务可执行文件是已删除 - 参见this article了解更多信息。

[3] 还有其他与 " 字符相关的复杂标准。 嵌入值中。