|
''' |
|
Proof of concept way to get cookies from chrome on Windows.. even when they're locked. |
|
Does not require admin rights. |
|
|
|
Includes a pure-python version of release_file_lock from: |
|
https://github.com/thewh1teagle/rookie/blob/02995bbbb692f775e12368e7fb2b728775c88ddd/rookie-rs/src/winapi.rs#L63 |
|
|
|
(C) - MIT License 2023 - Charles Machalow |
|
''' |
|
import os |
|
from ctypes import windll, byref, create_unicode_buffer, pointer, WINFUNCTYPE |
|
from ctypes.wintypes import DWORD, WCHAR, UINT |
|
import browser_cookie3 # pip install browser-cookie3 |
|
import backoff # pip install backoff |
|
|
|
ERROR_SUCCESS = 0 |
|
ERROR_MORE_DATA = 234 |
|
RmForceShutdown = 1 |
|
|
|
cookies_path = os.path.expandvars(r"%LOCALAPPDATA%\Google\Chrome\User Data\Default\Network\Cookies") |
|
|
|
rstrtmgr = windll.LoadLibrary("Rstrtmgr") |
|
|
|
@WINFUNCTYPE(None, UINT) |
|
def callback(percent_complete: UINT) -> None: |
|
print(f"Unlocking file status: {percent_complete}% done") |
|
|
|
def unlock_cookies(): |
|
session_handle = DWORD(0) |
|
session_flags = DWORD(0) |
|
session_key = (WCHAR * 256)() |
|
|
|
result = DWORD(rstrtmgr.RmStartSession(byref(session_handle), session_flags, session_key)).value |
|
|
|
if result != ERROR_SUCCESS: |
|
raise RuntimeError(f"RmStartSession returned non-zero result: {result}") |
|
|
|
try: |
|
result = DWORD(rstrtmgr.RmRegisterResources(session_handle, 1, byref(pointer(create_unicode_buffer(cookies_path))), 0, None, 0, None)).value |
|
|
|
if result != ERROR_SUCCESS: |
|
raise RuntimeError(f"RmRegisterResources returned non-zero result: {result}") |
|
|
|
proc_info_needed = DWORD(0) |
|
proc_info = DWORD(0) |
|
reboot_reasons = DWORD(0) |
|
|
|
result = DWORD(rstrtmgr.RmGetList(session_handle, byref(proc_info_needed), byref(proc_info), None, byref(reboot_reasons))).value |
|
|
|
if result not in (ERROR_SUCCESS, ERROR_MORE_DATA): |
|
raise RuntimeError(f"RmGetList returned non-successful result: {result}") |
|
|
|
if proc_info_needed.value: |
|
result = DWORD(rstrtmgr.RmShutdown(session_handle, RmForceShutdown, callback)).value |
|
|
|
if result != ERROR_SUCCESS: |
|
raise RuntimeError(f"RmShutdown returned non-successful result: {result}") |
|
else: |
|
print("File is not locked") |
|
finally: |
|
result = DWORD(rstrtmgr.RmEndSession(session_handle)).value |
|
|
|
if result != ERROR_SUCCESS: |
|
raise RuntimeError(f"RmEndSession returned non-successful result: {result}") |
|
|
|
|
|
# Use backoff here since there is a race condition between unlocking the file and reading it. |
|
# Technically we're killing a process within chrome that holds the lock. Chrome can/will restart it, |
|
# .. so we have to fetch cookies before it re-locks the file. Generally on my system we get them |
|
# .... though one time we didn't. I think it has to do with opening a new tab.. idk. Maybe not necessary? |
|
@backoff.on_exception(backoff.constant, PermissionError, max_tries=5) |
|
def fetch_cookies(): |
|
unlock_cookies() |
|
return browser_cookie3.chrome(cookies_path) |
|
|
|
cookies = fetch_cookies() |
|
print(len(cookies)) |