PowerShell 技能连载 - 从 Internet 下载信息(第 3 部分)

在前一个技能中,我们演示了如何使用 Invoke-WebRequest 从网页下载数据,并且处理 JSON 或 XML 格式的数据。然而,多数网页包含的是纯 HTML 数据。您可以使用正则表达式来从纯 HTML 中提取信息。

以下是获得网页内容的方法:

1
2
3
$url = 'http://pages.cs.wisc.edu/~ballard/bofh/bofhserver.pl'
$page = Invoke-WebRequest -Uri $url -UseBasicParsing
$page.Content

这个例子中的网页提供随机的借口。要获得最终的借口,得先创建正则表达式模式:

1
2
3
4
5
6
7
8
9
10
$url = 'http://pages.cs.wisc.edu/~ballard/bofh/bofhserver.pl'
$page = Invoke-WebRequest -Uri $url -UseBasicParsing
$content = $page.Content

$pattern = '(?s)<br><font size\s?=\s?"\+2">(.+)</font'

if ($page.Content -match $pattern)
{
$matches[1]
}

当您运行这段代码时,它可以提供一个新的借口。我们在此不深入讨论正则表达式。该正则表达式的基本原理是查找 )<br><font size\s?=\s?"\+2"> 这样的静态文本,然后取出之后的任何文本 ((.+)),直到结尾的静态文本 (</font)。$matches[1] 的值就是正则表达式中的第一个模式代表的内容,在这里就是我们要提取的借口。

PowerShell 技能连载 - 从 Internet 下载信息(第 2 部分)

Invoke-WebRequest 可以下载任意类型的信息,而且可以根据您的需要将它转为任意类型。在前一个技能里,我们演示了如何处理 JSON 数据。现在我们来看看返回 XML 数据的网页:

这个例子从欧洲中央银行获取当前的货币兑换率:

1
2
3
$url = 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml'
$result = Invoke-WebRequest -Uri $url -UseBasicParsing
$result.Content

以下是结果:

1
2
3
4
$url = 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml'
$result = Invoke-WebRequest -Uri $url -UseBasicParsing
$xml = [xml]$result.Content
$xml.Envelope.Cube.Cube.Cube

PowerShell 技能连载 - 从 Internet 下载信息(第 1 部分)

PowerShell 带来了两个 cmdlet,可以用来从 internet 获取信息。今天,我们重点关注 Invoke-WebRequest

这个 cmdlet 提供了一个简单的 web 客户端。传给它一个 URL,它就可以帮您下载该网页。以下简单的几行代码可以帮您下载 psconf.eu 的议程表:

1
2
$page = Invoke-WebRequest -Uri powershell.beer -UseBasicParsing
$page.Content

由于它是 JSON 格式的,所以可以将它通过管道传递给 ConvertFrom-Json 来获得对象:

1
2
$page = Invoke-WebRequest -Uri powershell.beer -UseBasicParsing
$page.Content | ConvertFrom-Json | Out-GridView

然而,有些时候(例如这个例子),它并不能正确地“展开”集合结果,所以得手工操作它:

1
2
$page = Invoke-WebRequest -Uri powershell.beer -UseBasicParsing
$($page.Content | ConvertFrom-Json) | Out-GridView

通过这种方法,您可以下载网页上的任意信息,然后处理它。如果一个 web 页返回的是 XML,您可以将它转换为 XML,而如果它是纯 HTML,您可以使用正则表达式来提取您需要的信息。更多信息请见将来的技能。

PowerShell 技能连载 - 清除所有账户的 Kerberos 票证

在前一个技能中我们介绍了 klist.exe 以及如何用它来清除当前用户的所有 Kerberos 票证,这样新的权限可以立即生效。

由于 PowerShell 可以很好地调用外部应用程序,例如 klist.exe,所以结合其它 PowerShell 命令,功能可以变得更强大。以下代码可以获取所有非使用 NTLM(例如 Kerberos 会话)的登录会话:

