有没有办法将 Powershell 中现有 Chrome Web 会话中已获取的 Cookie 用于 SessionVariable?
我知道 SessionVariable 的字段是:
Headers : {}
Cookies : System.Net.CookieContainer
UseDefaultCredentials : False
Credentials :
Certificates :
UserAgent : Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US)
WindowsPowerShell/5.1.17134.407
Proxy :
MaximumRedirection : -1
我是否可以做一些事情来最初为网络请求设置这些值,例如:?当会话可能有多个/不同类型的请求时,我是否需要特定的标头?
$ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"
$Params = @{
Headers = $headers
Cookies = $cookies
UseDefaultCredentials = "False"
Credentials = $creds
UserAgent = $ua
Proxy = ""
MaximumRedirection = "-1"
}
如果可以做这样的事情,我也有点困惑如何输入cookie。我从使用 PowerShell 获取 Cookies 找到了这个:
$webrequest = Invoke-WebRequest -Uri $url -SessionVariable websession
$cookies = $websession.Cookies.GetCookies($url)
# Here, you can output all of $cookies, or you can go through them one by one.
foreach ($cookie in $cookies) {
# You can get cookie specifics, or just use $cookie
# This gets each cookie's name and value
Write-Host "$($cookie.name) = $($cookie.value)"
}
我可以从任何给定站点以这种格式导出 cookie,但如果需要的话,我也可以将其缩减为“名称”=“值”。
[
{
"domain": "",
"expirationDate": "",
"hostOnly": "",
"httpOnly": "",
"name": "",
"path": "",
"sameSite": "",
"secure": "",
"session": "",
"storeId": "",
"value": "",
"id": ""
},
{
"domain": "",
etc...
}
]
我不知道如何将每个部分指定为 $cookies 中的 $cookie,也不知道如何以不同的方式添加它们,因为它不是来自 URL/WebRequest,而是来自 JSON。
感谢您的帮助!
这是使用 mySQLite 和 Bouncy Castle( Gist)作为 PowerShell 脚本的解决方案:
# One time setup
if (-not (Get-Package 'Portable.BouncyCastle' -ErrorAction Ignore)) {
if (-not (Get-PackageSource -Name NuGet -ErrorAction Ignore)) {
Register-PackageSource -Name NuGet -Location https://api.nuget.org/v3/index.json -ProviderName NuGet | Set-PackageSource -Trusted
}
Install-Package -Name 'Portable.BouncyCastle' -Source NuGet -Scope CurrentUser -SkipDependencies
}
# Download the MySQLite repository (for PowerShell <5 without PowerShellGet)
if (-not(Get-Module -Name MySQLite -ErrorAction Ignore) -and ($PSVersionTable.PSVersion.Major -lt 5)) {
$RepositoryZipUrl = 'https://api.github.com/repos/jdhitsolutions/MySQLite/zipball/master'
Invoke-RestMethod -Uri $RepositoryZipUrl -OutFile 'MySQLite.zip'
# Unblock the zip
Unblock-File 'MySQLite.zip'
# Extract the MySQLite folder to a module path (e.g. $env:USERPROFILE\Documents\WindowsPowerShell\Modules\)
Expand-Archive -Path 'MySQLite.zip' -DestinationPath $($env:PSModulePath -split [System.IO.Path]::PathSeparator | Where-Object { (Test-Path -Path $_ -PathType Container -ErrorAction SilentlyContinue) -and $(try { $tmp = New-Item -Path $_ -Name ([System.IO.Path]::GetRandomFileName()) -ItemType File -Value (Get-Random) -ErrorAction SilentlyContinue; Remove-Item -Path $tmp; $true | Write-Output } catch { $false | Write-Output } ) } | Select-Object -First 1) -Force -Confirm
}
elseif (-not(Get-Module -Name MySQLite -ErrorAction Ignore) -and ($PSVersionTable.PSVersion.Major -ge 5)) {
#Simple alternative, if you have PowerShell ≥5, or the PowerShellGet module:
Install-Module MySQLite -Repository PSGallery -Scope CurrentUser
}
# Import the MySQLite module
Import-Module MySQLite #Alternatively, Import-Module \\Path\To\MySQLite
# Import Bouncy Castle Classes
Get-Package 'Portable.BouncyCastle' | ForEach-Object { Add-Type -LiteralPath ($_.Source | Split-Path | Get-ChildItem -Filter 'netstandard*' -Recurse -Directory | Get-ChildItem -Filter *.dll -Recurse -File ).FullName }
# Specify for which domain you want to retrieve cookies
$domain = 'mavaddat.ca'
$cookiesPath = "$env:LOCALAPPDATA\Google\Chrome Beta\User Data\Default\Network\Cookies" # "$env:LOCALAPPDATA\Microsoft\Edge\User Data\Default\Network\Cookies" # "$env:APPDATA\Opera Software\Opera Stable\Cookies"
# Investigate the db structure
Get-MySQLiteTable -Path $cookiesPath -Detail
# Based on the schema of table `cookies`, form the query
$query = "SELECT name,encrypted_value,path,host_key FROM `"main`".`"cookies`" WHERE `"host_key`" LIKE '%$domain%' ESCAPE '\' LIMIT 0, 49999;"
# Or, get all cookies for all domains
$query = "SELECT name,encrypted_value,path,host_key FROM `"main`".`"cookies`" LIMIT 0, 49999;"
# Read the cookies from the SQLite
$cookies = Invoke-MySQLiteQuery -Path $cookiesPath -Query $query
# Get Chromium cookie master key
$localStatePath = "$env:LOCALAPPDATA\Google\Chrome Beta\User Data\Local State" # "$env:LOCALAPPDATA\Microsoft\Edge\User Data\Local State" # "$env:APPDATA\Opera Software\Opera Stable\Local State"
$cookiesKeyEncBaseSixtyFour = (Get-Content -Path $localStatePath | ConvertFrom-Json).'os_crypt'.'encrypted_key'
$cookiesKeyEnc = [System.Convert]::FromBase64String($cookiesKeyEncBaseSixtyFour) | Select-Object -Skip ([System.Text.Encoding]::UTF8.GetBytes('DPAPI').Count)
$cookiesKey = [System.Security.Cryptography.ProtectedData]::Unprotect($cookiesKeyEnc, $null, [System.Security.Cryptography.DataProtectionScope]::LocalMachine)
# Create a web session object for the IWR work
$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession
# Prep the cipher elements
$cipher = [Org.BouncyCastle.Crypto.Modes.GcmBlockCipher]::new([Org.BouncyCastle.Crypto.Engines.AesEngine]::new())
# Stuff the cookies into the session
foreach ($cookie in $cookies) {
$path = [string]::IsNullOrEmpty($cookie.path) ? '/' : $cookie.path
try {
$cipherStream = [System.IO.MemoryStream]::new($cookie.encrypted_value)
$cipherReader = [System.IO.BinaryReader]::new($cipherStream)
<#
# We don't need to keep the non-secret payload; however, this is how to retrieve it (spoiler alert, it's 'v10')
$nonSecretPayload = $cipherReader.ReadBytes(([System.Text.Encoding]::ASCII.GetBytes('v10').Count)) #
# if you want to read this, just use
[System.Text.Encoding]::Default.GetString($nonSecretPayload) | Out-Host
#>
# Alternatively, if you don't care about 'v10', move the stream pointer past it
$cipherReader.BaseStream.Position = [System.Text.Encoding]::ASCII.GetBytes('v10').Count
$nonce = $cipherReader.ReadBytes([System.Security.Cryptography.AesGcm]::NonceByteSizes.MinSize)
$parameters = [Org.BouncyCastle.Crypto.Parameters.AeadParameters]::new( ([Org.BouncyCastle.Crypto.Parameters.KeyParameter]::new($cookiesKey)), ([System.Security.Cryptography.AesGcm]::TagByteSizes.MaxSize * [byte]::MaxValue.GetShortestBitLength()), $nonce)
$cipher.Init($false, $parameters)
$cipherText = $cipherReader.ReadBytes($cookie.encrypted_value.Length)
$plainText = [byte[]]::new($cipher.GetOutputSize($cipherText.Length))
if (-not [string]::IsNullOrEmpty($plainText)) {
try {
$len = $cipher.ProcessBytes($cipherText, 0, $cipherText.Length, $plainText, 0)
$bytesDeciphered = $cipher.DoFinal($plainText, $len)
Write-Verbose "Deciphered $bytesDeciphered bytes"
}
catch [System.Management.Automation.MethodInvocationException] {
# if inner exception [Org.BouncyCastle.Crypto.InvalidCipherTextException]
if ($_.Exception.InnerException -is [Org.BouncyCastle.Crypto.InvalidCipherTextException]) {
Write-Error 'Invalid Cipher Text'
}
else {
Write-Error $_ # Echo the error unless you have a better way to handle
}
continue
}
finally {
$cipher.Reset()
}
try {
$session.Cookies.Add([System.Net.Cookie]::new(($cookie.name), [System.Text.Encoding]::Default.GetString($plainText), $path, ($cookie.host_key -replace '^\.')))
}
catch [System.Management.Automation.MethodInvocationException] {
if ($_.Exception.InnerException -is [System.Net.CookieException]) {
$session.Cookies.Add([System.Net.Cookie]::new(($cookie.name), [System.Web.HttpUtility]::UrlEncode([System.Text.Encoding]::Default.GetString($plainText)), $path, ($cookie.host_key -replace '^\.')))
}
else {
Write-Error $_ # Echo the error unless you have a better way to handle
}
}
}
}
finally {
$cipherStream.Dispose()
$cipherReader.Dispose()
}
}
# Remove sensitive objects
$cipherReader = $null
$cipherStream = $null
$cookiesKey = $null
$cookiesKeyEnc = $null
$cookiesKeyEncBaseSixtyFour = $null
$nonce = $null
$cipher = $null
$cipherText = $null
$plainText = $null
Remove-Variable cipher, cipherReader, cipherStream, cookiesKey, cookiesKeyEnc, cookiesKeyEncBaseSixtyFour, nonce, cipherText, plainText
# Do IWR Work
Invoke-WebRequest -Uri $domain -WebSession $session
有两个Chromium文件需要查询:
User Data
当地州User Data
是一个 JSON 格式的文件,用于保存 cookie 的加密密钥。对于我(在 Windows 11 上使用 Chrome Beta 107.0.5304.18)来说,这是 %LOCALAPPDATA%\Google\Chrome Beta\User Data\Local State
。
基于 Chromium 的浏览器使用存储在二进制 SQLite 数据库文件中的 cookie。请参阅有关如何查找 Chrome 数据库的超级用户问题,“有办法实时观看 cookie 及其值吗?”.
对我来说,这个文件名为Cookies
,它位于
%LOCALAPPDATA%\Google\Chrome Beta\User Data\Default\Network\Cookies
。使用MySQLite,我可以看到数据库有两个具有以下模式的表:
Cookies
桌子
Meta
桌子
“如何在 C# (.NET Core) 中读取 Brave Browser cookie 数据库加密值?” 我还遵循了 @lawrencegripper 的 this gist 的 PowerShell cookie 方法作为模板。