从 python 以管理员身份运行 powershell

问题描述 投票:0回答:1

我有一个如下所示的 PowerShell 脚本:

# Define time for report (default is 1 day)
$startDate = (get-date).AddDays(-10)

# Store successful logon events from security logs with the specified dates and workstation/IP in an array
# foreach ($DC in $DCs){
# $slogonevents = Get-Eventlog -LogName Security -ComputerName $DC.Hostname -after $startDate | where {$_.eventID -eq 4624 }
# }

$slogonevents = Get-Eventlog -LogName Security -after $startDate | where {$_.eventID -eq 4624 }

# Crawl through events; print all logon history with type, date/time, status, account name, computer and IP address if user logged on remotely

  $(foreach ($e in $slogonevents){
    # Logon Successful Events
    # Local (Logon Type 2)
    if (($e.EventID -eq 4624 ) -and ($e.ReplacementStrings[8] -eq 2)){
      write-host "Type: Local Logon`tDate: "$e.TimeGenerated "`tStatus: Success`tUser: "$e.ReplacementStrings[5] "`tWorkstation: "$e.ReplacementStrings[11]
    }
    # Remote (Logon Type 10)
    if (($e.EventID -eq 4624 ) -and ($e.ReplacementStrings[8] -eq 10)){
      write-host "Type: Remote Logon`tDate: "$e.TimeGenerated "`tStatus: Success`tUser: "$e.ReplacementStrings[5] "`tWorkstation: "$e.ReplacementStrings[11] "`tIP Address: "$e.ReplacementStrings[18]
    }
}) *>&1 > D:\Cyber_security\Python\test.txt

我想从 python 运行这个脚本。这个脚本保存在我的D盘中。我的python脚本是:

import subprocess, sys

p = subprocess.Popen(["powershell.exe", 
              "D:\Cyber_security\Python\login.ps1"], 
              stdout=sys.stdout)
p.communicate()

但它不起作用。我需要以管理员身份运行 powershell,但我不知道该怎么做。

python powershell
1个回答
1
投票

您需要 nest

powershell.exe
致电:

  • 使用 Start-Process

     调用 PowerShell 的 
    -Verb RunAs
     cmdlet 的外部调用,允许使用提升运行 any 可执行文件。

  • 由于您要使用海拔运行的是

    .ps1
    脚本,因此必须通过
    powershell.exe
    (Windows PowerShell CLI)调用它,就像您自己的尝试一样,只不过您明确需要合并
    Set-Location 
    调用以确保脚本在同一工作目录中运行。作为调用者(当使用
    C:\Windows\System32
    时,
    Start-Process -Verb RunAs
    是 Windows PowerShell 中的默认设置)。

    • 如果您不需要这个,或者如果您正在使用
      pwsh.exe
      ,跨平台 PowerShell (Core) 7+ 版本的 CLI(现在默认保留工作目录),内部调用可以简化为(在两个地方将
      powershell.exe
      替换为
      pwsh.exe
      以使用 PowerShell 7+):
    • powershell.exe -Args '-noprofile -file D:\Cyber_security\Python\login.ps1'
# See bottom section if you also want to get the exit code of 
# the elevated process.
p = subprocess.Popen(
  [
    "powershell.exe", 
    "-noprofile", "-c",
    r"""
    Start-Process -Verb RunAs -Wait powershell.exe -Args "
      -noprofile -c Set-Location \`"$PWD\`"; & D:\Cyber_security\Python\login.ps1
      "
    """
  ],
  stdout=sys.stdout
)
p.communicate()

注:

  • 运行带有海拔的进程:

    • 涉及无法绕过的交互式UAC确认/凭据提示(除非关闭UAC,这是不明智的)
    • 始终在新窗口中运行。
    • 防止直接捕获升高过程的输出流;您必须重定向到(临时)files,您可以使用
      Start-Process
      '
      -RedirectStandardOutput
      /
      -RedirectStandardError
      参数来完成此操作。
  • 添加了
  • CLI 参数

    -noprofile
    -c
    -noprofile
    禁止加载 PowerShell 的 配置文件,并且
    -c
    (
    -Command
    ) 明确指示接下来要执行的 PowerShell 命令。

  • -Wait
    已添加到上面的
    Start-Process
    调用中,以便使外部
    powershell.exe
    调用等待提升的进程退出后再继续。

  • 您并不严格需要

    powershell.exe
    +
    Start-Process -Verb RunAs
    来启动提升的进程,但这是最方便的选择。

    • 基于 Python 的解决方案是可能的,但涉及相当复杂的 WinAPI 使用 - 请参阅此博客文章
    • 请注意,虽然从技术上讲您可以使用
      runas.exe /user:Administrator
      实用程序来创建提升的会话,但这样做 (a) 仅适用于该帐户,即名为
      Adminstrator
      的内置帐户,并且该帐户在实践中经常被禁用(默认情况下它是禁用的),因为它存在安全风险(有关详细信息,请参阅此答案)。
  • 另一种方法是根据需要将

    .ps1
    文件修改为 self-elevate(或使用帮助器
    .ps1
    文件来实现此目的) - 请参阅这个答案


还获取提升进程的退出代码的变体:

如果您的

.ps1
脚本使用
exit
语句来故意报告表示成功与失败的(进程)退出代码,并且您想要查询该退出代码,则需要做更多的工作:

  • Start-Process
    -PassThru
    开关输出表示新启动进程的进程信息对象,其
    .ExitCode
    属性报告进程退出代码(终止后)。

  • 由于

    -c
    /
    -Command
    CLI 参数的工作方式,内部
    powershell.exe
    调用必须显式使用
    exit $LASTEXITCODE
    将脚本的退出代码中继为提升进程的退出代码。

p = subprocess.Popen(
  [
    "powershell.exe", 
    "-noprofile", "-c",
    r"""
    exit (
      Start-Process -Verb RunAs -PassThru -Wait powershell.exe -Args "
        -noprofile -c Set-Location \`"$PWD\`"; & C:\Users\jdoe\Desktop\pg\pg.ps1; exit `$LASTEXITCODE
      "
    ).ExitCode
    """
  ],
  stdout=sys.stdout
)
p.communicate()

print('Terminated with exit code ' + str(p.returncode))
© www.soinside.com 2019 - 2024. All rights reserved.