powershell Azure DevOps任务的子进程在作业停止时终止

snvhrwxg  于 2023-04-21  发布在  Shell
关注(0)|答案(1)|浏览(151)

我有一个自定义PowerShell Azure DevOps任务,该任务创建子进程(用于另一个PowerShell脚本)。我希望子进程运行一段时间-这是一个后台轮询作业。但是,自定义任务完成时,子进程将停止。
我已经将其隔离为一个最小的示例。主任务脚本如下:

$PollScriptPath = [System.IO.Path]::Combine($PSScriptRoot, "poll.ps1")
Start-Process -FilePath "cmd.exe" -ArgumentList "/c powershell.exe $PollScriptPath  >PollLog.txt 2>&1"

Poll.ps1在示例中什么也不做,只是在那里坐了5分钟:

Write-Host Hello
Start-Sleep -Seconds 300

任务执行器是遗留的Powershell主机;任务清单中的相关部分为:{"execution":{"PowerShell":{...}}}
为了检查,我在Start-Process行之后添加了一个30秒的睡眠;有了这些,我可以看到powershell进程在代理帐户的上下文中运行,只要PS主机进程正在运行。当后者退出时,前者也退出。
这可能与控制台所有权有关吗?例如,子进程从父进程继承控制台,当父进程退出并销毁控制台时,子进程也必须退出。或者这是关于进程层次结构的某种方式?或者可能是powershell主机具有适当的逻辑来拦截派生进程并终止它们?
编辑:几个数据点。派生进程生命周期的范围是作业,而不是任务。我添加了另一个延迟一分钟的任务,并且派生的PowerShell进程也将在执行该任务时保持活动。首先,这意味着现代PowerShell执行器和Node执行器都将表现出类似的派生进程行为。
此外,他们很可能使用作业对象来管理进程的生存期。代理计算机上的任务管理器不显示任何这些进程的作业ID。不过,可能是作业对象太安全,管理员无法看到它的存在。作业将是控制进程树生存期的一种自然的Windows本机方式...
它不是控制台驱动的。我已经以交互方式启动了代理-派生的cmd.exe获得了自己的窗口。当作业终止时仍然退出。
故意孤立一个进程(a启动b并等待一段时间,b启动c并立即退出)也不起作用。根据Process Explorer的判断,当b退出时,c在进程树中移动到a下面,这使它容易受到树终止逻辑的攻击。
这里概述了一种欺骗进程树的方法:https://scorpiosoftware.net/2021/01/10/parent-process-vs-creator-process/
这个想法是:

  • 创建/初始化具有1个属性的PROC_THREAD_ATTRIBUTE_LIST对象
  • 在那里放置PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,指定伪父进程的进程句柄
  • 将所述对象放入STARTUPINFOEX结构的lpAttributeList
  • 创建一个dwCreationFlagsEXTENDED_STARTUPINFO_PRESENT的子进程,传递上述结构

不用说,这个深度魔法不会暴露给PowerShell的Start-Process

2izufjch

2izufjch1#

在尝试逃离沙箱之后,我在代理机器上设置了一个没有触发器的计划任务,任务脚本将以Start-ScheduledTask启动它。
请注意,计划任务上有一组凭据,不一定必须与代理服务上的凭据匹配。在我的情况下,它必须匹配,并且确实匹配,因为我已经注意到以这种方式设置它,但在一般情况下,这是需要考虑的。在AzDevOps代理中执行的脚本不会自动访问代理服务的Windows凭据。
我并没有放弃寻找一种逃离沙盒的方法(现在这是一个值得骄傲的问题),但这也可以。至少我没有对任务的最终用户提出任何额外的要求。

相关问题