diff --git a/spy/Spy.vcxproj b/spy/Spy.vcxproj
index 1b4f3e5..f2caedd 100644
--- a/spy/Spy.vcxproj
+++ b/spy/Spy.vcxproj
@@ -241,6 +241,7 @@ $(SolutionDir)rpc\tool\protoc --nanopb_out=. wcf.proto
+
diff --git a/spy/Spy.vcxproj.filters b/spy/Spy.vcxproj.filters
index 2e558b4..d8614de 100644
--- a/spy/Spy.vcxproj.filters
+++ b/spy/Spy.vcxproj.filters
@@ -90,6 +90,9 @@
头文件
+
+ 头文件
+
diff --git a/spy/exec_sql.cpp b/spy/exec_sql.cpp
index 145c23d..faedd1c 100644
--- a/spy/exec_sql.cpp
+++ b/spy/exec_sql.cpp
@@ -2,45 +2,18 @@
#include "exec_sql.h"
#include "load_calls.h"
+#include "sqlite3.h"
#include "util.h"
-#define SQLITE_OK 0 /* Successful result */
-#define SQLITE_ERROR 1 /* Generic error */
-#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
-#define SQLITE_PERM 3 /* Access permission denied */
-#define SQLITE_ABORT 4 /* Callback routine requested an abort */
-#define SQLITE_BUSY 5 /* The database file is locked */
-#define SQLITE_LOCKED 6 /* A table in the database is locked */
-#define SQLITE_NOMEM 7 /* A malloc() failed */
-#define SQLITE_READONLY 8 /* Attempt to write a readonly database */
-#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/
-#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */
-#define SQLITE_CORRUPT 11 /* The database disk image is malformed */
-#define SQLITE_NOTFOUND 12 /* Unknown opcode in sqlite3_file_control() */
-#define SQLITE_FULL 13 /* Insertion failed because database is full */
-#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
-#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
-#define SQLITE_EMPTY 16 /* Internal use only */
-#define SQLITE_SCHEMA 17 /* The database schema changed */
-#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */
-#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */
-#define SQLITE_MISMATCH 20 /* Data type mismatch */
-#define SQLITE_MISUSE 21 /* Library used incorrectly */
-#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */
-#define SQLITE_AUTH 23 /* Authorization denied */
-#define SQLITE_FORMAT 24 /* Not used */
-#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */
-#define SQLITE_NOTADB 26 /* File opened that is not a database file */
-#define SQLITE_NOTICE 27 /* Notifications from sqlite3_log() */
-#define SQLITE_WARNING 28 /* Warnings from sqlite3_log() */
-#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */
-#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */
-
-#define SQLITE_INTEGER 1
-#define SQLITE_FLOAT 2
-#define SQLITE_TEXT 3
-#define SQLITE_BLOB 4
-#define SQLITE_NULL 5
+#define OFFSET_DB_INSTANCE 0x2FFDDC8
+#define OFFSET_DB_MICROMSG 0x68
+#define OFFSET_DB_CHAT_MSG 0x1C0
+#define OFFSET_DB_MISC 0x3D8
+#define OFFSET_DB_EMOTION 0x558
+#define OFFSET_DB_MEDIA 0x9B8
+#define OFFSET_DB_BIZCHAT_MSG 0x1120
+#define OFFSET_DB_FUNCTION_MSG 0x11B0
+#define OFFSET_DB_NAME 0x14
extern WxCalls_t g_WxCalls;
extern DWORD g_WeChatWinDllAddr;
@@ -67,25 +40,27 @@ typedef const void *(__cdecl *Sqlite3_column_blob)(DWORD *, int);
typedef int(__cdecl *Sqlite3_column_bytes)(DWORD *, int);
typedef int(__cdecl *Sqlite3_finalize)(DWORD *);
+static void GetDbHandle(DWORD base, DWORD offset)
+{
+ wchar_t *wsp;
+ wsp = (wchar_t *)(*(DWORD *)(base + offset + OFFSET_DB_NAME));
+ string dbname = Wstring2String(wstring(wsp));
+ dbMap[dbname] = *(DWORD *)(base + offset);
+}
+
dbMap_t GetDbHandles()
{
- if (!dbMap.empty())
- return dbMap;
+ dbMap.clear();
- g_WeChatWinDllAddr = (DWORD)GetModuleHandle(L"WeChatWin.dll");
- DWORD sqlHandleBaseAddr = *(DWORD *)(g_WeChatWinDllAddr + g_WxCalls.sql.base);
- DWORD sqlHandleBeginAddr = *(DWORD *)(sqlHandleBaseAddr + g_WxCalls.sql.start);
- DWORD sqlHandleEndAddr = *(DWORD *)(sqlHandleBaseAddr + g_WxCalls.sql.end);
- while (sqlHandleBeginAddr < sqlHandleEndAddr) {
- DWORD dwHandle = *(DWORD *)sqlHandleBeginAddr;
- string dbName = Wstring2String(wstring((wchar_t *)(*(DWORD *)(dwHandle + g_WxCalls.sql.name))));
- DWORD handle = *(DWORD *)(dwHandle + g_WxCalls.sql.slot);
- if (handle) {
- dbMap[dbName] = handle;
- }
+ DWORD dbInstanceAddr = *(DWORD *)(g_WeChatWinDllAddr + OFFSET_DB_INSTANCE);
+
+ GetDbHandle(dbInstanceAddr, OFFSET_DB_MICROMSG); // MicroMsg.db
+ GetDbHandle(dbInstanceAddr, OFFSET_DB_CHAT_MSG); // ChatMsg.db
+ GetDbHandle(dbInstanceAddr, OFFSET_DB_MISC); // Misc.db
+ GetDbHandle(dbInstanceAddr, OFFSET_DB_EMOTION); // Emotion.db
+ GetDbHandle(dbInstanceAddr, OFFSET_DB_MEDIA); // Media.db
+ GetDbHandle(dbInstanceAddr, OFFSET_DB_FUNCTION_MSG); // Function.db
- sqlHandleBeginAddr += 0x04;
- }
return dbMap;
}
diff --git a/spy/rpc_server.cpp b/spy/rpc_server.cpp
index 0c4d635..469864c 100644
--- a/spy/rpc_server.cpp
+++ b/spy/rpc_server.cpp
@@ -564,12 +564,12 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len
ret = func_get_contacts(out, out_len);
break;
}
-#if 0
case Functions_FUNC_GET_DB_NAMES: {
LOG_DEBUG("[Functions_FUNC_GET_DB_NAMES]");
ret = func_get_db_names(out, out_len);
break;
}
+#if 0
case Functions_FUNC_GET_DB_TABLES: {
LOG_DEBUG("[Functions_FUNC_GET_DB_TABLES]");
ret = func_get_db_tables(req.msg.str, out, out_len);
diff --git a/spy/sqlite3.h b/spy/sqlite3.h
new file mode 100644
index 0000000..ac3d2e8
--- /dev/null
+++ b/spy/sqlite3.h
@@ -0,0 +1,192 @@
+#pragma once
+
+#include "Windows.h"
+
+#define SQLITE_OK 0 /* Successful result */
+
+/* beginning-of-error-codes */
+#define SQLITE_ERROR 1 /* Generic error */
+#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
+#define SQLITE_PERM 3 /* Access permission denied */
+#define SQLITE_ABORT 4 /* Callback routine requested an abort */
+#define SQLITE_BUSY 5 /* The database file is locked */
+#define SQLITE_LOCKED 6 /* A table in the database is locked */
+#define SQLITE_NOMEM 7 /* A malloc() failed */
+#define SQLITE_READONLY 8 /* Attempt to write a readonly database */
+#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/
+#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */
+#define SQLITE_CORRUPT 11 /* The database disk image is malformed */
+#define SQLITE_NOTFOUND 12 /* Unknown opcode in sqlite3_file_control() */
+#define SQLITE_FULL 13 /* Insertion failed because database is full */
+#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
+#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
+#define SQLITE_EMPTY 16 /* Internal use only */
+#define SQLITE_SCHEMA 17 /* The database schema changed */
+#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */
+#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */
+#define SQLITE_MISMATCH 20 /* Data type mismatch */
+#define SQLITE_MISUSE 21 /* Library used incorrectly */
+#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */
+#define SQLITE_AUTH 23 /* Authorization denied */
+#define SQLITE_FORMAT 24 /* Not used */
+#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */
+#define SQLITE_NOTADB 26 /* File opened that is not a database file */
+#define SQLITE_NOTICE 27 /* Notifications from sqlite3_log() */
+#define SQLITE_WARNING 28 /* Warnings from sqlite3_log() */
+#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */
+#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */
+/* end-of-error-codes */
+
+/*
+** CAPI3REF: Extended Result Codes
+** KEYWORDS: {extended result code definitions}
+**
+** In its default configuration, SQLite API routines return one of 30 integer
+** [result codes]. However, experience has shown that many of
+** these result codes are too coarse-grained. They do not provide as
+** much information about problems as programmers might like. In an effort to
+** address this, newer versions of SQLite (version 3.3.8 [dateof:3.3.8]
+** and later) include
+** support for additional result codes that provide more detailed information
+** about errors. These [extended result codes] are enabled or disabled
+** on a per database connection basis using the
+** [sqlite3_extended_result_codes()] API. Or, the extended code for
+** the most recent error can be obtained using
+** [sqlite3_extended_errcode()].
+*/
+#define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1 << 8))
+#define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2 << 8))
+#define SQLITE_ERROR_SNAPSHOT (SQLITE_ERROR | (3 << 8))
+#define SQLITE_IOERR_READ (SQLITE_IOERR | (1 << 8))
+#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2 << 8))
+#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3 << 8))
+#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4 << 8))
+#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5 << 8))
+#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6 << 8))
+#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7 << 8))
+#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8 << 8))
+#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9 << 8))
+#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10 << 8))
+#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11 << 8))
+#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12 << 8))
+#define SQLITE_IOERR_ACCESS (SQLITE_IOERR | (13 << 8))
+#define SQLITE_IOERR_CHECKRESERVEDLOCK (SQLITE_IOERR | (14 << 8))
+#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15 << 8))
+#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16 << 8))
+#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17 << 8))
+#define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18 << 8))
+#define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19 << 8))
+#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20 << 8))
+#define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21 << 8))
+#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22 << 8))
+#define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23 << 8))
+#define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24 << 8))
+#define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25 << 8))
+#define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26 << 8))
+#define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27 << 8))
+#define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28 << 8))
+#define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29 << 8))
+#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30 << 8))
+#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31 << 8))
+#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32 << 8))
+#define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33 << 8))
+#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1 << 8))
+#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2 << 8))
+#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1 << 8))
+#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2 << 8))
+#define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3 << 8))
+#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1 << 8))
+#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2 << 8))
+#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3 << 8))
+#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4 << 8))
+#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5 << 8)) /* Not Used */
+#define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6 << 8))
+#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1 << 8))
+#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2 << 8))
+#define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3 << 8))
+#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1 << 8))
+#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2 << 8))
+#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3 << 8))
+#define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4 << 8))
+#define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5 << 8))
+#define SQLITE_READONLY_DIRECTORY (SQLITE_READONLY | (6 << 8))
+#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2 << 8))
+#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1 << 8))
+#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2 << 8))
+#define SQLITE_CONSTRAINT_FOREIGNKEY (SQLITE_CONSTRAINT | (3 << 8))
+#define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4 << 8))
+#define SQLITE_CONSTRAINT_NOTNULL (SQLITE_CONSTRAINT | (5 << 8))
+#define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6 << 8))
+#define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7 << 8))
+#define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8 << 8))
+#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9 << 8))
+#define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT | (10 << 8))
+#define SQLITE_CONSTRAINT_PINNED (SQLITE_CONSTRAINT | (11 << 8))
+#define SQLITE_CONSTRAINT_DATATYPE (SQLITE_CONSTRAINT | (12 << 8))
+#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1 << 8))
+#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2 << 8))
+#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1 << 8))
+#define SQLITE_AUTH_USER (SQLITE_AUTH | (1 << 8))
+#define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1 << 8))
+#define SQLITE_OK_SYMLINK (SQLITE_OK | (2 << 8)) /* internal use only */
+
+#define SQLITE_INTEGER 1
+#define SQLITE_FLOAT 2
+#define SQLITE_BLOB 4
+#define SQLITE_NULL 5
+#define SQLITE_TEXT 3
+
+#define SQLITE3_EXEC_OFFSET 0x1E24F70
+#define SQLITE3_BACKUP_INIT_OFFSET 0x1DEA900
+#define SQLITE3_PREPARE_OFFSET 0x1E2B8C0
+#define SQLITE3_OPEN_OFFSET 0x1E598B0
+#define SQLITE3_BACKUP_STEP_OFFSET 0x1DEAD00
+#define SQLITE3_BACKUP_REMAINING_OFFSET 0x1DEB440
+#define SQLITE3_BACKUP_PAGECOUNT_OFFSET 0x1DEB450
+#define SQLITE3_BACKUP_FINISH_OFFSET 0x1DEB340
+#define SQLITE3_SLEEP_OFFSET 0x1E5A0F0
+#define SQLITE3_ERRCODE_OFFSET 0x1E58550
+#define SQLITE3_CLOSE_OFFSET 0x1E56CD0
+#define SQLITE3_STEP_OFFSET 0x1DF3770
+#define SQLITE3_COLUMN_COUNT_OFFSET 0x1DF3C80
+#define SQLITE3_COLUMN_NAME_OFFSET 0x1DF4570
+#define SQLITE3_COLUMN_TYPE_OFFSET 0x1DF4410
+#define SQLITE3_COLUMN_BLOB_OFFSET 0x1DF3CC0
+#define SQLITE3_COLUMN_BYTES_OFFSET 0x1DF3DA0
+#define SQLITE3_FINALIZE_OFFSET 0x1DF2740
+
+typedef int (*Sqlite3_callback)(void *, int, char **, char **);
+
+typedef int(__cdecl *Sqlite3_exec)(DWORD, /* An open database */
+ const char *sql, /* SQL to be evaluated */
+ Sqlite3_callback, /* Callback function */
+ void *, /* 1st argument to callback */
+ char **errmsg /* Error msg written here */
+);
+typedef DWORD(__cdecl *Sqlite3_backup_init)(DWORD *pDest, /* Destination database handle */
+ const char *zDestName, /* Destination database name */
+ DWORD *pSource, /* Source database handle */
+ const char *zSourceName /* Source database name */
+);
+typedef int(__cdecl *Sqlite3_prepare)(DWORD db, /* Database handle */
+ const char *zSql, /* SQL statement, UTF-8 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ DWORD **ppStmt, /* OUT: Statement handle */
+ const char **pzTail /* OUT: Pointer to unused portion of zSql */
+);
+typedef int(__cdecl *Sqlite3_open)(const char *filename, DWORD **ppDb);
+typedef int(__cdecl *Sqlite3_backup_step)(DWORD *p, int nPage);
+typedef int(__cdecl *Sqlite3_backup_remaining)(DWORD *p);
+typedef int(__cdecl *Sqlite3_backup_pagecount)(DWORD *p);
+typedef int(__cdecl *Sqlite3_backup_finish)(DWORD *p);
+typedef int(__cdecl *Sqlite3_sleep)(int);
+typedef int(__cdecl *Sqlite3_errcode)(DWORD *db);
+typedef int(__cdecl *Sqlite3_close)(DWORD *);
+
+typedef int(__cdecl *Sqlite3_step)(DWORD *);
+typedef int(__cdecl *Sqlite3_column_count)(DWORD *pStmt);
+typedef const char *(__cdecl *Sqlite3_column_name)(DWORD *, int N);
+typedef int(__cdecl *Sqlite3_column_type)(DWORD *, int iCol);
+typedef const void *(__cdecl *Sqlite3_column_blob)(DWORD *, int iCol);
+typedef int(__cdecl *Sqlite3_column_bytes)(DWORD *, int iCol);
+typedef int(__cdecl *Sqlite3_finalize)(DWORD *pStmt);