2022-12-21 20:30:44 +08:00
# include "get_db_handle.h"
# include "common.h"
# include "db_operation.h"
# include "new_sqlite3.h"
# include "pch.h"
# include "wechat_data.h"
2023-02-10 15:52:55 +08:00
# define CONTACT_G_PINSTANCE_OFFSET 0x2e2d628
2022-12-21 20:30:44 +08:00
# define DB_MICRO_MSG_OFFSET 0x68
# define DB_CHAT_MSG_OFFSET 0x1C0
# define DB_MISC_OFFSET 0x3D8
# define DB_EMOTION_OFFSET 0x558
# define DB_MEDIA_OFFSET 0x9B8
# define DB_BIZCHAT_MSG_OFFSET 0x1120
# define DB_FUNCTION_MSG_OFFSET 0x11B0
# define DB_NAME_OFFSET 0x14
2023-02-10 15:52:55 +08:00
# define PUBLIC_MSG_MGR_OFFSET 0x2e6ce20
# define MULTI_DB_MSG_MGR_OFFSET 0x2e6ec84
# define FAVORITE_STORAGE_MGR_OFFSET 0x2e6e630
# define FTS_FAVORITE_MGR_OFFSET 0x2e2e168
2022-12-21 20:30:44 +08:00
using namespace std ;
map < wstring , DatabaseInfo > dbmap ;
std : : vector < DatabaseInfo > dbs ;
int GetDbInfo ( void * data , int argc , char * * argv , char * * name ) {
DatabaseInfo * pdata = ( DatabaseInfo * ) data ;
TableInfo tb = { 0 } ;
if ( argv [ 1 ] ) {
tb . name = new char [ strlen ( argv [ 1 ] ) + 1 ] ;
memcpy ( tb . name , argv [ 1 ] , strlen ( argv [ 1 ] ) + 1 ) ;
} else {
tb . name = ( char * ) " NULL " ;
}
if ( argv [ 2 ] ) {
tb . table_name = new char [ strlen ( argv [ 2 ] ) + 1 ] ;
memcpy ( tb . table_name , argv [ 2 ] , strlen ( argv [ 2 ] ) + 1 ) ;
} else {
tb . table_name = ( char * ) " NULL " ;
}
if ( argv [ 3 ] ) {
tb . rootpage = new char [ strlen ( argv [ 3 ] ) + 1 ] ;
memcpy ( tb . rootpage , argv [ 3 ] , strlen ( argv [ 3 ] ) + 1 ) ;
} else {
tb . rootpage = ( char * ) " NULL " ;
}
if ( argv [ 4 ] ) {
tb . sql = new char [ strlen ( argv [ 4 ] ) + 1 ] ;
memcpy ( tb . sql , argv [ 4 ] , strlen ( argv [ 4 ] ) + 1 ) ;
} else {
tb . sql = ( char * ) " NULL " ;
}
tb . name_len = strlen ( tb . name ) ;
tb . table_name_len = strlen ( tb . table_name ) ;
tb . sql_len = strlen ( tb . sql ) ;
tb . rootpage_len = strlen ( tb . rootpage ) ;
pdata - > tables . push_back ( tb ) ;
pdata - > count = pdata - > tables . size ( ) ;
return 0 ;
}
std : : vector < void * > GetDbHandles ( ) {
dbs . clear ( ) ;
dbmap . clear ( ) ;
DWORD base = GetWeChatWinBase ( ) ;
2023-02-10 15:52:55 +08:00
DWORD p_contact_addr = * ( DWORD * ) ( base + CONTACT_G_PINSTANCE_OFFSET ) ;
2022-12-21 20:30:44 +08:00
DWORD micro_msg_db_addr = * ( DWORD * ) ( p_contact_addr + DB_MICRO_MSG_OFFSET ) ;
DWORD chat_msg_db_addr = * ( DWORD * ) ( p_contact_addr + DB_CHAT_MSG_OFFSET ) ;
DWORD misc_db_addr = * ( DWORD * ) ( p_contact_addr + DB_MISC_OFFSET ) ;
DWORD emotion_db_addr = * ( DWORD * ) ( p_contact_addr + DB_EMOTION_OFFSET ) ;
DWORD media_db_addr = * ( DWORD * ) ( p_contact_addr + DB_MEDIA_OFFSET ) ;
DWORD bizchat_msg_db_addr =
* ( DWORD * ) ( p_contact_addr + DB_BIZCHAT_MSG_OFFSET ) ;
DWORD function_msg_db_addr =
* ( DWORD * ) ( p_contact_addr + DB_FUNCTION_MSG_OFFSET ) ;
// microMsg.db
DatabaseInfo micro_msg_db { 0 } ;
micro_msg_db . db_name = ( wchar_t * ) ( * (
DWORD * ) ( p_contact_addr + DB_MICRO_MSG_OFFSET + DB_NAME_OFFSET ) ) ;
micro_msg_db . db_name_len =
* ( DWORD * ) ( p_contact_addr + DB_MICRO_MSG_OFFSET + DB_NAME_OFFSET + 0x4 ) ;
micro_msg_db . handle = micro_msg_db_addr ;
ExecuteSQL ( micro_msg_db_addr ,
" select * from sqlite_master where type= \" table \" ; " ,
( DWORD ) GetDbInfo , & micro_msg_db ) ;
dbs . push_back ( micro_msg_db ) ;
wstring micro_msg_name = wstring ( ( wchar_t * ) ( * (
DWORD * ) ( p_contact_addr + DB_MICRO_MSG_OFFSET + DB_NAME_OFFSET ) ) ) ;
dbmap [ micro_msg_name ] = micro_msg_db ;
// chatMsg.db
DatabaseInfo chat_msg_db { 0 } ;
chat_msg_db . db_name = ( wchar_t * ) ( * (
DWORD * ) ( p_contact_addr + DB_CHAT_MSG_OFFSET + DB_NAME_OFFSET ) ) ;
chat_msg_db . db_name_len =
* ( DWORD * ) ( p_contact_addr + DB_CHAT_MSG_OFFSET + DB_NAME_OFFSET + 0x4 ) ;
chat_msg_db . handle = chat_msg_db_addr ;
ExecuteSQL ( chat_msg_db_addr ,
" select * from sqlite_master where type= \" table \" ; " ,
( DWORD ) GetDbInfo , & chat_msg_db ) ;
dbs . push_back ( chat_msg_db ) ;
wstring chat_msg_name = wstring ( ( wchar_t * ) ( * (
DWORD * ) ( p_contact_addr + DB_CHAT_MSG_OFFSET + DB_NAME_OFFSET ) ) ) ;
dbmap [ chat_msg_name ] = chat_msg_db ;
// misc.db
DatabaseInfo misc_db { 0 } ;
misc_db . db_name =
( wchar_t * ) ( * ( DWORD * ) ( p_contact_addr + DB_MISC_OFFSET + DB_NAME_OFFSET ) ) ;
misc_db . db_name_len =
* ( DWORD * ) ( p_contact_addr + DB_MISC_OFFSET + DB_NAME_OFFSET + 0x4 ) ;
misc_db . handle = misc_db_addr ;
ExecuteSQL ( misc_db_addr , " select * from sqlite_master where type= \" table \" ; " ,
( DWORD ) GetDbInfo , & misc_db ) ;
dbs . push_back ( misc_db ) ;
wstring misc_name = wstring ( (
wchar_t * ) ( * ( DWORD * ) ( p_contact_addr + DB_MISC_OFFSET + DB_NAME_OFFSET ) ) ) ;
dbmap [ misc_name ] = misc_db ;
// emotion.db
DatabaseInfo emotion_db { 0 } ;
emotion_db . db_name = ( wchar_t * ) ( * (
DWORD * ) ( p_contact_addr + DB_EMOTION_OFFSET + DB_NAME_OFFSET ) ) ;
emotion_db . db_name_len =
* ( DWORD * ) ( p_contact_addr + DB_EMOTION_OFFSET + DB_NAME_OFFSET + 0x4 ) ;
emotion_db . handle = emotion_db_addr ;
ExecuteSQL ( emotion_db_addr ,
" select * from sqlite_master where type= \" table \" ; " ,
( DWORD ) GetDbInfo , & emotion_db ) ;
dbs . push_back ( emotion_db ) ;
wstring emotion_name = wstring ( ( wchar_t * ) ( * (
DWORD * ) ( p_contact_addr + DB_EMOTION_OFFSET + DB_NAME_OFFSET ) ) ) ;
dbmap [ emotion_name ] = emotion_db ;
// media.db
DatabaseInfo media_db { 0 } ;
media_db . db_name = ( wchar_t * ) ( * ( DWORD * ) ( p_contact_addr + DB_MEDIA_OFFSET +
DB_NAME_OFFSET ) ) ;
media_db . db_name_len =
* ( DWORD * ) ( p_contact_addr + DB_MEDIA_OFFSET + DB_NAME_OFFSET + 0x4 ) ;
media_db . handle = media_db_addr ;
ExecuteSQL ( media_db_addr , " select * from sqlite_master where type= \" table \" ; " ,
( DWORD ) GetDbInfo , & media_db ) ;
dbs . push_back ( media_db ) ;
wstring media_name = wstring ( ( wchar_t * ) ( * (
DWORD * ) ( p_contact_addr + DB_MEDIA_OFFSET + DB_NAME_OFFSET ) ) ) ;
dbmap [ media_name ] = media_db ;
// functionMsg.db
DatabaseInfo function_msg_db { 0 } ;
function_msg_db . db_name = ( wchar_t * ) ( * (
DWORD * ) ( p_contact_addr + DB_FUNCTION_MSG_OFFSET + DB_NAME_OFFSET ) ) ;
function_msg_db . db_name_len = * (
DWORD * ) ( p_contact_addr + DB_FUNCTION_MSG_OFFSET + DB_NAME_OFFSET + 0x4 ) ;
function_msg_db . handle = function_msg_db_addr ;
ExecuteSQL ( function_msg_db_addr ,
" select * from sqlite_master where type= \" table \" ; " ,
( DWORD ) GetDbInfo , & function_msg_db ) ;
dbs . push_back ( function_msg_db ) ;
wstring function_msg_name = wstring ( ( wchar_t * ) ( * (
DWORD * ) ( p_contact_addr + DB_FUNCTION_MSG_OFFSET + DB_NAME_OFFSET ) ) ) ;
dbmap [ function_msg_name ] = function_msg_db ;
if ( bizchat_msg_db_addr ) {
// functionMsg.db maybe null
DatabaseInfo bizchat_msg_db { 0 } ;
bizchat_msg_db . db_name = ( wchar_t * ) ( * (
DWORD * ) ( p_contact_addr + DB_FUNCTION_MSG_OFFSET + DB_NAME_OFFSET ) ) ;
bizchat_msg_db . db_name_len =
* ( DWORD * ) ( p_contact_addr + DB_FUNCTION_MSG_OFFSET + DB_NAME_OFFSET +
0x4 ) ;
bizchat_msg_db . handle = bizchat_msg_db_addr ;
ExecuteSQL ( bizchat_msg_db_addr ,
" select * from sqlite_master where type= \" table \" ; " ,
( DWORD ) GetDbInfo , & bizchat_msg_db ) ;
dbs . push_back ( bizchat_msg_db ) ;
wstring bizchat_msg_name = wstring ( ( wchar_t * ) ( * (
DWORD * ) ( p_contact_addr + DB_FUNCTION_MSG_OFFSET + DB_NAME_OFFSET ) ) ) ;
dbmap [ bizchat_msg_name ] = bizchat_msg_db ;
}
DWORD multi_db_mgr_addr = base + MULTI_DB_MSG_MGR_OFFSET ;
DWORD public_msg_mgr_addr = base + PUBLIC_MSG_MGR_OFFSET ;
DWORD favorite_storage_mgr_addr = base + FAVORITE_STORAGE_MGR_OFFSET ;
DWORD fts_favorite_mgr_addr = base + FTS_FAVORITE_MGR_OFFSET ;
// MsgX.db
DWORD wrap_ptr = * ( DWORD * ) ( multi_db_mgr_addr ) ;
DWORD db_num = * ( DWORD * ) ( wrap_ptr + 0x30 ) ;
DWORD current_db_num = * ( DWORD * ) ( wrap_ptr + 0x38 ) ;
DWORD begin_ptr = * ( DWORD * ) ( wrap_ptr + 0x2c ) ;
for ( unsigned int i = 0 ; i < current_db_num ; i + + ) {
DWORD next_addr = begin_ptr + i * 0x4 ;
DWORD db_addr = * ( DWORD * ) next_addr ;
if ( db_addr ) {
DWORD msg0_db_addr = * ( DWORD * ) ( db_addr + 0x60 ) ;
DatabaseInfo msg0_db { 0 } ;
msg0_db . db_name = ( wchar_t * ) ( * ( DWORD * ) ( db_addr ) ) ;
msg0_db . db_name_len = * ( DWORD * ) ( db_addr + 0x4 ) ;
msg0_db . handle = msg0_db_addr ;
msg0_db . extrainfo = * ( DWORD * ) ( * ( DWORD * ) ( db_addr + 0x18 ) + 0x144 ) ;
ExecuteSQL (
msg0_db_addr , " select * from sqlite_master where type= \" table \" ; " ,
( DWORD ) GetDbInfo , & msg0_db ) ;
dbs . push_back ( msg0_db ) ;
wstring msg_db_name = wstring ( ( wchar_t * ) ( * ( DWORD * ) ( db_addr ) ) ) ;
dbmap [ msg_db_name ] = msg0_db ;
}
}
// publicMsg.db
DWORD public_msg_ptr = * ( DWORD * ) ( * ( DWORD * ) ( public_msg_mgr_addr ) + 0x8 ) ;
if ( public_msg_ptr ) {
DWORD public_msg_db_addr = * ( DWORD * ) ( public_msg_ptr + 0x38 ) ;
DatabaseInfo public_msg_db { 0 } ;
public_msg_db . db_name = ( wchar_t * ) ( * ( DWORD * ) ( public_msg_ptr + 0x4C ) ) ;
public_msg_db . db_name_len = * ( DWORD * ) ( public_msg_ptr + 0x50 ) ;
public_msg_db . handle = public_msg_db_addr ;
ExecuteSQL ( public_msg_db_addr ,
" select * from sqlite_master where type= \" table \" ; " ,
( DWORD ) GetDbInfo , & public_msg_db ) ;
dbs . push_back ( public_msg_db ) ;
wstring public_msg_db_name = wstring ( ( wchar_t * ) ( * ( DWORD * ) ( public_msg_ptr + 0x4C ) ) ) ;
dbmap [ public_msg_db_name ] = public_msg_db ;
}
// Favorite.db
DWORD favItems_ptr = * ( DWORD * ) ( * ( DWORD * ) ( favorite_storage_mgr_addr ) + 0x8 ) ;
if ( favItems_ptr ) {
DWORD favorite_db_addr = * ( DWORD * ) ( favItems_ptr + 0x38 ) ;
DatabaseInfo favorite_db { 0 } ;
favorite_db . db_name = ( wchar_t * ) ( * ( DWORD * ) ( favItems_ptr + 0x4C ) ) ;
favorite_db . db_name_len = * ( DWORD * ) ( favItems_ptr + 0x50 ) ;
favorite_db . handle = favorite_db_addr ;
ExecuteSQL ( favorite_db_addr ,
" select * from sqlite_master where type= \" table \" ; " ,
( DWORD ) GetDbInfo , & favorite_db ) ;
dbs . push_back ( favorite_db ) ;
wstring public_msg_db_name = wstring ( ( wchar_t * ) ( * ( DWORD * ) ( favItems_ptr + 0x4C ) ) ) ;
dbmap [ public_msg_db_name ] = favorite_db ;
}
DatabaseInfo db_end = { 0 } ;
dbs . push_back ( db_end ) ;
# ifdef _DEBUG
for ( unsigned int i = 0 ; i < dbs . size ( ) - 1 ; i + + ) {
printf ( " dbname = %ws,handle = 0x%08X,table_count:%d \n " , dbs [ i ] . db_name ,
dbs [ i ] . handle , dbs [ i ] . tables . size ( ) ) ;
for ( unsigned int j = 0 ; j < dbs [ i ] . tables . size ( ) ; j + + ) {
cout < < " name = " < < dbs [ i ] . tables [ j ] . name < < endl ;
cout < < " tbl_name = " < < dbs [ i ] . tables [ j ] . table_name < < endl ;
cout < < " rootpage = " < < dbs [ i ] . tables [ j ] . rootpage < < endl ;
cout < < " sql = " < < dbs [ i ] . tables [ j ] . sql < < endl ;
cout < < endl ;
}
cout < < endl ;
}
# endif
vector < void * > ret_array ;
for ( unsigned int i = 0 ; i < dbs . size ( ) - 1 ; i + + )
ret_array . push_back ( & dbs [ i ] ) ;
return ret_array ;
}
DWORD GetDbHandleByDbName ( wchar_t * dbname ) {
if ( dbmap . size ( ) = = 0 ) {
GetDbHandles ( ) ;
}
if ( dbmap . find ( dbname ) ! = dbmap . end ( ) ) {
return dbmap [ dbname ] . handle ;
}
return 0 ;
}
unsigned int GetLocalIdByMsgId ( ULONG64 msgid , int & dbIndex ) {
char sql [ 260 ] = { 0 } ;
sprintf_s ( sql , " select localId from MSG where MsgSvrID=%llu; " , msgid ) ;
wchar_t dbname [ 20 ] = { 0 } ;
for ( int i = 0 ; ; i + + ) {
swprintf_s ( dbname , L " MSG%d.db " , i ) ;
DWORD handle = GetDbHandleByDbName ( dbname ) ;
# ifdef _DEBUG
cout < < " handle = " < < handle < < endl ;
# endif
if ( handle = = 0 ) return 0 ;
vector < vector < string > > result ;
int ret = Select ( handle , ( const char * ) sql , result ) ;
# ifdef _DEBUG
cout < < " size = " < < result . size ( ) < < endl ;
# endif
if ( result . size ( ) = = 0 ) continue ;
dbIndex = dbmap [ dbname ] . extrainfo ;
return stoi ( result [ 1 ] [ 0 ] ) ;
}
return 0 ;
2023-02-04 12:04:28 +08:00
}
vector < string > GetChatMsgByMsgId ( ULONG64 msgid ) {
char sql [ 260 ] = { 0 } ;
sprintf_s ( sql , " select localId,TalkerId,MsgSvrID,Type,SubType,IsSender,CreateTime,Sequence,StatusEx,FlagEx,Status,MsgServerSeq,MsgSequence,StrTalker,StrContent,BytesExtra from MSG where MsgSvrID=%llu; " , msgid ) ;
wchar_t dbname [ 20 ] = { 0 } ;
for ( int i = 0 ; ; i + + ) {
swprintf_s ( dbname , L " MSG%d.db " , i ) ;
DWORD handle = GetDbHandleByDbName ( dbname ) ;
if ( handle = = 0 ) return { } ;
vector < vector < string > > result ;
int ret = Select ( handle , ( const char * ) sql , result ) ;
# ifdef _DEBUG
cout < < " size = " < < result . size ( ) < < endl ;
# endif
if ( result . size ( ) = = 0 ) continue ;
return result [ 1 ] ;
}
return { } ;
2022-12-21 20:30:44 +08:00
}