initial commit
This commit is contained in:
190
Dat File Script/decrypt-dat-file.md
Normal file
190
Dat File Script/decrypt-dat-file.md
Normal file
@@ -0,0 +1,190 @@
|
||||
# How to read/edit `store.dat` on Windows
|
||||
|
||||
## What this does
|
||||
|
||||
- Decrypts `%AppData%\rIDE\<userId>\store.dat` using Windows **DPAPI
|
||||
(CurrentUser)**.
|
||||
- Lets you **view** keys and **update** a value (e.g., `GithubToken`,
|
||||
`SupabaseToken`, etc.).
|
||||
- Must be run **as the same Windows user account** that created the
|
||||
file.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
## 0) One-time setup
|
||||
|
||||
1. **Save the script** (name it exactly): `decrypt-dat-file.ps1`\
|
||||
(Use the version Jimmy shared --- it already loads the
|
||||
`System.Security` assembly and includes `Set-StoreValue`.)
|
||||
|
||||
2. Put it somewhere easy, e.g.:
|
||||
|
||||
C:\Users\<you>\OneDrive\Desktop\Codebuddy\decrypt-dat-file.ps1
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
## 1) Open PowerShell & allow running the script (this session only)
|
||||
|
||||
``` powershell
|
||||
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
|
||||
```
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
## 2) Find your `userId` folder and back up the file
|
||||
|
||||
`store.dat` lives at:
|
||||
|
||||
%AppData%\rIDE\<userId>\store.dat
|
||||
|
||||
In PowerShell, reference `%AppData%` as `$env:APPDATA`. Example:
|
||||
|
||||
``` powershell
|
||||
# Replace <userId> with the actual folder name (GUID)
|
||||
cd "$env:APPDATA\rIDE\<userId>"
|
||||
Copy .\store.dat .\store.bak
|
||||
```
|
||||
|
||||
> Tip: to list the available userId folders:
|
||||
|
||||
``` powershell
|
||||
Get-ChildItem "$env:APPDATA\rIDE"
|
||||
```
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
## 3) List keys / read values (no edits yet)
|
||||
|
||||
### Option A --- run the script with parameters (no functions loaded)
|
||||
|
||||
Use the **call operator** `&` when passing parameters:
|
||||
|
||||
``` powershell
|
||||
& "C:\Users\<you>\OneDrive\Desktop\Codebuddy\decrypt-dat-file.ps1" -UserId "<userId>" -ListKeys
|
||||
# Example output: GithubToken, SupabaseToken, AzureAccessToken, ...
|
||||
```
|
||||
|
||||
Read a specific key:
|
||||
|
||||
``` powershell
|
||||
& "C:\Users\<you>\OneDrive\Desktop\Codebuddy\decrypt-dat-file.ps1" -UserId "<userId>" -Key GithubToken -Raw
|
||||
```
|
||||
|
||||
> `-Raw` prints the exact string. Without `-Raw`, JSON values (like
|
||||
> `SupabaseToken`) are pretty-printed.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
## 4) Edit a value
|
||||
|
||||
You have **two ways** to edit:
|
||||
|
||||
### Option A (recommended): *dot-source* once, then call `Set-StoreValue`
|
||||
|
||||
Dot-sourcing loads the helper functions into your shell:
|
||||
|
||||
``` powershell
|
||||
. "C:\Users\<you>\OneDrive\Desktop\Codebuddy\decrypt-dat-file.ps1"
|
||||
```
|
||||
|
||||
Now update a key:
|
||||
|
||||
- **Plain string key** (e.g., `GithubToken`):
|
||||
|
||||
``` powershell
|
||||
Set-StoreValue -UserId "<userId>" -Key "GithubToken" -Value "ghp_or_ghu_yourNewTokenHere"
|
||||
```
|
||||
|
||||
- **JSON key** (e.g., `SupabaseToken` expects JSON):
|
||||
|
||||
``` powershell
|
||||
$newPat = '{"AccessToken":"myNewSupabasePAT","RefreshToken":null,"ExpiresAt":"2025-12-31T23:59:59Z"}'
|
||||
Set-StoreValue -UserId "<userId>" -Key "SupabaseToken" -Value $newPat
|
||||
```
|
||||
|
||||
Verify:
|
||||
|
||||
``` powershell
|
||||
& "C:\Users\<you>\OneDrive\Desktop\Codebuddy\decrypt-dat-file.ps1" -UserId "<userId>" -Key GithubToken -Raw
|
||||
# or
|
||||
& "C:\Users\<you>\OneDrive\Desktop\Codebuddy\decrypt-dat-file.ps1" -UserId "<userId>" -Key SupabaseToken
|
||||
```
|
||||
|
||||
### Option B: stay "no functions" and only run the script
|
||||
|
||||
Use this only to **view** or **list**; editing requires Option A.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
## 5) Common pitfalls & fixes
|
||||
|
||||
- **`The term 'Set-StoreValue' is not recognized`**\
|
||||
You *ran* the script but didn't dot-source it. Dot-source first:
|
||||
|
||||
``` powershell
|
||||
. "C:\Users\<you>\OneDrive\Desktop\Codebuddy\decrypt-dat-file.ps1"
|
||||
```
|
||||
|
||||
- **`Unable to find type [System.Security.Cryptography.ProtectedData]`**\
|
||||
Use the script Jimmy provided (it includes
|
||||
`Add-Type -AssemblyName System.Security`).\
|
||||
If you still see it:
|
||||
|
||||
``` powershell
|
||||
Add-Type -AssemblyName System.Security
|
||||
```
|
||||
|
||||
- **`DPAPI Unprotect failed...`**\
|
||||
You're not running as the same Windows user that created the file.
|
||||
Switch to that user profile.
|
||||
|
||||
- **`%AppData%` doesn't work in PowerShell**\
|
||||
Use `$env:APPDATA` (PowerShell style):
|
||||
|
||||
``` powershell
|
||||
cd "$env:APPDATA\rIDE\<userId>"
|
||||
```
|
||||
|
||||
- **Edited value shape**
|
||||
|
||||
- Keys like `GithubToken` are **plain strings**.\
|
||||
- Keys like `SupabaseToken` and `projectSecret_*` are **JSON**.
|
||||
Make sure you pass valid JSON.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
## 6) Quick examples (ready to paste)
|
||||
|
||||
### List keys
|
||||
|
||||
``` powershell
|
||||
& "C:\Users\<you>\OneDrive\Desktop\Codebuddy\decrypt-dat-file.ps1" -UserId "<userId>" -ListKeys
|
||||
```
|
||||
|
||||
### Read GitHub token (raw)
|
||||
|
||||
``` powershell
|
||||
& "C:\Users\<you>\OneDrive\Desktop\Codebuddy\decrypt-dat-file.ps1" -UserId "<userId>" -Key GithubToken -Raw
|
||||
```
|
||||
|
||||
### Update GitHub token
|
||||
|
||||
``` powershell
|
||||
. "C:\Users\<you>\OneDrive\Desktop\Codebuddy\decrypt-dat-file.ps1"
|
||||
Set-StoreValue -UserId "<userId>" -Key "GithubToken" -Value "ghp_or_ghu_yourNewTokenHere"
|
||||
```
|
||||
|
||||
### Update Supabase token (JSON)
|
||||
|
||||
``` powershell
|
||||
. "C:\Users\<you>\OneDrive\Desktop\Codebuddy\decrypt-dat-file.ps1"
|
||||
$newPat = '{"AccessToken":"myNewSupabasePAT","RefreshToken":null,"ExpiresAt":"2025-12-31T23:59:59Z"}'
|
||||
Set-StoreValue -UserId "<userId>" -Key "SupabaseToken" -Value $newPat
|
||||
```
|
||||
|
||||
### Verify
|
||||
|
||||
``` powershell
|
||||
& "C:\Users\<you>\OneDrive\Desktop\Codebuddy\decrypt-dat-file.ps1" -UserId "<userId>" -Key GithubToken -Raw
|
||||
& "C:\Users\<you>\OneDrive\Desktop\Codebuddy\decrypt-dat-file.ps1" -UserId "<userId>" -Key SupabaseToken
|
||||
```
|
||||
196
Dat File Script/decrypt-dat-file.ps1
Normal file
196
Dat File Script/decrypt-dat-file.ps1
Normal file
@@ -0,0 +1,196 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Decrypts and edits rIDE SecureLocalStorage store.dat (DPAPI CurrentUser).
|
||||
Works on Windows PowerShell 5.1 and PowerShell 7+.
|
||||
|
||||
.PARAMETER UserId
|
||||
The userId subfolder under %AppData%\rIDE\. Use "." with -AppDataOverride "." if you're already in the folder.
|
||||
|
||||
.PARAMETER Key
|
||||
Optional. If provided, prints only this key's value.
|
||||
|
||||
.PARAMETER ListKeys
|
||||
Optional. If set, prints only the available keys.
|
||||
|
||||
.PARAMETER AppDataOverride
|
||||
Optional. Override base AppData path (defaults to [Environment]::GetFolderPath("ApplicationData")).
|
||||
Example: -AppDataOverride "." to use .\store.dat in the current directory.
|
||||
|
||||
.PARAMETER Raw
|
||||
Optional. Output raw strings (no pretty objects / nested JSON parsing).
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$UserId,
|
||||
|
||||
[string]$Key,
|
||||
|
||||
[switch]$ListKeys,
|
||||
|
||||
[string]$AppDataOverride,
|
||||
|
||||
[switch]$Raw
|
||||
)
|
||||
|
||||
# Ensure DPAPI types exist
|
||||
Add-Type -AssemblyName System.Security
|
||||
|
||||
# ---- Helpers ----
|
||||
|
||||
# Convert PSObject/arrays into pure hashtables/arrays so PS 5.1 works like PS7 -AsHashtable
|
||||
function Convert-PSObjectToHashtable {
|
||||
param([Parameter(ValueFromPipeline=$true)]$InputObject)
|
||||
process {
|
||||
if ($null -eq $InputObject) { return $null }
|
||||
|
||||
if ($InputObject -is [System.Collections.IDictionary]) {
|
||||
$ht = @{}
|
||||
foreach ($k in $InputObject.Keys) {
|
||||
$ht[$k] = Convert-PSObjectToHashtable $InputObject[$k]
|
||||
}
|
||||
return $ht
|
||||
}
|
||||
|
||||
if ($InputObject -is [System.Collections.IEnumerable] -and -not ($InputObject -is [string])) {
|
||||
$arr = @()
|
||||
foreach ($item in $InputObject) { $arr += ,(Convert-PSObjectToHashtable $item) }
|
||||
return $arr
|
||||
}
|
||||
|
||||
if ($InputObject -is [psobject]) {
|
||||
$ht = @{}
|
||||
foreach ($p in $InputObject.PSObject.Properties) {
|
||||
$ht[$p.Name] = Convert-PSObjectToHashtable $p.Value
|
||||
}
|
||||
return $ht
|
||||
}
|
||||
|
||||
return $InputObject
|
||||
}
|
||||
}
|
||||
|
||||
function Get-StorePath {
|
||||
param([string]$UserId, [string]$AppDataOverride)
|
||||
|
||||
$appData = if ($AppDataOverride) { $AppDataOverride } else { [Environment]::GetFolderPath("ApplicationData") }
|
||||
# Code uses "rIDE" but Windows is case-insensitive
|
||||
$dir = Join-Path (Join-Path $appData "rIDE") $UserId
|
||||
return Join-Path $dir "store.dat"
|
||||
}
|
||||
|
||||
function Read-DecryptedStore {
|
||||
param([string]$Path)
|
||||
|
||||
if (-not (Test-Path -LiteralPath $Path)) { throw "File not found: $Path" }
|
||||
|
||||
try {
|
||||
$encBytes = [System.IO.File]::ReadAllBytes($Path)
|
||||
} catch {
|
||||
throw "Unable to read file '$Path': $($_.Exception.Message)"
|
||||
}
|
||||
|
||||
try {
|
||||
$decBytes = [System.Security.Cryptography.ProtectedData]::Unprotect(
|
||||
$encBytes, $null,
|
||||
[System.Security.Cryptography.DataProtectionScope]::CurrentUser
|
||||
)
|
||||
} catch {
|
||||
throw "DPAPI Unprotect failed. Are you running as the SAME Windows user that created the file? Inner: $($_.Exception.Message)"
|
||||
}
|
||||
|
||||
$json = [System.Text.Encoding]::UTF8.GetString($decBytes)
|
||||
|
||||
try {
|
||||
$obj = $json | ConvertFrom-Json
|
||||
$dict = Convert-PSObjectToHashtable $obj # PS5.1-safe
|
||||
if ($dict -isnot [hashtable]) { throw "Expected a JSON object/dictionary at the top level." }
|
||||
return $dict
|
||||
} catch {
|
||||
throw "Decrypted bytes were not valid JSON: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
function Try-ParseJson {
|
||||
param([string]$s)
|
||||
try {
|
||||
if ($null -ne $s -and ($s.TrimStart().StartsWith('{') -or $s.TrimStart().StartsWith('['))) {
|
||||
return $s | ConvertFrom-Json
|
||||
}
|
||||
} catch { }
|
||||
return $s
|
||||
}
|
||||
|
||||
function Write-EncryptedStore {
|
||||
param(
|
||||
[string]$Path,
|
||||
[hashtable]$Store
|
||||
)
|
||||
|
||||
$json = $Store | ConvertTo-Json -Depth 10 -Compress
|
||||
$bytes = [System.Text.Encoding]::UTF8.GetBytes($json)
|
||||
$enc = [System.Security.Cryptography.ProtectedData]::Protect(
|
||||
$bytes, $null,
|
||||
[System.Security.Cryptography.DataProtectionScope]::CurrentUser
|
||||
)
|
||||
[System.IO.File]::WriteAllBytes($Path, $enc)
|
||||
}
|
||||
|
||||
function Set-StoreValue {
|
||||
param(
|
||||
[string]$UserId,
|
||||
[string]$Key,
|
||||
[string]$Value,
|
||||
[string]$AppDataOverride
|
||||
)
|
||||
|
||||
$path = Get-StorePath -UserId $UserId -AppDataOverride $AppDataOverride
|
||||
$store = Read-DecryptedStore -Path $path
|
||||
|
||||
$store[$Key] = $Value
|
||||
Write-EncryptedStore -Path $path -Store $store
|
||||
Write-Host "Key '$Key' updated successfully in $path"
|
||||
}
|
||||
|
||||
# ---- Main (print/list/single-key) ----
|
||||
$path = Get-StorePath -UserId $UserId -AppDataOverride $AppDataOverride
|
||||
|
||||
try {
|
||||
$store = Read-DecryptedStore -Path $path
|
||||
} catch {
|
||||
Write-Error $_.Exception.Message
|
||||
exit 1
|
||||
}
|
||||
|
||||
if ($ListKeys) {
|
||||
$store.Keys | Sort-Object
|
||||
exit 0
|
||||
}
|
||||
|
||||
if ($Key) {
|
||||
if ($store.ContainsKey($Key)) {
|
||||
$val = $store[$Key]
|
||||
if ($Raw) {
|
||||
$val
|
||||
} else {
|
||||
$parsed = Try-ParseJson -s $val
|
||||
$parsed | ConvertTo-Json -Depth 10
|
||||
}
|
||||
exit 0
|
||||
} else {
|
||||
Write-Error "Key '$Key' not found. Use -ListKeys to see available keys."
|
||||
exit 2
|
||||
}
|
||||
}
|
||||
|
||||
# No key specified: show entire dictionary (pretty where possible)
|
||||
if ($Raw) {
|
||||
$store.GetEnumerator() | Sort-Object Name | ForEach-Object {
|
||||
"{0} = {1}" -f $_.Key, $_.Value
|
||||
}
|
||||
} else {
|
||||
$pretty = @{}
|
||||
foreach ($k in $store.Keys) { $pretty[$k] = Try-ParseJson -s $store[$k] }
|
||||
$pretty | ConvertTo-Json -Depth 10
|
||||
}
|
||||
Reference in New Issue
Block a user