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);