如何在PowerShell会话中读取其他进程的私有环境变量并筛选目标进程
PowerShell读取运行中进程私有环境变量的方法
原命令失效原因
- 你使用的
$env:Client-Nr读取的是当前PowerShell进程自身的环境变量,和目标testxx进程完全无关,因此无法完成筛选。 Process.StartInfo.EnvironmentVariables属性仅会保存由当前PowerShell进程启动的子进程的启动时环境变量,对于系统上其他已运行的独立进程,该属性不会同步读取目标进程运行时的实际私有环境变量,因此无法获取到Client-Nr的值。
解决方法
你可以通过调用Windows原生API读取目标进程的环境块(PEB)来获取私有环境变量,以下是可直接使用的PowerShell函数:
function Get-ProcessEnvironmentVariable { param( [Parameter(Mandatory=$true, ValueFromPipeline=$true)] [System.Diagnostics.Process]$Process, [string]$VariableName ) process { $pbi = [System.Runtime.InteropServices.Marshal]::AllocHGlobal([IntPtr]::Size * 6) $returnLength = New-Object IntPtr # 调用NtQueryInformationProcess获取进程基本信息 $ntQueryMethod = [diagnostics.process].getmethod("NtQueryInformationProcess", [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Static) $ntStatus = $ntQueryMethod.Invoke($null, @($Process.Handle, 0, $pbi, [IntPtr]::Size * 6, [ref]$returnLength)) if ($ntStatus -ne 0) { Write-Error "无法读取进程信息,错误码:$ntStatus" [System.Runtime.InteropServices.Marshal]::FreeHGlobal($pbi) return } # 读取PEB地址 $pebAddress = [System.Runtime.InteropServices.Marshal]::ReadIntPtr([IntPtr]::Add($pbi, [IntPtr]::Size)) [System.Runtime.InteropServices.Marshal]::FreeHGlobal($pbi) # 读取环境块地址(64位系统偏移,32位系统需调整为[IntPtr]::Size * 9) $processParametersAddress = [System.Runtime.InteropServices.Marshal]::ReadIntPtr([IntPtr]::Add($pebAddress, [IntPtr]::Size * 4)) $environmentBlockAddress = [System.Runtime.InteropServices.Marshal]::ReadIntPtr([IntPtr]::Add($processParametersAddress, [IntPtr]::Size * 8)) # 解析环境变量字符串 $envTable = @{} $currentPtr = $environmentBlockAddress while ($true) { $currentString = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($currentPtr) if ([string]::IsNullOrEmpty($currentString)) { break } $splitPos = $currentString.IndexOf('=') if ($splitPos -gt 0) { $key = $currentString.Substring(0, $splitPos) $value = $currentString.Substring($splitPos + 1) $envTable[$key] = $value } $currentPtr = [IntPtr]::Add($currentPtr, ($currentString.Length + 1) * 2) } if ($PSBoundParameters.ContainsKey('VariableName')) { return $envTable[$VariableName] } return $envTable } }
筛选目标进程的命令
将上述函数复制到PowerShell中执行加载后,运行以下命令即可筛选出Client-Nr取值为Client-Two的testxx进程:
Get-Process -Name "testxx" | Where-Object { (Get-ProcessEnvironmentVariable -Process $_ -VariableName "Client-Nr") -eq "Client-Two" }
注意事项
- 执行上述操作需要以管理员身份启动PowerShell,否则没有权限读取其他进程的内存信息。
- 上述函数默认适配64位Windows系统,32位系统需要修改
processParametersAddress读取的偏移量。
内容的提问来源于stack exchange,提问作者Keeran
相关产品推荐
相关产品推荐

