PowerShell 技能连载 - 验证 Active Directory 凭据
PowerShell 可以通过 Active Directory 验证 AD 用户名和密码:
1 | Add-Type -AssemblyName System.DirectoryServices.AccountManagement |
请注意这种方法只能作为诊断目的。它以明文的方式输入密码。
PowerShell 技能连载 - 验证 Active Directory 凭据
PowerShell 可以通过 Active Directory 验证 AD 用户名和密码:
1 | Add-Type -AssemblyName System.DirectoryServices.AccountManagement |
请注意这种方法只能作为诊断目的。它以明文的方式输入密码。
PowerShell 技能连载 - 为输出编号(第 1 部分)
如果你想增加一个递增的数字到你的输出,这里有一个简单的方法:
1 | Get-Process | |
Select-Object 添加了一个名为 “#“ 的新属性,ForEach-Object 添加了一个自动递增的数字。结果如下:
# ProcessName CPU
- ----------- ---
1 AdobeCollabSync 65,5625
2 AdobeCollabSync 0,5
3 AGMService
...
如果曾经写过需要接受密码等敏感输入的 PowerShell 函数,请确保允许用户传入 SecureString。如果您通过明文接受密码,则存在很大的风险,即其他人可能在输入密码时看到密码,或者(更糟的是)密码已被记录,稍后可以在转储文件中找到。
下面是一个简单的框架,说明如何实现安全输入:
1 | function Enter-Secret |
当用户运行 Enter-Secret,可以以屏蔽的方式输入密码。在内部,函数将安全字符串转换为纯文本。这样,秘密密码就永远不可见,也永远不会被记录下来。
从 SecureString 到 String 的转换是通过创建一个临时凭证对象来执行的。凭据对象有一个内置方法 (GetNetworkCredential()),用于将SecureString 转换为字符串。
PowerShell 技能连载 - 查找隐藏的 PowerShell 应用
最广为人知的 PowerShell 宿主当然是 PowerShell.exe 和 powershell_ise.exe,因为它们是开箱即用的。但是,运行 PowerShell 的宿主可能更多(而且是隐藏的)。任何实例化 PowerShell 引擎的软件都是一个 PowerShell 宿主。这可以是 Visual Studio Code(安装了 PowerShell扩展)、Visual Studio 或任何其它类似的软件。
要找出所有当前运行 PowerShell 的宿主,请运行以下命令:
1 | Get-ChildItem -Path "\\.\pipe\" -Filter '*pshost*' | |
结果看起来类似这样:
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
1131 101 628520 42440 11216 0 SupportAssistAgent
1011 82 269920 299208 85,30 17420 1 powershell_ise
520 29 68012 75880 1,23 33532 1 powershell
590 31 69508 77712 2,02 36636 1 powershell
545 27 67952 76668 1,14 37584 1 powershell
4114 654 801136 965032 129,69 28968 1 devenv
“SupportAssistAgent” 是由 Visual Studio Code 打开的,而 “devenv” 代表由 Visual Studio 启动的内部 PowerShell 宿主。
大多数现代计算机都有不止一个处理器,无论是物理处理器还是逻辑处理器。如果你想知道处理器的数量,这里有一段 PowerShell 代码:
1 | Get-WmiObject -Class Win32_Processor | |
结果看起来类似这样:
Caption NumberOfLogicalProcessors
------- -------------------------
Intel64 Family 6 Model 78 Stepping 3 4
当您在这样的机器上运行一个进程时,它通常没有特定的处理器关联性,因此 Windows 决定该进程将运行在哪个处理器上。
如果愿意,可以为每个进程声明一个特定的处理器关联。这是很有用的,例如,如果你想控制一个程序可以使用的处理器,也就是防止一个进程使用所有的处理器。
处理器关联性由位标志控制。要找出当前处理器与进程的关联关系,请使用以下代码:
1 | $process = Get-Process -Id $PID |
在本例中,用的是当前的 PowerShell 进程,但是您可以指定任何进程。典型的结果是:
1111
在 4 处理器的机器上,进程没有特定的关联性,可以使用任何处理器。要设置新的关联,最简单的方法是使用自己的位掩码并更改属性。例如,要将当前 PowerShell 进程仅锁定到第一个处理器,可以这样做:
1 | # calculate the bit mask |
PowerShell 技能连载 - 转储 Chrome 的所有密码
在前面的技能中,我们演示了如何从个人 Windows 密码库转储所有密码。基本上任何密码管理器都是如此,因为这些程序的目的是返回它们为您存储的密码。
谷歌 Chrome 浏览器将您的个人密码(和网站历史记录)存储在 SQLLite 数据库中。PowerShell 可以轻松地访问这个数据库并为您转储信息。但是,要做到这一点,PowerShell 需要不属于 Windows 的特定 SQLLite 程序集。
下面的代码展示了如何 (a) 通过一行程序下载大量代码,(b) 在下载的代码中嵌入一个二进制 .net 程序集。
警告:只能在演示机器上运行此代码,或者确保先下载代码,然后在运行之前仔细检查。代码是从第三方下载的,您永远不知道这些代码是否包含恶意内容。
如果你希望转储 Chrome 的隐私信息,我们建议你把代码下载到一个安全的机器上,隔离并检查它,然后在需要的时候从本地保存的副本中使用它。永远不要从不可信的来源下载和执行代码,除非仔细检查代码的实际功能:
1 | # download the code from GitHub |
注意,当Chrome运行时,SQLLite数据库被锁定。你需要关闭Chrome才能转储它的隐私数据。
代码来自未知或不可信源的事实并不意味着代码不好。事实上,当您查看代码时,您会发现一些有趣的技术:
1 | # download the code from GitHub |
您将看到,代码附带了访问 SQLLite 数据库所需的二进制 .net 程序集。二进制文件以 base64 编码为字符串。这是在你的电脑上恢复二进制的部分:
1 | $content = [System.Convert]::FromBase64String($assembly) |
下面是更多与安全相关的PowerShell单行程序:https://chrishales.wordpress.com/2018/01/03/powershell-password-one-liners/
PowerShell 技能连载 - 从 Windows 中转储个人密码
Windows 有一个受保护的密码库,它可以在其中存储您的密码,因此您不必始终在 InternetExplorer 或 Edge 中手动输入密码。
如果您习惯了自动密码管理器,可能偶尔会忘记原始密码。下面是一个超级简单的 PowerShell 方法来转储存储在 Windows 密码库中的所有密码:
1 | # important: this is required to load the assembly |
请注意,如果您从未在 InternetExplorer 或 Edge 中存储凭据,则不会得到任何结果。还请注意,此代码设计的工作方式:只有您只能检索密码,就像您在浏览器中访问网站并要求浏览器为您填写凭据一样。
转储所有存储的密码说明了为什么在您不在时始终锁定您的计算机是如此重要。如果您让您的计算机无人值守的话,任何人都可以运行此 PowerShell 代码来转储您的个人密码。
PowerShell 技能连载 - 通过 PowerShell 安装 Google Chrome
要下载并安装谷歌Chrome浏览器,只需几个常见的 PowerShell 命令组合:
1 | $Installer = "$env:temp\chrome_installer.exe" |
PowerShell 技能连载 - 使用始终可见的弹出对话框
在上一个技能中,我们使用了一种古老的 COM 技术来显示带有内置超时的弹出框。除了对话框有时会被覆盖在 PowerShell 窗口下之外,这种方法运行得非常好。
通过一个鲜为人知的技巧,你可以确保对话框总是打开在所有其他窗口的顶部:
1 | $shell = New-Object -ComObject WScript.Shell |
关键是在参数中添加 4096 来控制按钮和图标。这将该对话框转换为模态对话框:它保证在所有现有窗口之上打开,并且永远不会被覆盖。
使用哈希表来包装所有这些幻数,这又是一个好办法:
1 | $timeoutSeconds = 5 |
也许你在过去偶然见过这样的代码:
1 | $shell = New-Object -ComObject WScript.Shell |
这段代码打开一个对话框,询问用户是否可以重启计算机。弹出对话框有一个内置超时设置,因此即使在无人值守的情况下运行,代码也不会停止。
但是,由于 PowerShell 使用的是一种旧的 COM 方法,它是由加密的 ID 来控制。用户无法理解 “36” 表示一个带有 YesNo 按钮和问号的对话框。那么如何转义返回的值呢?
哈希表可以以一种简单的方法来包装代码数字,并使代码更具可读性。请看:
1 | $timeoutSeconds = 5 |
多亏了哈希表,代码使用 $buttons.YesNo + $icon.Question 而不是指定 “36”,而且一旦运行了代码(这样就定义了哈希表),甚至可以获得可用选项的智能感知。
同样,通过使用原始返回值作为哈希表的键,可以轻松地将返回代码转换为人类可读的格式。通过这种方式,您可以使用 switch 语句并为用户单击的按钮分配脚本块,而不必知道单个按钮代码。