添加all命令中解密错误数据日志写入文件,修复部分bug #28 #29

This commit is contained in:
xaoyo 2023-11-22 18:33:49 +08:00
parent 2f2cf58c47
commit 36f0d26e45
6 changed files with 123 additions and 24 deletions

View File

@ -16,6 +16,7 @@
<details>
<summary><strong>更新日志(点击展开)</strong></summary>
* 2023.11.22 添加all命令中解密错误数据日志写入文件,修复部分bug
* 2023.11.16 增加聊天记录导出为html
* 2023.11.15 添加test文件添加自动构建可执行文件的脚本,添加版本描述
* 2023.11.15 [v2.2.5变化较大]重构解密脚本的返回值,重构命令行参数
@ -49,7 +50,7 @@
## 1. 项目简介
PyWxDump可用于获取用户个人信息(昵称/账号/手机/邮箱/数据库密钥(用来解密聊天记录))数据库读取、解密脚本聊天记录查看、聊天记录导出为html。
[PyWxDump](https://github.com/xaoyaoo/PyWxDump)可用于:获取用户个人信息(昵称/账号/手机/邮箱/数据库密钥(用来解密聊天记录))数据库读取、解密脚本聊天记录查看、聊天记录导出为html。
支持多账户信息获取,支持所有微信版本。
@ -67,7 +68,7 @@ PyWxDump可用于获取用户个人信息(昵称/账号/手机/邮箱/数据
* 6提供数据库部分字段说明
* 7支持微信多开场景获取多用户信息等
* 8微信需要登录状态才能获取数据库密钥
* 9支持导出聊天记录为html
* 9支持导出聊天记录为html,备份微信聊天记录,方便查看
**版本差异**
@ -121,6 +122,7 @@ PyWxDump
[PyWxDump](https://github.com/xaoyaoo/PyWxDump)是[SharpWxDump](https://github.com/AdminTest0/SharpWxDump)
的经过重构python语言版本同时添加了一些新的功能。
* 项目地址https://github.com/xaoyaoo/PyWxDump
* 目前只在windows下测试过linux下可能会存在问题。
* 如发现[version_list.json](pywxdump/version_list.json)缺失或错误,
请提交[issues](https://github.com/xaoyaoo/PyWxDump/issues).
@ -331,10 +333,15 @@ else:
本项目仅供学习交流使用,请勿用于非法用途,否则后果自负。
本项目仅允许在授权情况下对数据库进行备份,严禁用于非法目的,否则自行承担所有相关责任。使用该工具则代表默认同意该条款;
您应该在下载保存编译使用本项目的24小时内删除本项目的源代码和编译出的程序。
本项目仅允许在授权情况下对数据库进行备份,严禁用于非法目的,否则自行承担所有相关责任。
下载、保存、进一步浏览源代码或者下载安装、编译使用本程序,表示你同意本警告,并承诺遵守它;
请勿利用本项目的相关技术从事非法测试,如因此产生的一切不良后果与项目作者无关。
# 四、许可证
```text

View File

@ -5,6 +5,7 @@
# Author: xaoyaoo
# Date: 2023/09/27
# -------------------------------------------------------------------------------
import os.path
import sqlite3
import pysilk
from io import BytesIO
@ -245,5 +246,43 @@ def read_audio(MsgSvrID, is_play=False, is_wave=False, DB_PATH: str = "", rate=2
return pcm_data
def wordcloud_generator(text, out_path="", is_show=False, img_path="", font="C:\Windows\Fonts\simhei.ttf"):
"""
词云
:param is_show: 是否显示
:param img_path: 背景图片路径
:param text: 文本
:param font: 字体路径
:return:
"""
try:
from wordcloud import WordCloud
import jieba
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.font_manager import fontManager
except ImportError as e:
print("error", e)
raise ImportError("请安装wordcloud,jieba,numpy,matplotlib,pillow库")
words = jieba.lcut(text) # 精确分词
newtxt = ' '.join(words) # 空格拼接
# 字体路径
# 创建WordCloud对象
wordcloud1 = WordCloud(width=800, height=400, background_color='white', font_path=font)
wordcloud1.generate(newtxt)
if out_path and out_path != "":
wordcloud1.to_file("wordcloud.png") # 保存图片
if img_path and os.path.exists(img_path): # 设置背景图片
img_color = np.array(Image.open(img_path)) # 读取背景图片
img_color = img_color.reshape((img_color.shape[0] * img_color.shape[1], 3))
wordcloud1.recolor(color_func=img_color) # 设置背景图片颜色
if is_show:
# 显示词云
wordcloud_img = wordcloud1.to_image()
wordcloud_img.show()
if __name__ == '__main__':
pass
wordcloud_generator("我是中国人,我喜欢吃饭", is_show=True)

View File

@ -12,9 +12,6 @@ import json
import multiprocessing
import os
import re
import time
import winreg
import threading
import platform
import psutil

View File

@ -7,6 +7,8 @@
# -------------------------------------------------------------------------------
import argparse
import importlib.metadata
import sys
import textwrap
from . import *
@ -19,12 +21,12 @@ class MainBiasAddr():
self.mode = "bias"
# 添加 'bias_addr' 子命令解析器
sb_bias_addr = parser.add_parser(self.mode, help="获取微信基址偏移")
sb_bias_addr.add_argument("--mobile", type=str, help="手机号", required=True)
sb_bias_addr.add_argument("--name", type=str, help="微信昵称", required=True)
sb_bias_addr.add_argument("--account", type=str, help="微信账号", required=True)
sb_bias_addr.add_argument("--key", type=str, help="(可选)密钥")
sb_bias_addr.add_argument("--db_path", type=str, help="(可选)已登录账号的微信文件夹路径")
sb_bias_addr.add_argument("-vlp", '--version_list_path', type=str,
sb_bias_addr.add_argument("--mobile", type=str, help="手机号", metavar="", required=True)
sb_bias_addr.add_argument("--name", type=str, help="微信昵称", metavar="", required=True)
sb_bias_addr.add_argument("--account", type=str, help="微信账号", metavar="", required=True)
sb_bias_addr.add_argument("--key", type=str, metavar="", help="(可选)密钥")
sb_bias_addr.add_argument("--db_path", type=str, metavar="", help="(可选)已登录账号的微信文件夹路径")
sb_bias_addr.add_argument("-vlp", '--version_list_path', type=str, metavar="",
help="(可选)微信版本偏移文件路径,如有,则自动更新",
default=None)
self.sb_bias_addr = sb_bias_addr
@ -52,12 +54,13 @@ class MainWxInfo():
self.mode = "info"
# 添加 'wx_info' 子命令解析器
sb_wx_info = parser.add_parser(self.mode, help="获取微信信息")
sb_wx_info.add_argument("-vlp", type=str, help="(可选)微信版本偏移文件路径", default=VERSION_LIST_PATH)
sb_wx_info.add_argument("-vlp", '--version_list_path', metavar="", type=str,
help="(可选)微信版本偏移文件路径", default=VERSION_LIST_PATH)
return sb_wx_info
def run(self, args):
# 读取微信各版本偏移
path = args.vlp
path = args.version_list_path
version_list = json.load(open(path, "r", encoding="utf-8"))
result = read_info(version_list, True) # 读取微信信息
return result
@ -173,7 +176,7 @@ class MainExportChatRecords():
def init_parses(self, parser):
self.mode = "export"
# 添加 'decrypt' 子命令解析器
sb_decrypt = parser.add_parser(self.mode, help="聊天记录导出为html")
sb_decrypt = parser.add_parser(self.mode, help="聊天记录导出为html[需要安装flask]")
sb_decrypt.add_argument("-u", "--username", type=str, help="微信账号", required=True, metavar="")
sb_decrypt.add_argument("-o", "--outpath", type=str, help="导出路径", required=True, metavar="")
sb_decrypt.add_argument("-msg", "--msg_path", type=str, help="解密后的 MSG.db 的路径", required=True,
@ -274,8 +277,11 @@ class MainAll():
f'[+] success "{os.path.relpath(ret1[0], os.path.commonprefix(wxdbpaths))}" -> "{os.path.relpath(ret1[1], os.getcwd())}"')
out_dbs.append(ret1[1])
print("-" * 32)
print("[-] " + f"{len(errors)} 个文件解密失败;")
print(
"[-] " + f"{len(errors)} 个文件解密失败(可能原因:非当前登录用户数据库;非加密数据库),详见{out_path}下‘解密失败.txt;")
# print("; ".join([f'"{wxdbpaths[i]}"' for i in errors]))
with open(os.path.join(out_path, "解密失败.txt"), "w", encoding="utf-8") as f:
f.write("\n".join([f'{i}' for i in errors]))
print("=" * 32)
if len(out_dbs) <= 0:
@ -300,13 +306,31 @@ class MainAll():
MainShowChatRecords().run(args)
PYWXDUMP_VERSION = importlib.metadata.version('pywxdump')
class CustomArgumentParser(argparse.ArgumentParser):
def format_help(self):
# 首先显示软件简介
# 定义软件简介文本并进行格式化
PYWXDUMP_VERSION = importlib.metadata.version('pywxdump')
first_line = f'\033[36m{" PyWxDump v" + PYWXDUMP_VERSION + " ":=^80}\033[0m'
brief = 'PyWxDump是一款用于获取账号信息(昵称/账号/手机/邮箱/数据库密钥)、解密数据库、查看\n聊天记录、备份导出聊天记录为html的工具。'
other = '更多详情请查看: \033[4m\033[1mhttps://github.com/xaoyaoo/PyWxDump\033[0m'
separator = f'{"options":-^80}'
# 获取帮助信息并添加到软件简介下方
help_text = super().format_help().strip()
return f'{first_line}\n{brief}\n{separator}\n{help_text}\n{separator}\n{other}\n{first_line}\n'
def console_run():
# 创建命令行参数解析器
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
version = importlib.metadata.version('pywxdump')
version = f"PyWxDump {version}"
parser.add_argument('-V', '--version', action='version', version=version)
parser = CustomArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
PYWXDUMP_VERSION = importlib.metadata.version('pywxdump')
parser.add_argument('-V', '--version', action='version', version=f"PyWxDump v{PYWXDUMP_VERSION}")
# 添加子命令解析器
subparsers = parser.add_subparsers(dest="mode", help="""运行模式:""", required=True, metavar="mode")
@ -347,6 +371,12 @@ def console_run():
sb_all = main_all.init_parses(subparsers)
modes[main_all.mode] = main_all
# 检查是否需要显示帮助信息
if len(sys.argv) == 1:
sys.argv.append('-h')
elif len(sys.argv) == 2 and sys.argv[1] in modes.keys():
sys.argv.append('-h')
args = parser.parse_args() # 解析命令行参数
if not any(vars(args).values()):

View File

@ -24,9 +24,35 @@ def get_info_without_key(h_process, address, n_size=64):
return text.strip() if text.strip() != "" else "None"
def pattern_scan_all(handle, pattern, *, return_multiple=False):
import sys
next_region = 0
found = []
user_space_limit = 0x7FFFFFFF0000 if sys.maxsize > 2 ** 32 else 0x7fff0000
while next_region < user_space_limit:
try:
next_region, page_found = pymem.pattern.scan_pattern_page(
handle,
next_region,
pattern,
return_multiple=return_multiple
)
except Exception as e:
print(e)
break
if not return_multiple and page_found:
return page_found
if page_found:
found += page_found
if not return_multiple:
return None
return found
def get_info_wxid(h_process, n_size=64):
pm = pymem.Pymem("WeChat.exe")
addrs = pymem.pattern.pattern_scan_all(pm.process_handle, b'wxid_', return_multiple=True)
# addrs = pymem.pattern.pattern_scan_all(pm.process_handle, b'wxid_', return_multiple=True)
addrs = pattern_scan_all(pm.process_handle, b'wxid_', return_multiple=True)
for addr in addrs:
wxidtmp = get_info_without_key(h_process, addr, n_size)
if wxidtmp.startswith("wxid_") and r'\FileStorage\MsgAttach' in wxidtmp:

View File

@ -3,7 +3,7 @@ from setuptools import setup, find_packages
with open("README.md", "r", encoding="utf-8") as fh:
long_description = fh.read()
version = "2.2.7"
version = "2.2.8"
install_requires = [
"psutil",