检索并搜索您的 Chrome 历史记录





5.00/5 (7投票s)
如何通过访问“history”Sqlite 数据库来检索和搜索您的 Chrome 历史记录
如何查看您的 Chrome 历史记录
首先,让我们看看查看 Chrome 历史记录的“正常”方法。只需转到历史记录菜单选项,如下所示
然后您将看到所有最近访问的网站,从后到前。
Chrome 取证
Google Chrome 将其浏览历史记录存储为名为“history”的 SQLite 数据库,该数据库位于不同的位置,具体取决于操作系统。在 Windows 中,该位置位于 %APPDATA% 文件夹中。
还有存档历史记录,早于 History 文件中的信息。请注意,存档历史记录仅包含访问记录。
SQL 查询
为了获取最近(或所有)历史记录,或者对历史记录数据库执行搜索,我准备了几个 SQL 查询
获取所有历史记录
SELECT last_visit_time, datetime(last_visit_time / 1000000 - 11644473600, _
'unixepoch', 'localtime'),url,title FROM urls ORDER BY last_visit_time DESC
所以代码将是
#define CHROME_HISTORY_SQL_QUERY "SELECT last_visit_time,
datetime(last_visit_time / 1000000 - 11644473600, 'unixepoch', 'localtime'),
url,title FROM urls ORDER BY last_visit_time DESC"
Fetch history based on a search term
在这种情况下,我们希望允许一个搜索词,为了方便起见,我们假设如果搜索词是“child
”,我们将搜索“*child*
”,在 SQL 语法中是“%child%
”。所以代码将是 2 个预处理器定义
#define CHROME_HISTORY_SQL_QUERY2_LEFT "SELECT last_visit_time,
datetime(last_visit_time / 1000000 - 11644473600, 'unixepoch', 'localtime'),
url,title FROM urls WHERE title like '"
#define CHROME_HISTORY_SQL_QUERY2_RIGHT "' ORDER BY last_visit_time DESC"
Fetch history based on a complex query
当我们想添加一个查询词,例如“Where last_visit_time > <date>
”时,我们使用以下代码
#define CHROME_HISTORY_SQL_QUERY_LEFT "SELECT last_visit_time,
datetime(last_visit_time / 1000000 - 11644473600, 'unixepoch', 'localtime'),
url,title FROM urls "
#define CHROME_HISTORY_SQL_QUERY_RIGHT " ORDER BY last_visit_time DESC"
数据结构
首先,我们为浏览历史记录定义了一个通用数据结构,它应该支持所有浏览器,并且将在本文中在 Google Chrome 的范围内进行演示
typedef struct _SGBrowserHistory
{
int Browser; // 1 = chrome, 2 = firefox, 3 = ie
WCHAR SiteURL[URL_MAXSIZE];
WCHAR SiteName[1024];
WCHAR LastVisitDate[256];
} SGBrowserHistory;
利用 CSimpleArray 类也很有用。我们定义一个新类型 SGBrowserHistoryArray
,它将用于存储一个动态数组,其中包含 SGBrowserHistory
数据结构的元素。所以我们有
SGBrowserHistory
,和SGBrowserHistoryArray
typedef CSimpleArray<SGBrowserHistory> SGBrowserHistoryArray;
我们的程序
我创建了一个小程序,该程序使用我们为我们的几个产品开发的类库。
现在我们可以深入研究代码
使用我们类的最简单方法是只获取所有已存储的历史记录。这可能需要时间,我们不希望在 Chrome 使用时阻止或被阻止(并且当它被使用时,它的数据库被访问和更改),因此首先创建我们自己的备份数据库并将其命名为 temp.db。(定义为 TEMP_DB_NAME
)。
bool SGBrowsingHistory::GetChromeHistory
(SGBrowserHistoryArray *history, CString FileName,CString SearchString)
{
bool result = false;
WCHAR szPath[MAX_PATH];
//const char *lpTail;
utils::SG_GetSpecialFolderPath(szPath, CSIDL_LOCAL_APPDATA);
StrCat(szPath, CHROMEHISTORY);
WCHAR filename[MAX_PATH + 1] = { TEMP_DB_NAME };
if (CopyFile(szPath, filename, FALSE))
{
if (GetFileAttributes(filename) != 0xFFFFFFFF)
{
}
else
{
wprintf(L"Error: Cannot find login data for Google Chrome browser\r\n");
}
bool result = db->GetChromeHistoryRecords(filename, history, SearchString);
}
return result;
}
将结果存储在我们自己的数据库中
我们的程序不仅与 Chrome 的数据库交互,还创建我们自己的数据库,我们可以在其中根据需要存储数据。
SG_Database 类
我已经创建了一个用于处理数据库的类,大多数情况下我将使用 sqlite,我认为这是最好的。我还使用了 Tyushkov Nikolay 的 CppSQLite3U
,它是一个包装类,更易于支持 UNICODE。
创建 ChromeHistory 表
为了创建 ChromeHistory
表,我们使用一个预处理器定义,如下所示
#define createTableChromeHistory L"CREATE TABLE IF NOT EXISTS ChromeHistory(\
id INTEGER PRIMARY KEY AUTOINCREMENT,\
created TIMESTAMP not null default CURRENT_TIMESTAMP,\
date_last_visited TEXT not null default '',\
site_name TEXT not null default '',\
size_url TEXT not null default '',\
);"
记录错误
我在之前的文章中写了很多关于这个主题的内容。在这种情况下,这里是一个用于记录 SQL 错误的非常简单的函数。
#define STR_ERROR_RUNNING_QEURY L"Error running query: %s. Error message: %s. Function = %s\n"
void CSGDatabase::LogSqlError(CppSQLite3Exception &e, CString Function, CString sql)
{
wprintf(STR_ERROR_RUNNING_QEURY, sql.GetBuffer(), e.errorMessage(), Function.GetBuffer());
}
然后我们创建一个宏
#define LOGSQLERROR(e,sql) LogSqlError(e, (CString)__FUNCTION__, sql);
用于已经调用它,以及 LogSqlError
已调用的当前函数。
LOGSQLERROR(e,sql);
有关 Chrome 数据库的其他信息
日期和时间的存储方式
History 文件使用不同的时间戳。
visits.visit_time
Chrome 将每次访问给定网站的日期存储在 visits.visit_time
中。 visits.visit_time
是自 1601 年 1 月 1 日 UTC 以来(以)微秒为单位的。
这里有一个将 Chrome 时间转换为系统时间的函数。
// convert chrome time (as long long integer) to system time
SYSTEMTIME intChromeTimeToSysTime(long long int UnixTime)
{
time_t dosTime(UnixTime);
// Note that LONGLONG is a 64-bit value
SYSTEMTIME systemTime;
LARGE_INTEGER utcFT = { 0 };
utcFT.QuadPart = ((unsigned __int64)dosTime) * 10000000;
FileTimeToSystemTime((FILETIME*)&utcFT, &systemTime);
return systemTime;
}
请注意,此时间戳与 Windows FILETIME 不同,后者是自 1601 年 1 月 1 日 UTC 以来(以)100 纳秒为单位的。
时间戳
History 文件使用不同的时间戳。
visits.visit_time
visits.visit_time
是自 1601 年 1 月 1 日 UTC 以来(以)微秒为单位的。
以下代码演示了将 Chrome 访问时间转换为人类可读格式的正确方法
date_string = datetime.datetime( 1601, 1, 1 )
+ datetime.timedelta( microseconds=timestamp )
请注意,此时间戳与 Windows FILETIME 不同,后者是自 1601 年 1 月 1 日 UTC 以来(以)100 纳秒为单位的。
downloads.start_time
downloads.start_time
是自 1970 年 1 月 1 日 UTC 以来(以)秒为单位的。
延伸阅读
历史
- 2019 年 6 月 14 日:初始版本