diff --git a/README.md b/README.md index 3332bef..5ddcf6d 100644 --- a/README.md +++ b/README.md @@ -149,9 +149,9 @@ GET /api/v1/chatlog?time=2023-01-01&talker=wxid_xxx 参数说明: - `time`: 时间范围,格式为 `YYYY-MM-DD` 或 `YYYY-MM-DD~YYYY-MM-DD` - `talker`: 聊天对象标识(支持 wxid、群聊 ID、备注名、昵称等) -- `limit`: 返回记录数量(默认 100) -- `offset`: 分页偏移量(默认 0) -- `format`: 输出格式,支持 `json`、`csv` 或纯文本(默认 纯文本) +- `limit`: 返回记录数量 +- `offset`: 分页偏移量 +- `format`: 输出格式,支持 `json`、`csv` 或纯文本 ### 其他 API 接口 diff --git a/cmd/chatlog/cmd_server.go b/cmd/chatlog/cmd_server.go new file mode 100644 index 0000000..c6c01d1 --- /dev/null +++ b/cmd/chatlog/cmd_server.go @@ -0,0 +1,43 @@ +package chatlog + +import ( + "runtime" + + "github.com/sjzar/chatlog/internal/chatlog" + + "github.com/rs/zerolog/log" + "github.com/spf13/cobra" +) + +func init() { + rootCmd.AddCommand(serverCmd) + serverCmd.Flags().StringVarP(&serverAddr, "addr", "a", "127.0.0.1:5030", "server address") + serverCmd.Flags().StringVarP(&serverDataDir, "data-dir", "d", "", "data dir") + serverCmd.Flags().StringVarP(&serverWorkDir, "work-dir", "w", "", "work dir") + serverCmd.Flags().StringVarP(&serverPlatform, "platform", "p", runtime.GOOS, "platform") + serverCmd.Flags().IntVarP(&serverVer, "version", "v", 3, "version") +} + +var ( + serverAddr string + serverDataDir string + serverWorkDir string + serverPlatform string + serverVer int +) + +var serverCmd = &cobra.Command{ + Use: "server", + Short: "Start HTTP server", + Run: func(cmd *cobra.Command, args []string) { + m, err := chatlog.New("") + if err != nil { + log.Err(err).Msg("failed to create chatlog instance") + return + } + if err := m.CommandHTTPServer(serverAddr, serverDataDir, serverWorkDir, serverPlatform, serverVer); err != nil { + log.Err(err).Msg("failed to start server") + return + } + }, +} diff --git a/internal/chatlog/http/static/index.htm b/internal/chatlog/http/static/index.htm index d0a071e..b8d05a1 100644 --- a/internal/chatlog/http/static/index.htm +++ b/internal/chatlog/http/static/index.htm @@ -1,156 +1,733 @@ - - - - - + + + Chatlog - - -
-
-            ('-. .-.    ('-.      .-') _                                         
-            ( OO )  /   ( OO ).-. (  OO) )                                        
-   .-----.  ,--. ,--.   / . --. / /     '._   ,--.       .-'),-----.   ,----.     
-  '  .--./  |  | |  |   | \-.  \  |'--...__)  |  |.-')  ( OO'  .-.  ' '  .-./-')  
-  |  |('-.  |   .|  | .-'-'  |  | '--.  .--'  |  | OO ) /   |  | |  | |  |_( O- ) 
- /_) |OO  ) |       |  \| |_.'  |    |  |     |  |`-' | \_) |  |\|  | |  | .--, \ 
- ||  |`-'|  |  .-.  |   |  .-.  |    |  |    (|  '---.'   \ |  | |  |(|  | '. (_/ 
-(_'  '--'\  |  | |  |   |  | |  |    |  |     |      |     `'  '-'  ' |  '--'  |  
-   `-----'  `--' `--'   `--' `--'    `--'     `------'       `-----'   `------'    
-        
-
-            _____  _             _    _               
-            /  __ \| |           | |  | |              
-            | /  \/| |__    __ _ | |_ | |  ___    __ _ 
-            | |    | '_ \  / _` || __|| | / _ \  / _` |
-            | \__/\| | | || (_| || |_ | || (_) || (_| |
-             \____/|_| |_| \__,_| \__||_| \___/  \__, |
-                                                  __/ |
-                                                 |___/ 
-        
-
-                                                          
-            ,-----. ,--.                 ,--.   ,--.                 
-            '  .--./ |  ,---.   ,--,--. ,-'  '-. |  |  ,---.   ,---.  
-            |  |     |  .-.  | ' ,-.  | '-.  .-' |  | | .-. | | .-. | 
-            '  '--'\ |  | |  | \ '-'  |   |  |   |  | ' '-' ' ' '-' ' 
-             `-----' `--' `--'  `--`--'   `--'   `--'  `---'  .`-  /  
-                                                              `---'   
-        
-
-            ____   _               _     _                 
-            / ___| | |__     __ _  | |_  | |   ___     __ _ 
-           | |     | '_ \   / _` | | __| | |  / _ \   / _` |
-           | |___  | | | | | (_| | | |_  | | | (_) | | (_| |
-            \____| |_| |_|  \__,_|  \__| |_|  \___/   \__, |
-                                                      |___/ 
-        
-
-            _____                    _____                    _____                _____                    _____           _______                   _____          
-            /\    \                  /\    \                  /\    \              /\    \                  /\    \         /::\    \                 /\    \         
-           /::\    \                /::\____\                /::\    \            /::\    \                /::\____\       /::::\    \               /::\    \        
-          /::::\    \              /:::/    /               /::::\    \           \:::\    \              /:::/    /      /::::::\    \             /::::\    \       
-         /::::::\    \            /:::/    /               /::::::\    \           \:::\    \            /:::/    /      /::::::::\    \           /::::::\    \      
-        /:::/\:::\    \          /:::/    /               /:::/\:::\    \           \:::\    \          /:::/    /      /:::/~~\:::\    \         /:::/\:::\    \     
-       /:::/  \:::\    \        /:::/____/               /:::/__\:::\    \           \:::\    \        /:::/    /      /:::/    \:::\    \       /:::/  \:::\    \    
-      /:::/    \:::\    \      /::::\    \              /::::\   \:::\    \          /::::\    \      /:::/    /      /:::/    / \:::\    \     /:::/    \:::\    \   
-     /:::/    / \:::\    \    /::::::\    \   _____    /::::::\   \:::\    \        /::::::\    \    /:::/    /      /:::/____/   \:::\____\   /:::/    / \:::\    \  
-    /:::/    /   \:::\    \  /:::/\:::\    \ /\    \  /:::/\:::\   \:::\    \      /:::/\:::\    \  /:::/    /      |:::|    |     |:::|    | /:::/    /   \:::\ ___\ 
-   /:::/____/     \:::\____\/:::/  \:::\    /::\____\/:::/  \:::\   \:::\____\    /:::/  \:::\____\/:::/____/       |:::|____|     |:::|    |/:::/____/  ___\:::|    |
-   \:::\    \      \::/    /\::/    \:::\  /:::/    /\::/    \:::\  /:::/    /   /:::/    \::/    /\:::\    \        \:::\    \   /:::/    / \:::\    \ /\  /:::|____|
-    \:::\    \      \/____/  \/____/ \:::\/:::/    /  \/____/ \:::\/:::/    /   /:::/    / \/____/  \:::\    \        \:::\    \ /:::/    /   \:::\    /::\ \::/    / 
-     \:::\    \                       \::::::/    /            \::::::/    /   /:::/    /            \:::\    \        \:::\    /:::/    /     \:::\   \:::\ \/____/  
-      \:::\    \                       \::::/    /              \::::/    /   /:::/    /              \:::\    \        \:::\__/:::/    /       \:::\   \:::\____\    
-       \:::\    \                      /:::/    /               /:::/    /    \::/    /                \:::\    \        \::::::::/    /         \:::\  /:::/    /    
-        \:::\    \                    /:::/    /               /:::/    /      \/____/                  \:::\    \        \::::::/    /           \:::\/:::/    /     
-         \:::\    \                  /:::/    /               /:::/    /                                 \:::\    \        \::::/    /             \::::::/    /      
-          \:::\____\                /:::/    /               /:::/    /                                   \:::\____\        \::/____/               \::::/    /       
-           \::/    /                \::/    /                \::/    /                                     \::/    /         ~~                      \::/____/        
-            \/____/                  \/____/                  \/____/                                       \/____/                                                   
-                                                                                                                                                                      
-        
-
-            ___  _   _    __    ____  __    _____   ___ 
-            / __)( )_( )  /__\  (_  _)(  )  (  _  ) / __)
-           ( (__  ) _ (  /(__)\   )(   )(__  )(_)( ( (_-.
-            \___)(_) (_)(__)(__) (__) (____)(_____) \___/
-        
-
-            ________      ___  ___      ________      _________    ___           ________      ________     
-            |\   ____\    |\  \|\  \    |\   __  \    |\___   ___\ |\  \         |\   __  \    |\   ____\    
-            \ \  \___|    \ \  \\\  \   \ \  \|\  \   \|___ \  \_| \ \  \        \ \  \|\  \   \ \  \___|    
-             \ \  \        \ \   __  \   \ \   __  \       \ \  \   \ \  \        \ \  \\\  \   \ \  \  ___  
-              \ \  \____    \ \  \ \  \   \ \  \ \  \       \ \  \   \ \  \____    \ \  \\\  \   \ \  \|\  \ 
-               \ \_______\   \ \__\ \__\   \ \__\ \__\       \ \__\   \ \_______\   \ \_______\   \ \_______\
-                \|_______|    \|__|\|__|    \|__|\|__|        \|__|    \|_______|    \|_______|    \|_______|            
-        
-
-            ╔═╗┬ ┬┌─┐┌┬┐┬  ┌─┐┌─┐
-            ║  ├─┤├─┤ │ │  │ ││ ┬
-            ╚═╝┴ ┴┴ ┴ ┴ ┴─┘└─┘└─┘
-        
-
-            ▄▄·  ▄ .▄ ▄▄▄· ▄▄▄▄▄▄▄▌         ▄▄ • 
-            ▐█ ▌▪██▪▐█▐█ ▀█ •██  ██•  ▪     ▐█ ▀ ▪
-            ██ ▄▄██▀▐█▄█▀▀█  ▐█.▪██▪   ▄█▀▄ ▄█ ▀█▄
-            ▐███▌██▌▐▀▐█ ▪▐▌ ▐█▌·▐█▌▐▌▐█▌.▐▌▐█▄▪▐█
-            ·▀▀▀ ▀▀▀ · ▀  ▀  ▀▀▀ .▀▀▀  ▀█▄▀▪·▀▀▀▀ 
-        
-
-            ,. - .,               .·¨'`;        ,.·´¨;\                   ,.,   '               ,  . .,  °             ,.  '              , ·. ,.-·~·.,   ‘              ,.-·^*ª'` ·,        
-            ,·'´ ,. - ,   ';\          ';   ;'\       ';   ;::\                ;´   '· .,        ;'´    ,   ., _';\'         /   ';\             /  ·'´,.-·-.,   `,'‚           .·´ ,·'´:¯'`·,  '\‘     
-        ,·´  .'´\:::::;'   ;:'\ '       ;   ;::'\      ,'   ;::';             .´  .-,    ';\      \:´¨¯:;'   `;::'\:'\      ,'   ,'::'\           /  .'´\:::::::'\   '\ °       ,´  ,'\:::::::::\,.·\'    
-       /  ,'´::::'\;:-/   ,' ::;  '     ;  ;::_';,. ,.'   ;:::';°           /   /:\:';   ;:'\'      \::::;   ,'::_'\;'     ,'    ;:::';'       ,·'  ,'::::\:;:-·-:';  ';\‚      /   /:::\;·'´¯'`·;\:::\°  
-     ,'   ;':::::;'´ ';   /\::;' '     .'     ,. -·~-·,   ;:::'; '         ,'  ,'::::'\';  ;::';          ,'  ,'::;'  ‘       ';   ,':::;'       ;.   ';:::;´       ,'  ,':'\‚    ;   ;:::;'          '\;:·´  
-     ;   ;:::::;   '\*'´\::\'  °     ';   ;'\::::::::;  '/::::;       ,.-·'  '·~^*'´¨,  ';::;          ;  ;:::;  °       ;  ,':::;' '        ';   ;::;       ,'´ .'´\::';‚  ';   ;::/      ,·´¯';  °    
-     ';   ';::::';    '\::'\/.'         ;  ';:;\;::-··;  ;::::;        ':,  ,·:²*´¨¯'`;  ;::';          ;  ;::;'  ‘       ,'  ,'::;'           ';   ':;:   ,.·´,.·´::::\;'°  ';   '·;'   ,.·´,    ;'\      
-      \    '·:;:'_ ,. -·'´.·´\‘       ':,.·´\;'    ;' ,' :::/  '       ,'  / \::::::::';  ;::';          ;  ;::;'‚         ;  ';_:,.-·´';\‘     \·,   `*´,.·'´::::::;·´     \'·.    `'´,.·:´';   ;::\'    
-       '\:` ·  .,.  -·:´::::::\'       \:::::\    \·.'::::;         ,' ,'::::\·²*'´¨¯':,'\:;           ',.'\::;'‚         ',   _,.-·'´:\:\‘     \\:¯::\:::::::;:·´         '\::\¯::::::::';   ;::'; ‘  
-         \:::::::\:::::::;:·'´'          \;:·´     \:\::';          \`¨\:::/          \::\'            \::\:;'‚          \¨:::::::::::\';      `\:::::\;::·'´  °            `·:\:::;:·´';.·´\::;'     
-           `· :;::\;::-·´                          `·\;'            '\::\;'            '\;'  '           \;:'      ‘       '\;::_;:-·'´‘            ¯                           ¯      \::::\;'‚     
-                                                      '               `¨'                                °                '¨                      ‘                                    '\:·´'       
-        
-
-            ▄████▄   ██░ ██  ▄▄▄      ▄▄▄█████▓ ██▓     ▒█████    ▄████ 
-            ▒██▀ ▀█  ▓██░ ██▒▒████▄    ▓  ██▒ ▓▒▓██▒    ▒██▒  ██▒ ██▒ ▀█▒
-            ▒▓█    ▄ ▒██▀▀██░▒██  ▀█▄  ▒ ▓██░ ▒░▒██░    ▒██░  ██▒▒██░▄▄▄░
-            ▒▓▓▄ ▄██▒░▓█ ░██ ░██▄▄▄▄██ ░ ▓██▓ ░ ▒██░    ▒██   ██░░▓█  ██▓
-            ▒ ▓███▀ ░░▓█▒░██▓ ▓█   ▓██▒  ▒██▒ ░ ░██████▒░ ████▓▒░░▒▓███▀▒
-            ░ ░▒ ▒  ░ ▒ ░░▒░▒ ▒▒   ▓▒█░  ▒ ░░   ░ ▒░▓  ░░ ▒░▒░▒░  ░▒   ▒ 
-              ░  ▒    ▒ ░▒░ ░  ▒   ▒▒ ░    ░    ░ ░ ▒  ░  ░ ▒ ▒░   ░   ░ 
-            ░         ░  ░░ ░  ░   ▒     ░        ░ ░   ░ ░ ░ ▒  ░ ░   ░ 
-            ░ ░       ░  ░  ░      ░  ░             ░  ░    ░ ░        ░ 
-            ░                                                            
-        
-
-            ▄█▄     ▄  █ ██      ▄▄▄▄▀ █     ████▄   ▄▀  
-            █▀ ▀▄  █   █ █ █  ▀▀▀ █    █     █   █ ▄▀    
-            █   ▀  ██▀▀█ █▄▄█     █    █     █   █ █ ▀▄  
-            █▄  ▄▀ █   █ █  █    █     ███▄  ▀████ █   █ 
-            ▀███▀     █     █   ▀          ▀        ███  
-                     ▀     █                             
-                          ▀                              
-        
+ + +
+
+

🎉 恭喜!Chatlog 服务已成功启动

+

+ Chatlog 是一个帮助你轻松使用自己聊天数据的工具,现在你可以通过 HTTP + API 访问你的聊天记录、联系人和群聊信息。 +

+
+ +
+

🔍 API 接口与调试

+ +
+
+
最近会话
+
群聊
+
联系人
+
聊天记录
+
+ + +
+
+

+ 查询最近会话列表。GET /api/v1/session +

+
+
+ + +
+
+ + +
+
+

+ 查询群聊列表,可选择性地按关键词搜索。GET /api/v1/chatroom +

+
+
+ + +
+
+ + +
+
+ + +
+
+

+ 查询联系人列表,可选择性地按关键词搜索。GET /api/v1/contact +

+
+
+ + +
+
+ + +
+
+ + +
+
+

+ 查询指定时间范围内与特定联系人或群聊的聊天记录。GET /api/v1/chatlog +

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + + + +
+
+
+ +
+

🤖 MCP 集成

+

+ Chatlog 支持 MCP (Model Context Protocol) SSE 协议,可与支持 MCP 的 AI + 助手无缝集成。 +

+

SSE 端点:/sse

+

+ 详细集成指南请参考 + MCP 集成指南 +

+
+ +
+

📚 更多资源

+

+ 查看 + GitHub 项目 + 获取完整文档和使用指南。 +

+

+ 如果你有任何问题或建议,欢迎通过 + Discussions + 进行交流。 +

+
+ - + diff --git a/internal/wechat/key/darwin/v3.go b/internal/wechat/key/darwin/v3.go index fd92ca5..fd0decc 100644 --- a/internal/wechat/key/darwin/v3.go +++ b/internal/wechat/key/darwin/v3.go @@ -22,7 +22,7 @@ const ( var V3KeyPatterns = []KeyPatternInfo{ { Pattern: []byte{0x72, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x33, 0x32}, - Offset: 24, + Offsets: []int{24}, }, } @@ -122,16 +122,73 @@ func (e *V3Extractor) findMemory(ctx context.Context, pid uint32, memoryChannel return err } - log.Debug().Msgf("Read memory region, size: %d bytes", len(memory)) + totalSize := len(memory) + log.Debug().Msgf("Read memory region, size: %d bytes", totalSize) - // Send memory data to channel for processing - select { - case memoryChannel <- memory: - log.Debug().Msg("Memory region sent for analysis") - case <-ctx.Done(): - return ctx.Err() + // If memory is small enough, process it as a single chunk + if totalSize <= MinChunkSize { + select { + case memoryChannel <- memory: + log.Debug().Msg("Memory sent as a single chunk for analysis") + case <-ctx.Done(): + return ctx.Err() + } + return nil } + chunkCount := MaxWorkers * ChunkMultiplier + + // Calculate chunk size based on fixed chunk count + chunkSize := totalSize / chunkCount + if chunkSize < MinChunkSize { + // Reduce number of chunks if each would be too small + chunkCount = totalSize / MinChunkSize + if chunkCount == 0 { + chunkCount = 1 + } + chunkSize = totalSize / chunkCount + } + + // Process memory in chunks from end to beginning + for i := chunkCount - 1; i >= 0; i-- { + select { + case <-ctx.Done(): + return ctx.Err() + default: + // Calculate start and end positions for this chunk + start := i * chunkSize + end := (i + 1) * chunkSize + + // Ensure the last chunk includes all remaining memory + if i == chunkCount-1 { + end = totalSize + } + + // Add overlap area to catch patterns at chunk boundaries + if i > 0 { + start -= ChunkOverlapBytes + if start < 0 { + start = 0 + } + } + + chunk := memory[start:end] + + log.Debug(). + Int("chunk_index", i+1). + Int("total_chunks", chunkCount). + Int("chunk_size", len(chunk)). + Int("start_offset", start). + Int("end_offset", end). + Msg("Processing memory chunk") + + select { + case memoryChannel <- chunk: + case <-ctx.Done(): + return ctx.Err() + } + } + } return nil } @@ -173,24 +230,26 @@ func (e *V3Extractor) SearchKey(ctx context.Context, memory []byte) (string, boo break // No more matches found } - // Check if we have enough space for the key - keyOffset := index + keyPattern.Offset - if keyOffset < 0 || keyOffset+32 > len(memory) { - index -= 1 - continue - } + // Try each offset for this pattern + for _, offset := range keyPattern.Offsets { + // Check if we have enough space for the key + keyOffset := index + offset + if keyOffset < 0 || keyOffset+32 > len(memory) { + continue + } - // Extract the key data, which is 32 bytes long - keyData := memory[keyOffset : keyOffset+32] + // Extract the key data, which is at the offset position and 32 bytes long + keyData := memory[keyOffset : keyOffset+32] - // Validate key against database header - if e.validator.Validate(keyData) { - log.Debug(). - Str("pattern", hex.EncodeToString(keyPattern.Pattern)). - Int("offset", keyPattern.Offset). - Str("key", hex.EncodeToString(keyData)). - Msg("Key found") - return hex.EncodeToString(keyData), true + // Validate key against database header + if e.validator.Validate(keyData) { + log.Debug(). + Str("pattern", hex.EncodeToString(keyPattern.Pattern)). + Int("offset", offset). + Str("key", hex.EncodeToString(keyData)). + Msg("Key found") + return hex.EncodeToString(keyData), true + } } index -= 1 diff --git a/internal/wechat/key/darwin/v4.go b/internal/wechat/key/darwin/v4.go index 09530a5..f538e1a 100644 --- a/internal/wechat/key/darwin/v4.go +++ b/internal/wechat/key/darwin/v4.go @@ -16,17 +16,16 @@ import ( ) const ( - MaxWorkers = 8 + MaxWorkers = 8 + MinChunkSize = 1 * 1024 * 1024 // 1MB + ChunkOverlapBytes = 1024 // Greater than all offsets + ChunkMultiplier = 2 // Number of chunks = MaxWorkers * ChunkMultiplier ) var V4KeyPatterns = []KeyPatternInfo{ { Pattern: []byte{0x20, 0x66, 0x74, 0x73, 0x35, 0x28, 0x25, 0x00}, - Offset: 16, - }, - { - Pattern: []byte{0x20, 0x66, 0x74, 0x73, 0x35, 0x28, 0x25, 0x00}, - Offset: -80, + Offsets: []int{16, -80, 64}, }, } @@ -126,14 +125,72 @@ func (e *V4Extractor) findMemory(ctx context.Context, pid uint32, memoryChannel return err } - log.Debug().Msgf("Read memory region, size: %d bytes", len(memory)) + totalSize := len(memory) + log.Debug().Msgf("Read memory region, size: %d bytes", totalSize) - // Send memory data to channel for processing - select { - case memoryChannel <- memory: - log.Debug().Msg("Memory region sent for analysis") - case <-ctx.Done(): - return ctx.Err() + // If memory is small enough, process it as a single chunk + if totalSize <= MinChunkSize { + select { + case memoryChannel <- memory: + log.Debug().Msg("Memory sent as a single chunk for analysis") + case <-ctx.Done(): + return ctx.Err() + } + return nil + } + + chunkCount := MaxWorkers * ChunkMultiplier + + // Calculate chunk size based on fixed chunk count + chunkSize := totalSize / chunkCount + if chunkSize < MinChunkSize { + // Reduce number of chunks if each would be too small + chunkCount = totalSize / MinChunkSize + if chunkCount == 0 { + chunkCount = 1 + } + chunkSize = totalSize / chunkCount + } + + // Process memory in chunks from end to beginning + for i := chunkCount - 1; i >= 0; i-- { + select { + case <-ctx.Done(): + return ctx.Err() + default: + // Calculate start and end positions for this chunk + start := i * chunkSize + end := (i + 1) * chunkSize + + // Ensure the last chunk includes all remaining memory + if i == chunkCount-1 { + end = totalSize + } + + // Add overlap area to catch patterns at chunk boundaries + if i > 0 { + start -= ChunkOverlapBytes + if start < 0 { + start = 0 + } + } + + chunk := memory[start:end] + + log.Debug(). + Int("chunk_index", i+1). + Int("total_chunks", chunkCount). + Int("chunk_size", len(chunk)). + Int("start_offset", start). + Int("end_offset", end). + Msg("Processing memory chunk") + + select { + case memoryChannel <- chunk: + case <-ctx.Done(): + return ctx.Err() + } + } } return nil @@ -177,24 +234,26 @@ func (e *V4Extractor) SearchKey(ctx context.Context, memory []byte) (string, boo break // No more matches found } - // Check if we have enough space for the key - keyOffset := index + keyPattern.Offset - if keyOffset < 0 || keyOffset+32 > len(memory) { - index -= 1 - continue - } + // Try each offset for this pattern + for _, offset := range keyPattern.Offsets { + // Check if we have enough space for the key + keyOffset := index + offset + if keyOffset < 0 || keyOffset+32 > len(memory) { + continue + } - // Extract the key data, which is 16 bytes after the pattern and 32 bytes long - keyData := memory[keyOffset : keyOffset+32] + // Extract the key data, which is at the offset position and 32 bytes long + keyData := memory[keyOffset : keyOffset+32] - // Validate key against database header - if e.validator.Validate(keyData) { - log.Debug(). - Str("pattern", hex.EncodeToString(keyPattern.Pattern)). - Int("offset", keyPattern.Offset). - Str("key", hex.EncodeToString(keyData)). - Msg("Key found") - return hex.EncodeToString(keyData), true + // Validate key against database header + if keyData, ok := e.validate(ctx, keyData); ok { + log.Debug(). + Str("pattern", hex.EncodeToString(keyPattern.Pattern)). + Int("offset", offset). + Str("key", hex.EncodeToString(keyData)). + Msg("Key found") + return hex.EncodeToString(keyData), true + } } index -= 1 @@ -204,11 +263,19 @@ func (e *V4Extractor) SearchKey(ctx context.Context, memory []byte) (string, boo return "", false } +func (e *V4Extractor) validate(ctx context.Context, keyDate []byte) ([]byte, bool) { + if e.validator.Validate(keyDate) { + return keyDate, true + } + // Try to find a valid key by *** + return nil, false +} + func (e *V4Extractor) SetValidate(validator *decrypt.Validator) { e.validator = validator } type KeyPatternInfo struct { Pattern []byte - Offset int + Offsets []int } diff --git a/internal/wechatdb/datasource/windowsv3/datasource.go b/internal/wechatdb/datasource/windowsv3/datasource.go index 2a8434c..92d62e4 100644 --- a/internal/wechatdb/datasource/windowsv3/datasource.go +++ b/internal/wechatdb/datasource/windowsv3/datasource.go @@ -35,7 +35,7 @@ var Groups = []dbm.Group{ }, { Name: Contact, - Pattern: `^MicroMsg.db$`, + Pattern: `^MicroMsg\.db$`, BlackList: []string{}, }, {