{"record":{"id":"4df36f70ca6d9cbd","repo":"moonD4rk/HackBrowserData","slug":"readfile-w","errorCode":null,"errorMessage":"ReadFile: %w","messagePattern":"ReadFile: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"filemanager/copy_windows.go","lineNumber":136,"sourceCode":"\t}\n\n\tsize := int(fileSize)\n\n\t// Try FileMapping first — reads from kernel file cache, includes WAL data\n\tif data, err := winapi.MapFile(handle, size); err == nil {\n\t\treturn data, nil\n\t}\n\n\t// FileMapping failed, fall back to ReadFile.\n\t// Seek to beginning first — the handle's file pointer may be at an\n\t// arbitrary position.\n\tif _, err := windows.Seek(handle, 0, 0); err != nil {\n\t\treturn nil, fmt.Errorf(\"seek to start: %w\", err)\n\t}\n\tdata := make([]byte, size)\n\tvar bytesRead uint32\n\tif err := windows.ReadFile(handle, data, &bytesRead, nil); err != nil {\n\t\treturn nil, fmt.Errorf(\"ReadFile: %w\", err)\n\t}\n\treturn data[:bytesRead], nil\n}\n\n// extractStableSuffix extracts a path suffix that is stable across short/long\n// path name variations. It finds \"AppData\" in the path and returns everything\n// after \"AppData\\Local\\\" or \"AppData\\Roaming\\\" in lowercase.\n//\n// Example:\n//\n//\tC:\\Users\\RUNNER~1\\AppData\\Local\\Google\\Chrome\\...\\Cookies\n//\t→ google\\chrome\\...\\cookies\n//\n// For paths without \"AppData\" (e.g., test temp dirs), it falls back to\n// the last 3 path components to provide reasonable matching specificity.\nfunc extractStableSuffix(path string) string {\n\tlower := strings.ToLower(path)\n\t// Try to find AppData\\Local\\ or AppData\\Roaming\\","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/moonD4rk/HackBrowserData/blob/0503d04d7a8d0379d060268a74f1b149e5a0aad5/filemanager/copy_windows.go#L118-L154","documentation":"readFileContent wraps a failure of windows.ReadFile with \"ReadFile: %w\". This is the last-resort read path in copyLocked: FileMapping already failed, so the tool falls back to reading the whole file (size bytes) from the duplicated Chrome handle via the Win32 ReadFile API. If ReadFile fails, the locked-file bypass cannot recover the database content and the extraction of that file fails.","triggerScenarios":"Windows-only. Session.Acquire on a locked file where findFileHandle successfully duplicated Chrome's handle, winapi.MapFile failed (e.g. mapping size constraints, access rights), and the ReadFile call on the duplicated handle errors — handle lacks read access, buffer/size issues, I/O error on the underlying file, or the handle became invalid after duplication.","commonSituations":"Duplicated handle was opened GENERIC_WRITE-only or with no FILE_READ_DATA by the browser; antivirus blocking reads of the Cookies database; very large file where allocation of the size-byte buffer fails indirectly; Chrome exiting mid-copy invalidating the handle's backing file state.","solutions":["Retry the extraction — transient handle races with a running browser often resolve on a second attempt.","Close the browser (or wait for it to flush/checkpoint) so the plain copyFile path succeeds without needing the locked-file fallback.","Run under the same user account that launched the browser so DUPLICATE_SAME_ACCESS yields a readable handle.","Check AV/EDR exclusion lists — security software frequently denies ReadFile on browser credential stores opened through unusual handle paths."],"exampleFix":"// before\ndata := make([]byte, size)\nvar bytesRead uint32\nif err := windows.ReadFile(handle, data, &bytesRead, nil); err != nil {\n    return nil, fmt.Errorf(\"ReadFile: %w\", err)\n}\n// after\ndata := make([]byte, size)\nvar bytesRead uint32\nif err := windows.ReadFile(handle, data, &bytesRead, nil); err != nil {\n    return nil, fmt.Errorf(\"ReadFile %d bytes: %w\", size, err)\n} // add error-context; caller surfaces it alongside the original copy error","handlingStrategy":"retry","validationCode":"// check the target is a real, non-empty file before attempting locked copy\nfi, err := os.Stat(src)\nif err != nil || fi.IsDir() || fi.Size() == 0 {\n    return fmt.Errorf(\"cannot locked-copy %s: %w\", src, err)\n}","typeGuard":null,"tryCatchPattern":"// Go: treat ReadFile failures in the fallback as transient\nif err := s.Acquire(src, dst, false); err != nil {\n    if strings.Contains(err.Error(), \"ReadFile:\") {\n        if retryErr := s.Acquire(src, dst, false); retryErr == nil {\n            return nil\n        }\n    }\n    return err\n}","preventionTips":["Add AV/EDR exclusions for the tool when doing authorized research","Close the browser when possible so the normal copy path is used","Run under the browser owner's account"],"tags":["windows","file-io","locked-file","handle-duplication","win32-api"],"backgroundTag":"file-read-failed","analyzedSha":"0503d04d7a8d0379d060268a74f1b149e5a0aad5","analyzedAt":"2026-09-06T13:38:28.707Z","contentChangedAt":"2026-09-06T13:38:28.707Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}