1
Get-WmiObject -ClassName Win32_LogonSession -Filter "AuthenticationPackage != 'NTLM'"

在提权过的 PowerShell 中运行这行代码,将可以看到所有登录会话。只需要做一点小修改,就可以获取十六进制的登录 ID:

1
2
Get-WmiObject -ClassName Win32_LogonSession -Filter "AuthenticationPackage != 'NTLM'" |
ForEach-Object {[Convert]::ToString($_.LogonId, 16)}

要清除所有会话的缓存的 Kerberos 票证,您可以(在提权的 PowerShell 中)运行这段代码:

1
2
3
Get-WmiObject -ClassName Win32_LogonSession -Filter "AuthenticationPackage != 'NTLM'" |
ForEach-Object {[Convert]::ToString($_.LogonId, 16)} |
ForEach-Object { klist.exe purge -li $_ }

PowerShell 技能连载 - 清除当前用户的 Kerberos 票证

如果要应用更新的权限设置,并不需要重启系统。而只需要清除 Kerberos 票证就可以基于当前的权限获取一个新的票证。

In PowerShell, use this command to purge all cached Kerberos tickets:
在 PowerShell 中,只需要用这条命令就可以清除所有缓存的 Kerberos:

1
2
3
4
5
6
7
PS> klist purge

Current LogonId is 0:0x2af9a
Deleting all tickets:
Ticket(s) purged!

PS>

PowerShell 技能连载 - 创建十六进制数值

有一系列方法可以将十进制数据转为十六进制表示:

1
2
3
4
5
6
7
$value = 255

[Convert]::ToString($value, 16)
'{0:x}' -f $value
'{0:X}' -f $value
'{0:x10}' -f $value
'{0:X10}' -f $value

PowerShell 技能连载 - 用 Chocolatey 安装 PowerShell 6

在之前的技能中,我们解释了如何下载和安装 Chocolatey,一个免费的 Windows 包管理器,可以用来安装软件。

今天,我们将看看如何用 Chocolatey 下载 PowerShell Core 6,这样您就可以体验它了。该安装并不会改变当前的 PowerShell 版本,所以您可以安全地同时安装它。

要安装 PowerShell Core 包,您需要管理员权限。用完整管理员权限打开一个 PowerShell 窗口。请不要用 PowerShell ISE 打开 Chocolatey,因为 PowerShell ISE 无法显示交互式控制台信息和提示。

如果您将 chocolatey 安装为一个便携式软件,请将它的路径添加到 Windows 的 Path 环境变量中。然后运行安装命令:

1
2
3
PS> $env:path += ";C:\ProgramData\chocoportable"

PS> choco install powershell-core -y

当 Choco 确定依赖关系、下载和安装必备项时,您将会见到一系列信息,最后才是安装 PowerShell Core 6。

当安装完成时,PowerShell Core 6 可以在 C:\Program Files\PowerShell\[Version]\pwsh.exe 这儿找到。

要确认您通过 Chocolatey 安装的包是否过时,请运行这条命令:

1
PS> choco outdated

如果需要更新一个已安装的包,请使用这条命令:

powershell
PS C:\> choco upgrade powershell-core
Chocolatey v0.10.8
Upgrading the following packages:
powershell-core
By upgrading you accept licenses for the packages.
powershell-core v6.0.2 is the latest version available based on your source(s).

Chocolatey upgraded 0/1 packages.
See the log for details (C:\ProgramData\chocoportable\logs\chocolatey.log).
PS C:\>

PowerShell 技能连载 - 用 PowerShell 操作 Chocolatey

Chocolatey 是一个 Windows 平台上免费的包管理器,可以用来下载和安装软件。

在用 PowerShell 操作 Chocolatey 之前,您需要下载和安装它。如果您没有管理员特权,请使用以下代码。它将下载安装脚本,检测它的数字签名并确保它是合法的,然后运行它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# download and save installation script, then check signature
$url = 'https://chocolatey.org/install.ps1'
$outPath = "$env:temp\installChocolatey.ps1"
Invoke-WebRequest -UseBasicParsing -Uri $url -OutFile $outPath

