PowerShell 技能连载 - 检测危险的 NTFS 权限

以下是一个查找潜在危险的 NTFS 权限的快速简单的方法。这段脚本检测所有 $pathsToCheck 的文件夹并且汇报错有具有 $dangerousBitMask 中定义的文件系统标志的安全存取控制项(译者注:也就是“路径”)。

在这个例子中,该脚本从您的 %PATH% 环境变量中得到所有查找到的路径。这些路径是高风险的,需要用 NTFS 权限来保护,只能由 Administrators 和 system 拥有写权限。

软件安装程序常常将它们自身加入环境变量而没有正确地保护它们所加入的文件夹权限。这将增加安全风险。以下脚本将检查这些地方并找出哪些有潜在危险的 NTFS 存取权限供您做决定。

# list of paths to check for dangerous NTFS permissions
$pathsToCheck = $env:Path -split ';'

# these are the bits to watch for
# if *any* one of these is set, the folder is reported
$dangerousBitsMask = '011010000000101010110'
$dangerousBits = [Convert]::ToInt64($dangerousBitsMask, 2)

# check all paths...
$pathsToCheck |
ForEach-Object {
  $path = $_
  # ...get NTFS security descriptor...
  $acl = Get-Acl -Path  $path
  # ...check for any "dangerous" access right
  $acl.Access |
  Where-Object { $_.AccessControlType -eq 'Allow' } |
  Where-Object { ($_.FileSystemRights -band $dangerousBits) -ne 0 } |
  ForEach-Object {
    # ...append path information, and display filesystem rights as bitmask
    $ace = $_
    $bitmask = ('0' * 64) + [Convert]::toString([int]$ace.FileSystemRights, 2)
    $bitmask = $bitmask.Substring($bitmask.length - 64)
    $ace | Add-Member -MemberType NoteProperty -Name Path -Value $path -PassThru | Add-Member -MemberType NoteProperty -Name Rights -Value $bitmask -PassThru
  }
} |
Sort-Object -Property IdentityReference |
Select-Object -Property IdentityReference, Path, Rights, FileSystemRights |
Out-GridView

PowerShell 技能连载 - 获取 IP 地址的地理信息

您希望知道某个公网 IP 地址位于什么地方吗?假设您有 Internet 连接,您可以查询公共信息服务来获得。

这个例子将获取某个 IP 地址的地理信息。请确认您将示例 IP 地址替换为了实际存在的公网 IP 地址。请打开类似 https://www.whatismyip.com/ 这样的网站来查看您自己的 IP 地址。如果您使用的是一个内网 IP 地址,该 WEB 服务将无法准确地报告地理信息数据。

#requires -Version 3

$ipaddress = '93.212.237.11'
$infoService = "http://freegeoip.net/xml/$ipaddress"

$geoip = Invoke-RestMethod -Method Get -URI $infoService

$geoip.Response

PowerShell 技能连载 - 获取当前 IP 地址

以下是一段您计算机绑定的所有 IP 地址的代码:

#requires -Version 1


$ipaddress = [System.Net.DNS]::GetHostByName($null)
Foreach ($ip in $ipaddress.AddressList)
{
  $ip.IPAddressToString
}

如果您将 $null 替换为主机名(例如“_server123_”),就可以获取对应计算机绑定的 IP 地址。

如果您只需要获取 IPv4 地址,请试试这段代码:

#requires -Version 1


$ipaddress = [System.Net.DNS]::GetHostByName($null)
foreach($ip in $ipaddress.AddressList)
{
  if ($ip.AddressFamily -eq 'InterNetwork')
  {
    $ip.IPAddressToString
  }
}

PowerShell 技能连载 - 验证域凭据

要通过当前的域验证凭据(用户名和密码),您可以使用这段代码:

#requires -Version 1

$username = 'test\user'
$password = 'topSecret'

$root = "LDAP://" + ([ADSI]"").distinguishedName
$Domain = New-Object System.DirectoryServices.DirectoryEntry($root, $username, $password)

if ($Domain.Name -eq $null)
{
  Write-Warning 'Credentials incorrect, or computer is not a domain member.'
}
else
{
  Write-Host 'Credentials accepted.'
}

总的来说,该脚本首先确认当前域名,然后用提供的凭据来获取根元素。

如果该操作成功完成,说明凭据时合法的。如果失败,说明凭据是无效的,或者该计算机根本没有加入域。

PowerShell 技能连载 - 安全使用 UNC 路径

当您在 PowerShell 中使用 UNC 路径时,您的脚本可能会中断。由于 UNC 路径没有驱动器号,所以 PowerShell 将会在当前目录下查找,并且使用当前路径对应的 PSProvider。

所以如果您的当前目录不是一个文件路径(例如是一个注册表驱动器),那么您的 UNC 路径将会被解释成一个注册表路径。

要安全地使用路径,请一定在 UNC 路径前面加上正确的提供器名称:

