1

我们的环境正在删除一堆 Windows 2003 服务器,并且为了尝试提取对现有共享的权限,我一直在尝试提出一个解决方案来编写脚本。

然而,问题在于 WMI 无法在这些服务器上运行,因此我无法执行 GWMI Win32_Share。考虑到服务器的使用年限,更现代的 powershell 命令也不起作用。

我能做的是 Get-ACL,但是我需要提供共享的路径。我能看到获得共享完整路径的唯一方法是通过 Net Share 或 Get-ItemProperty HKLM ,其中我没有运气。

如果有比我更聪明的人知道一种方法来解析净份额的“资源”列,那么你会帮我一个大忙。

4

2 回答 2

1

您可能可以通过一些正则表达式来实现所需的结果

兼容 Powershell V1

switch -regex (net share){
    '^(\S+)\s+(\w:.+?)(?=\s{2,})' {
        New-Object PSObject -Property @{
            ShareName = $matches.1
            Resource  = $matches.2
        }
    }
}

Powershell 3.0+

switch -regex (net share){
    '^(\S+)\s+(\w:.+?)(?=\s{2,})' {
        [PSCustomObject]@{
            ShareName = $matches.1
            Resource  = $matches.2
        }
    }
}

在 powershell 5.1 上,您可以使用ConvertFrom-String“训练”数据。它可以是真实的样本数据或通用数据。可能需要针对您的特定环境进行一些调整,但这在测试中效果很好。

$template = @'
{Share*:ADMIN$}       {Path: C:\Windows}                      {Note:Remote Admin}
{Share*:Admin}        {Path: E:\Admin}                        {Note:Default share}
{Share*:Apps}         {Path: D:\Apps}                         {Note:test}
'@

net share | Select-Object -Skip 4 | Select-Object -SkipLast 2 |
    ConvertFrom-String -TemplateContent $template -OutVariable ShareList

显示的任何输出现在都应该包含在变量中$ShareList

$Sharelist | Get-Member -MemberType NoteProperty


   TypeName: System.Management.Automation.PSCustomObject

Name  MemberType   Definition              
----  ----------   ----------              
Note  NoteProperty string Note=Remote Admin
Path  NoteProperty string Path=C:\Windows  
Share NoteProperty string Share=ADMIN$ 

您还可以使用psexec远程获取信息并应用任一建议的解决方案。

switch -regex (.\PsExec.exe -nobanner \\$RemoteComputer cmd "/c net share"){
    '^(\S+)\s+(\w:.+?)(?=\s{2,})' {
        [PSCustomObject]@{
            ShareName = $matches.1
            Resource  = $matches.2
        }
    }
}

或者

$template = @'
{Share*:ADMIN$}       {Path: C:\Windows}                      {Note:Remote Admin}
{Share*:Admin}        {Path: E:\Admin}                        {Note:Default share}
{Share*:Apps}         {Path: D:\Apps}                         {Note:Test}
'@

.\PsExec.exe -nobanner \\$RemoteComputer cmd "/c net share" |
    Select-Object -Skip 4 | Select-Object -SkipLast 2 |
        ConvertFrom-String -TemplateContent $template -OutVariable ShareList
于 2021-07-15T21:30:00.027 回答
0

不幸的是,强大的net share输出解析并非易事,需要两遍方法:

  • 仅从的输出中收集所有共享名称net share
  • 对于每个共享名称$shareName,调用net share $shareName共享特定属性并将其解析为自定义对象。

尝试从net shareonly 解析输出的问题是,太长的值可能会被截断(使用...)或导致换行;也就是说,您无法稳健地获得完整值;相比之下,net share $shareName使用列表格式,其中的值不会被截断。

下面的代码实现了两遍方法:

笔记:

  • 我已经验证它可以在 PowerShell v2 中运行;我无法再访问 v1。

  • 根据 的输出net share $shareName,表示本地目标路径的属性名称是Path,而不是Resource的输出net share

  • 如果您在没有提升的情况下运行(不是管理员),由于缺少权限,无法查询以下属性:Users, Caching, Permission; 代码悄悄地忽略了它们。

# Run `net share` and collect its output lines in an array.
$lines = net share

# First pass: 
# Extract all share *names* from the lines.
# Note: Assumes that 4 header rows and a trailing status row can be ignored.
$shareNames = switch -regex ($lines[4..($lines.Count-2)]) { 
   # Extract the first whitespace-separated token,
   # but ignore wrapped lines (for overly long names / paths), which
   # start with whitespace.
   '^\S' { (-split $_)[0] }
}

# Second pass:
# Call `net share <name>` for each name and parse the list of properties into
# a [pscustomobject] instance.
# Note: 
#  * When runnning *without elevation*, querying the following fields 
#    fails due to lack of permissions, which is quietly ignored here:
#      Users, Caching, Permission
#  * Assumes that property names are either one or two words and followed
#    by at least two spaces.
foreach ($shareName in $shareNames) {
  Write-Verbose -vb "Processing $shareName..."
  # Initialize a hashtable to store the properties.
  # Note: In PSv3+, you can use [ordered] @{} to define the properties in predictable order.
  $properties = @{}
  # Parse the property lines and add them to the hashtable.
  switch -regex (net share $shareName 2>$null) {
     '^(\w+ (?:\w+)?) {2,}(.*)' {
        $properties[$Matches[1]] = ($Matches[2]).Trim()
     }
  }
  # Convert the hashtable to a custom object.
  # Note: In PSv3+, you can simplify to [pscustomobject] $properties
  New-Object pscustomobject $properties
}
于 2021-07-16T19:51:47.300 回答