# test signature
$result = Get-AuthenticodeSignature -FilePath $outPath
if ($result.Status -ne 'Valid')
{
Write-Warning "Installation Script Damaged/Malware?"
exit 1
}

# install chocolatey for current user
$env:ChocolateyInstall='C:\ProgramData\chocoportable'

Start-Process -FilePath powershell -ArgumentList "-noprofile -noExit -ExecutionPolicy Bypass -File ""$outPath""" -Wait

# clean up
Remove-Item -Path $outPath

要查看更多的安装选项,请访问 https://chocolatey.org/install

以上脚本不需要管理员权限,以便携应用的方式安装 Chocolatey。要使用它,您需要临时将安装文件夹添加到 Windows 的 Path 环境变量。然后输入 choco 来测试安装情况。该命令将汇报它的版本号:

1
2
3
4
5
6
7
PS> $env:path += ";C:\ProgramData\chocoportable"

PS> choco
Chocolatey v0.10.8
Please run 'choco -?' or 'choco -?' for help menu.

PS>

我们将看看如何使用 Chocolatey 自动下载和安装 PowerShell Core 6,然后和您当前 Windows PowerShell 安装并行地使用它。

同时,访问 https://chocolatey.org/packages?q=notepadplusplus 来查看您是否可以通过 Chocolatey 来安装。以下是使用 Chocolatey 需要考虑的关键步骤:

  • 使用 PowerShell 控制台窗口。不要使用没有真正控制台窗口的 PowerShell 宿主(例如 ISE)
  • 如果可能,使用管理员权限运行 PowerShell。许多包需要完整的 Administrator 权限来安装软件
  • 将 Chocolatey 安装路径添加到 Path 环境变量

当您的环境准备好后,可以试试下载和安装一个工具,例如 Notepad++ 是多么简单:

PS C:\> $env:path += ";C:\ProgramData\chocoportable"
PS C:\> choco install notepadplusplus -y
Chocolatey v0.10.8
[Pending] Removing incomplete install for 'notepadplusplus'
Installing the following packages:
notepadplusplus
By installing you accept licenses for the packages.

notepadplusplus.install v7.5.6 [Approved]
notepadplusplus.install package files install completed. Performing ot
her installation steps.
Installing 64-bit notepadplusplus.install...
notepadplusplus.install has been installed.
notepadplusplus.install installed to 'C:\Program Files\Notepad++'
Added C:\ProgramData\chocoportable\bin\notepad++.exe shim pointed to '
c:\program files\notepad++\notepad++.exe'.
  notepadplusplus.install may be able to be automatically uninstalled.

 The install of notepadplusplus.install was successful.
  Software installed as 'exe', install location is likely default.

notepadplusplus v7.5.6 [Approved]
notepadplusplus package files install completed. Performing other inst
allation steps.
 The install of notepadplusplus was successful.
  Software install location not explicitly set, could be in package or

  default install location if installer.

Chocolatey installed 2/2 packages.
 See the log for details (C:\ProgramData\chocoportable\logs\chocolatey
.log).
PS C:\>

当 Chocolatey 完成安装 Notepad++ 的安装后,只需要按下 Win + R 键,然后在“运行”对话框中输入

Notepad++

编辑器就启动了。

PowerShell 技能连载 - 检查数字签名

当您从 internet 下载一个脚本时,它可能包含了一个数字签名,数字签名能帮您确定脚本是从哪里来的。我们在前一个技能里讨论了这个内容,以下是我们使用的代码:它将一个 PowerShell 脚本下载到磁盘,然后显示它的数字签名:

1
2
3
4
5
6
7
# save script to file
$url = 'https://chocolatey.org/install.ps1'
$outPath = "$env:temp\installChocolatey.ps1"
Invoke-WebRequest -UseBasicParsing -Uri $url -OutFile $outPath