# UNC-Paths have no drive letter
# so PowerShell uses the current directory instead to find the PSProvider
# for UNC paths, to be safe, always add the provider name manually
$exists = Test-Path -Path 'FileSystem::\\server12\fileshare'

$exists

PowerShell 技能连载 - 使用 Splatting 技术

通过 splatting 技术,您可以调用 cmdlet,并可以控制提交的参数。

要实现该目标,先向一个哈希表插入参数和值,然后将哈希表传给 cmdlet。这种方法适用于任意 cmdlet。

以下是一个例子:

# classic:
Get-ChildItem -Path c:\windows -Filter *.ps1 -Recurse -ErrorAction SilentlyContinue


# Splatting
$params = @{}
$params.Path = 'c:\windows'
$params.Filter = '*.ps1'
$params.Recurse = $true
$params.ErrorAction = 'SilentlyContinue'
Get-ChildItem @params

PowerShell 技能连载 - 读取 RSS 频道

我们可以通过 XML 对象来读取 RSS 频道信息,然而 XML 对象不支持代理服务器。

这个例子用 Invoke-WebRequest 通过代理服务器来获取 RSS 数据(如果忽略 -Proxy 参数则直接获取),然后将结果转换为 XML。

#requires -Version 3


$url = 'http://blogs.msdn.com/b/powershell/rss.aspx'

$page = Invoke-WebRequest -Uri $url <#-Proxy 'http://proxy...:8080' -ProxyUseDefaultCredentials#>
$content = $page.Content


$xml = [XML]$content
$xml.rss.channel.item  | Out-GridView

这段代码将显示 PowerShell 团队博客数据。

PowerShell 技能连载 - 读取注册表键值和值类型

Get-ItemProperty 可以方便地读取注册表键值,但是无法获得注册表键值的数据类型。

Get-ItemProperty -Path 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion'

以下是通过 .NET 方法的另一种实现,可以获得所有的信息:

PS> Get-RegistryValue 'HKLM\Software\Microsoft\Windows NT\CurrentVersion'

Name                     Type Value
----                     ---- -----
CurrentVersion         String 6.1
CurrentBuild           String 7601
SoftwareType           String System
CurrentType            String Multiprocessor Free
InstallDate             DWord 1326015519
RegisteredOrganization String
RegisteredOwner        String Tobias
SystemRoot             String C:\Windows
InstallationType       String Client
EditionID              String Ultimate
ProductName            String Windows 7 Ultimate
ProductId              String 0042xxx657
DigitalProductId       Binary {164, 0, 0, 0...}
DigitalProductId4      Binary {248, 4, 0, 0...}
CurrentBuildNumber     String 7601
BuildLab               String 7601.win7sp1_gdr.150202-1526
BuildLabEx             String 7601.18741.amd64fre.win7sp1_gdr.150202-1526
BuildGUID              String f974f16b-3e62-4136-a6fb-64fccddecde3
CSDBuildNumber         String 1130
PathName               String C:\Windows

我们需要开发一个 Get-RegistryValue 函数来实现该功能。请注意该函数可传入任意合法的注册表键,并且不需要使用 PowerShell 驱动器号。

function Get-RegistryValue
{
    param
    (
        [Parameter(Mandatory = $true)]
        $RegistryKey
    )

    $key = Get-Item -Path "Registry::$RegistryKey"
    $key.GetValueNames() |
    ForEach-Object {
        $name = $_
        $rv = 1 | Select-Object -Property Name, Type, Value
        $rv.Name = $name
        $rv.Type = $key.GetValueKind($name)
        $rv.Value = $key.GetValue($name)
        $rv
    }
}

PowerShell 技能连载 - 查找电视剧信息

PowerShell 可以查询基于 XML 内容的网站,以下是一个查询电影数据库的例子:

只需要输入您感兴趣的电视剧名称即可。如果您不能直接访问 Internet,可以用 -Proxy 参数指定代理服务器。

#requires -Version 3

$name = 'stargate'
$url = "http://thetvdb.com/api/GetSeries.php?seriesname=$name&language=en"

$page = Invoke-WebRequest -Uri $url <#-Proxy 'http://proxy....:8080' -ProxyUseDefaultCredentials#>
$content = $page.Content


$xml = [XML]$content
$xml.Data.Series | Out-GridView

PowerShell 技能连载 - 比较文件夹内容

要快速比较文件夹内容并且找出只在一个文件夹中存在的文件,请试试以下代码:

$list1 = Get-ChildItem c:\Windows\system32 | Sort-Object -Property Name

$list2 = Get-ChildItem \\server12\c$\windows\system32 | Sort-Object -Property Name


Compare-Object -ReferenceObject $list1 -DifferenceObject $list2 -Property Name |
  Sort-Object -Property Name

该代码属两个文件夹列表,一个来自本机,另一个来自远程计算机。接下来 Compare-Object 命令会挑出只在一个文件夹中存在的文件。