mirror of
https://github.com/moonD4rk/HackBrowserData.git
synced 2026-10-13 03:37:12 +02:00
docs: rewrite readme, rfcs, and contributing (#555)
* docs: rewrite README, RFCs, and CONTRIBUTING * docs: fix Linux storage labels in RFC-006 (Opera/Vivaldi swapped)
This commit is contained in:
1 parent
2ee7d0ac79
commit
d8032ac824
15 files changed
+1412
-2133
No files matched your search
@@ -0,0 +1,120 @@
|
||||
# RFC-009: Windows Locked File Bypass
|
||||
|
||||
**Author**: moonD4rk
|
||||
**Status**: Living Document
|
||||
**Created**: 2026-04-05
|
||||
|
||||
## 1. Problem
|
||||
|
||||
Chromium on Windows sets `PRAGMA locking_mode=EXCLUSIVE` on certain SQLite databases, most notably the `Cookies` file (`Network/Cookies`). This means Chrome's process holds the file open with `dwShareMode=0` (no sharing), preventing any other process from opening it — even for reading.
|
||||
|
||||
```
|
||||
Chrome.exe
|
||||
→ CreateFileW("Network/Cookies", ..., dwShareMode=0) // exclusive lock
|
||||
→ PRAGMA locking_mode=EXCLUSIVE
|
||||
|
||||
hack-browser-data.exe
|
||||
→ os.ReadFile("Network/Cookies")
|
||||
→ ERROR: access denied
|
||||
```
|
||||
|
||||
This is a **Windows-specific problem**. On macOS and Linux, SQLite uses `fcntl`/`flock` advisory locks, which do not prevent other processes from reading the file. The standard copy path works fine on those platforms.
|
||||
|
||||
## 2. Solution Overview
|
||||
|
||||
Bypass the exclusive lock using Windows kernel APIs: enumerate system handles to find Chrome's file handle, duplicate it into our process, then read the file contents via memory-mapped I/O. **No admin privileges required.**
|
||||
|
||||
```
|
||||
NtQuerySystemInformation → find Chrome's handle to Cookies file
|
||||
→ DuplicateHandle into our process
|
||||
→ CreateFileMappingW + MapViewOfFile (read from kernel cache)
|
||||
→ write bytes to temp destination
|
||||
```
|
||||
|
||||
## 3. Step-by-Step
|
||||
|
||||
### 3.1 Enumerate System Handles
|
||||
|
||||
Call `NtQuerySystemInformation` with `SystemExtendedHandleInformation` (class 64) to get every open handle in the system. The "extended" variant uses `ULONG_PTR` for PIDs and handle values, avoiding truncation on 64-bit Windows.
|
||||
|
||||
The query starts with a 4 MB buffer and doubles it (up to 256 MB) if the API returns `STATUS_INFO_LENGTH_MISMATCH`.
|
||||
|
||||
Each entry in the result table:
|
||||
|
||||
| Field | Size | Description |
|
||||
|-------|------|-------------|
|
||||
| UniqueProcessID | `uintptr` | Owning process PID |
|
||||
| HandleValue | `uintptr` | Handle value in the owning process |
|
||||
| GrantedAccess | `uint32` | Access mask |
|
||||
| ObjectTypeIndex | `uint16` | Kernel object type |
|
||||
|
||||
### 3.2 Find the Target Handle
|
||||
|
||||
For each handle entry:
|
||||
|
||||
1. `OpenProcess(PROCESS_DUP_HANDLE, pid)` — open the owning process
|
||||
2. `DuplicateHandle` — duplicate the handle into our process with `DUPLICATE_SAME_ACCESS`
|
||||
3. `GetFileType` — verify it is `FILE_TYPE_DISK` (skip pipes, sockets, etc.)
|
||||
4. `GetFinalPathNameByHandleW` — get the full file path
|
||||
|
||||
### 3.3 Path Matching with Short-Name Tolerance
|
||||
|
||||
Windows 8.3 short path names (e.g. `RUNNER~1` vs `runneradmin`) cause direct path comparison to fail. The solution extracts a **stable suffix** by stripping everything before `AppData\Local\` or `AppData\Roaming\` and comparing in lowercase:
|
||||
|
||||
```
|
||||
Input: C:\Users\RUNNER~1\AppData\Local\Google\Chrome\...\Network\Cookies
|
||||
Suffix: google\chrome\...\network\cookies
|
||||
|
||||
Input: C:\Users\runneradmin\AppData\Local\Google\Chrome\...\Network\Cookies
|
||||
Suffix: google\chrome\...\network\cookies
|
||||
|
||||
→ match!
|
||||
```
|
||||
|
||||
### 3.4 Read via Memory-Mapped I/O
|
||||
|
||||
Once we have a duplicated handle to the locked file:
|
||||
|
||||
```
|
||||
| DuplicateHandle (read access) |
|
||||
|-------------------------------------------------|
|
||||
↓
|
||||
| CreateFileMappingW(handle, PAGE_READONLY) |
|
||||
|-------------------------------------------------|
|
||||
↓
|
||||
| MapViewOfFile(mapping, FILE_MAP_READ, fileSize) |
|
||||
|-------------------------------------------------|
|
||||
↓
|
||||
| byte slice from kernel file cache |
|
||||
| (includes uncommitted WAL data from Chrome) |
|
||||
|-------------------------------------------------|
|
||||
↓
|
||||
| os.WriteFile(destination, bytes, 0600) |
|
||||
|-------------------------------------------------|
|
||||
```
|
||||
|
||||
Memory-mapped I/O reads from the OS kernel's **file cache**, which includes data Chrome has written but not yet checkpointed to disk. This produces a more complete snapshot than a raw `ReadFile`.
|
||||
|
||||
**Fallback**: if `CreateFileMappingW` fails (e.g., the file is empty or zero-length), falls back to `Seek(0)` + `ReadFile` on the duplicated handle.
|
||||
|
||||
## 4. Why This Works
|
||||
|
||||
The key insight is that `dwShareMode=0` only prevents **new** `CreateFileW` calls from opening the file. It does **not** prevent:
|
||||
|
||||
- `DuplicateHandle` — which creates a copy of an existing handle (Chrome's own handle)
|
||||
- `CreateFileMappingW` — which operates on a handle we already own
|
||||
- `MapViewOfFile` — which reads from the kernel's page cache
|
||||
|
||||
This is a documented Windows behavior, not an exploit. The technique requires only standard user privileges because `PROCESS_DUP_HANDLE` access is available for processes owned by the same user.
|
||||
|
||||
## 5. Limitations
|
||||
|
||||
- **Performance**: enumerating all system handles is expensive (the system may have 100,000+ handles). The entire table must be scanned to find the target file.
|
||||
- **Race condition**: Chrome could close and reopen the file between enumeration and duplication, though this is unlikely for long-lived database files.
|
||||
- **Not needed on macOS/Linux**: advisory locking on these platforms does not prevent reading, so the standard `copyFile` path is always sufficient.
|
||||
|
||||
## Related RFCs
|
||||
|
||||
| RFC | Topic |
|
||||
|-----|-------|
|
||||
| [RFC-008](008-file-acquisition-and-platform-quirks.md) | File acquisition lifecycle and session management |
|
||||
Reference in new issue
Block a user