# test signature
Get-AuthenticodeSignature -FilePath $outPath

结果类似这样:

    Directory: C:\Users\tobwe\AppData\Local\Temp


SignerCertificate                         Status         Path
-----------------                         ------         ----
493018BA27EAA09B895BC5660E77F694B84877C7  Valid          installChocolatey.ps1

“Status” 列报告了这个文件是否可信。然而如何获取更多的关于证书和它的所有者的信息,特别是找出 “493018BA27EAA09B895BC5660E77F694B84877C7” 是谁?

只需要将签名证书传给一个 Windows API 函数,就可以显示证书的属性对话框:

1
2
3
4
5
6
7
8
9
10
11
# save script to file
$url = 'https://chocolatey.org/install.ps1'
$outPath = "$env:temp\installChocolatey.ps1"
Invoke-WebRequest -UseBasicParsing -Uri $url -OutFile $outPath

# test signature
$result = Get-AuthenticodeSignature -FilePath $outPath
$signerCert = $result.SignerCertificate

Add-Type -Assembly System.Security
[Security.Cryptography.x509Certificates.X509Certificate2UI]::DisplayCertificate($signerCert)

现在您能了解到该证书编号指向 “Chocolatey Software, Inc” 公司,以及该证书是由 DigiCert 颁发。这是为什么 Windows 信任该签名:DigiCert 采取措施验证签名人的个人详细信息。

PowerShell 技能连载 - 信任下载的文件

通过 Internet 下载的脚本,很有可能被恶意软件感染过,或者源头是法非的数据来源。数字签名可以增加一个额外的信任和保护层。

作为示例,我们将测试官方的 “Chocolatey” 安装脚本,它的下载地址在这里:

https://chocolatey.org/install.ps1

当您在浏览器中打开这个 URL 时,您将会看到一个十分长的 PowerShell 脚本,您现在需要十分谨慎地检查每一行代码,在运行它之前确保它是完整的,并且不会作恶。

幸运的是,在脚本的尾部您会发现一个非常长的注释块。这是一个数字签名。要检查是否能够信任该脚本,以及它是否未被篡改过,您需要将该代码保存到一个文件中。然后,您可以验证签名:

1
2
3
4
5
6
7
# save script to file
$url = 'https://chocolatey.org/install.ps1'
$outPath = "$env:temp\installChocolatey.ps1"
Invoke-WebRequest -UseBasicParsing -Uri $url -OutFile $outPath

# test signature
Get-AuthenticodeSignature -FilePath $outPath

结果看起来类似这样:

    Directory: C:\Users\tobwe\AppData\Local\Temp


SignerCertificate                         Status         Path
-----------------                         ------         ----
493018BA27EAA09B895BC5660E77F694B84877C7  Valid          installChocolatey.ps1

如果 “Status” 列报告 “Valid”,那么说明:

  • 这个文件未被篡改过,是原始的内容
  • 该文件是由 “SignerCertificate” 报告的证书创建的

当然您不能理解 “493018BA27EAA09B895BC5660E77F694B84877C7” 是谁,但您可以确定 Windows 认为该证书是可信任的,,所以您可以十分安全地运行这个脚本(如果您想了解 493018BA27EAA09B895BC5660E77F694B84877C7 到底是谁,请看明天的技能)。

以下是 “Status” 其它可能的情况:

  • HashMismatch:文件内容被修改。这种情况高度可疑。
  • Unknown:签名的证书不被信任。任何人都有可能签名了这个文件。这个签名对您没有任何意义。
  • NotSigned:该脚本没有签名。

如果 Status 的值不是 Valid,那么该签名对您没有任何意义,在运行之前必须人工检查和测试代码。

如果 Status 的值是 Valid,那么您可以明确地确定创建脚本的人,而且您可以安全地认为它没有被其他人改过。不过,一个合法的签名并不是完全地保证,说明该脚本是无害的。