feat: 添加微信数据库解密工具的基本功能

This commit is contained in:
2977094657
2025-07-07 19:01:14 +08:00
commit 4896e8a2ec
11 changed files with 1895 additions and 0 deletions

0
src/__init__.py Normal file
View File

View File

@@ -0,0 +1,5 @@
"""微信数据库解密工具
"""
__version__ = "0.1.0"
__author__ = "WeChat Decrypt Tool"

View File

@@ -0,0 +1,128 @@
"""微信解密工具的FastAPI Web服务器"""
from typing import Optional
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from .wechat_decrypt import decrypt_wechat_databases
app = FastAPI(
title="微信数据库解密工具",
description="现代化的微信数据库解密工具,支持微信信息检测和数据库解密功能",
version="0.1.0"
)
# Enable CORS for React frontend
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
class DecryptRequest(BaseModel):
"""解密请求模型"""
key: str
db_storage_path: Optional[str] = None # 可选的数据库存储路径,如 ......\{微信id}\db_storage
@app.get("/", summary="根端点")
async def root():
"""根端点"""
return {"message": "微信数据库解密工具 API"}
@app.get("/api/wechat-detection", summary="详细检测微信安装信息")
async def detect_wechat_detailed():
"""详细检测微信安装信息,包括版本、路径、消息目录等。"""
try:
from .wechat_detection import detect_wechat_installation
info = detect_wechat_installation()
# 添加一些统计信息
stats = {
'total_databases': len(info['databases']),
'total_user_accounts': len(info['user_accounts']),
'total_message_dirs': len(info['message_dirs']),
'has_wechat_installed': info['wechat_install_path'] is not None,
'detection_time': __import__('datetime').datetime.now().isoformat()
}
return {
'status': 'success',
'data': info,
'statistics': stats
}
except Exception as e:
return {
'status': 'error',
'error': str(e),
'data': None,
'statistics': None
}
@app.post("/api/decrypt", summary="解密微信数据库")
async def decrypt_databases(request: DecryptRequest):
"""使用提供的密钥解密微信数据库
参数:
- key: 解密密钥(必选)
- db_storage_path: 数据库存储路径(可选),如 ......\\{微信id}\\db_storage
如果不提供db_storage_path将自动检测所有微信数据库
"""
try:
# 验证密钥格式
if not request.key or len(request.key) != 64:
raise HTTPException(status_code=400, detail="密钥格式无效必须是64位十六进制字符串")
# 使用新的解密API
results = decrypt_wechat_databases(
db_storage_path=request.db_storage_path,
key=request.key
)
if results["status"] == "error":
raise HTTPException(status_code=400, detail=results["message"])
return {
"status": "completed" if results["status"] == "success" else "failed",
"total_databases": results["total_databases"],
"success_count": results["successful_count"],
"failure_count": results["failed_count"],
"output_directory": results["output_directory"],
"message": results["message"],
"processed_files": results["processed_files"],
"failed_files": results["failed_files"]
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.get("/api/health", summary="健康检查端点")
async def health_check():
"""健康检查端点"""
return {"status": "healthy", "service": "微信解密工具"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)

View File

@@ -0,0 +1,385 @@
#!/usr/bin/env python3
"""
微信4.x数据库解密工具
基于SQLCipher 4.0加密机制,支持批量解密微信数据库文件
使用方法:
python wechat_decrypt.py
密钥: 请通过参数传入您的解密密钥
"""
import os
import hashlib
import hmac
from pathlib import Path
from datetime import datetime
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
# 默认密钥已移除,请通过参数传入
WECHAT_KEY = None
# SQLite文件头
SQLITE_HEADER = b"SQLite format 3\x00"
def setup_logging():
"""设置日志配置"""
import logging
# 创建日志目录
now = datetime.now()
log_dir = Path("output/logs") / str(now.year) / f"{now.month:02d}" / f"{now.day:02d}"
log_dir.mkdir(parents=True, exist_ok=True)
# 设置日志文件名
date_str = now.strftime("%d")
log_file = log_dir / f"{date_str}_decrypt.log"
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s | %(levelname)s | %(message)s',
handlers=[
logging.FileHandler(log_file, encoding='utf-8'),
logging.StreamHandler()
]
)
logging.info(f"日志系统初始化完成,日志文件: {log_file}")
return log_dir
class WeChatDatabaseDecryptor:
"""微信4.x数据库解密器"""
def __init__(self, key_hex: str):
"""初始化解密器
参数:
key_hex: 64位十六进制密钥
"""
if len(key_hex) != 64:
raise ValueError("密钥必须是64位十六进制字符串")
try:
self.key_bytes = bytes.fromhex(key_hex)
except ValueError:
raise ValueError("密钥必须是有效的十六进制字符串")
def decrypt_database(self, db_path: str, output_path: str) -> bool:
"""解密微信4.x版本数据库
使用SQLCipher 4.0参数:
- PBKDF2-SHA512, 256000轮迭代
- AES-256-CBC加密
- HMAC-SHA512验证
- 页面大小4096字节
"""
import logging
logging.info(f"开始解密数据库: {db_path}")
try:
with open(db_path, 'rb') as f:
encrypted_data = f.read()
logging.info(f"读取文件大小: {len(encrypted_data)} bytes")
if len(encrypted_data) < 4096:
logging.warning(f"文件太小,跳过解密: {db_path}")
return False
# 检查是否已经是解密的数据库
if encrypted_data.startswith(SQLITE_HEADER):
logging.info(f"文件已是SQLite格式直接复制: {db_path}")
with open(output_path, 'wb') as f:
f.write(encrypted_data)
return True
# 提取salt (前16字节)
salt = encrypted_data[:16]
# 计算mac_salt (salt XOR 0x3a)
mac_salt = bytes(b ^ 0x3a for b in salt)
# 使用PBKDF2-SHA512派生密钥
kdf = PBKDF2HMAC(
algorithm=hashes.SHA512(),
length=32,
salt=salt,
iterations=256000,
backend=default_backend()
)
derived_key = kdf.derive(self.key_bytes)
# 派生MAC密钥
mac_kdf = PBKDF2HMAC(
algorithm=hashes.SHA512(),
length=32,
salt=mac_salt,
iterations=2,
backend=default_backend()
)
mac_key = mac_kdf.derive(derived_key)
# 解密数据
decrypted_data = bytearray()
decrypted_data.extend(SQLITE_HEADER)
page_size = 4096
iv_size = 16
hmac_size = 64 # SHA512的HMAC是64字节
# 计算保留区域大小 (对齐到AES块大小)
reserve_size = iv_size + hmac_size
if reserve_size % 16 != 0:
reserve_size = ((reserve_size // 16) + 1) * 16
total_pages = len(encrypted_data) // page_size
successful_pages = 0
failed_pages = 0
# 逐页解密
for cur_page in range(total_pages):
start = cur_page * page_size
end = start + page_size
page = encrypted_data[start:end]
page_num = cur_page + 1 # 页面编号从1开始
if len(page) < page_size:
logging.warning(f"页面 {page_num} 大小不足: {len(page)} bytes")
break
# 确定偏移量:第一页(cur_page == 0)需要跳过salt
offset = 16 if cur_page == 0 else 0 # SALT_SIZE = 16
# 提取存储的HMAC
hmac_start = page_size - reserve_size + iv_size
hmac_end = hmac_start + hmac_size
stored_hmac = page[hmac_start:hmac_end]
# 按照wechat-dump-rs的方式验证HMAC
data_end = page_size - reserve_size + iv_size
hmac_data = page[offset:data_end]
# 分步计算HMAC先更新数据再更新页面编号
mac = hmac.new(mac_key, digestmod=hashlib.sha512)
mac.update(hmac_data) # 包含加密数据+IV
mac.update(page_num.to_bytes(4, 'little')) # 页面编号(小端序)
expected_hmac = mac.digest()
if stored_hmac != expected_hmac:
logging.warning(f"页面 {page_num} HMAC验证失败")
failed_pages += 1
continue
# 提取IV和加密数据用于AES解密
iv = page[page_size - reserve_size:page_size - reserve_size + iv_size]
encrypted_page = page[offset:page_size - reserve_size]
# AES-CBC解密
try:
cipher = Cipher(
algorithms.AES(derived_key),
modes.CBC(iv),
backend=default_backend()
)
decryptor = cipher.decryptor()
decrypted_page = decryptor.update(encrypted_page) + decryptor.finalize()
# 按照wechat-dump-rs的方式重组页面数据
decrypted_data.extend(decrypted_page)
decrypted_data.extend(page[page_size - reserve_size:]) # 保留区域
successful_pages += 1
except Exception as e:
logging.error(f"页面 {page_num} AES解密失败: {e}")
failed_pages += 1
continue
logging.info(f"解密完成: 成功 {successful_pages} 页, 失败 {failed_pages}")
# 写入解密后的文件
with open(output_path, 'wb') as f:
f.write(decrypted_data)
logging.info(f"解密文件大小: {len(decrypted_data)} bytes")
return True
except Exception as e:
logging.error(f"解密失败: {db_path}, 错误: {e}")
return False
def decrypt_wechat_databases(db_storage_path: str = None, key: str = None) -> dict:
"""
微信数据库解密API函数
参数:
db_storage_path: 数据库存储路径,如 ......\\{微信id}\\db_storage
如果为None将自动搜索数据库文件
key: 解密密钥如果为None将使用默认密钥
返回值:
dict: 解密结果统计信息
{
"status": "success" | "error",
"message": "描述信息",
"total_databases": 总数据库数量,
"successful_count": 成功解密数量,
"failed_count": 失败数量,
"output_directory": "输出目录路径",
"processed_files": ["解密成功的文件列表"],
"failed_files": ["解密失败的文件列表"]
}
"""
import logging
# 初始化日志系统
setup_logging()
# 验证密钥是否提供
if not key:
return {
"status": "error",
"message": "解密密钥是必需的参数",
"total_databases": 0,
"successful_count": 0,
"failed_count": 0,
"output_directory": "",
"processed_files": [],
"failed_files": []
}
decrypt_key = key
logging.info("=" * 60)
logging.info("微信4.x数据库解密工具 - API模式")
logging.info("=" * 60)
# 创建输出目录
output_dir = Path("output/databases")
output_dir.mkdir(parents=True, exist_ok=True)
logging.info(f"输出目录: {output_dir.absolute()}")
# 查找数据库文件
if db_storage_path:
# 使用指定路径查找数据库
database_paths = []
storage_path = Path(db_storage_path)
if storage_path.exists():
for db_file in storage_path.glob("*.db"):
if db_file.is_file() and db_file.name != 'key_info.db':
database_paths.append(str(db_file))
logging.info(f"在指定路径找到 {len(database_paths)} 个数据库文件")
else:
return {
"status": "error",
"message": f"指定的数据库路径不存在: {db_storage_path}",
"total_databases": 0,
"successful_count": 0,
"failed_count": 0,
"output_directory": str(output_dir.absolute()),
"processed_files": [],
"failed_files": []
}
else:
# 使用检测函数获取数据库列表
try:
from .wechat_detection import detect_wechat_installation
wechat_info = detect_wechat_installation()
if wechat_info and wechat_info.get('databases'):
database_paths = [db['path'] for db in wechat_info['databases']]
logging.info(f"通过检测函数找到 {len(database_paths)} 个数据库文件")
else:
database_paths = []
logging.warning("检测函数未找到数据库文件")
except Exception as e:
logging.error(f"检测函数调用失败: {e}")
database_paths = []
if not database_paths:
return {
"status": "error",
"message": "未找到微信数据库文件请确保微信已安装并有数据或提供正确的db_storage路径",
"total_databases": 0,
"successful_count": 0,
"failed_count": 0,
"output_directory": str(output_dir.absolute()),
"processed_files": [],
"failed_files": []
}
# 创建解密器
try:
decryptor = WeChatDatabaseDecryptor(decrypt_key)
logging.info("解密器初始化成功")
except ValueError as e:
return {
"status": "error",
"message": f"密钥错误: {e}",
"total_databases": len(database_paths),
"successful_count": 0,
"failed_count": 0,
"output_directory": str(output_dir.absolute()),
"processed_files": [],
"failed_files": []
}
# 批量解密
success_count = 0
total_count = len(database_paths)
processed_files = []
failed_files = []
for db_path in database_paths:
# 生成输出文件名
db_name = os.path.basename(db_path)
output_path = output_dir / f"decrypted_{db_name}"
# 解密数据库
if decryptor.decrypt_database(db_path, str(output_path)):
success_count += 1
processed_files.append(str(output_path))
else:
failed_files.append(db_path)
logging.error(f"解密失败: {db_path}")
# 返回结果
result = {
"status": "success" if success_count > 0 else "error",
"message": f"解密完成: 成功 {success_count}/{total_count}",
"total_databases": total_count,
"successful_count": success_count,
"failed_count": total_count - success_count,
"output_directory": str(output_dir.absolute()),
"processed_files": processed_files,
"failed_files": failed_files
}
logging.info("=" * 60)
logging.info("解密任务完成!")
logging.info(f"成功: {success_count}/{total_count}")
logging.info(f"失败: {total_count - success_count}/{total_count}")
logging.info(f"输出目录: {output_dir.absolute()}")
logging.info("=" * 60)
return result
def main():
"""主函数 - 保持向后兼容"""
result = decrypt_wechat_databases()
if result["status"] == "error":
print(f"错误: {result['message']}")
else:
print(f"解密完成: {result['message']}")
print(f"输出目录: {result['output_directory']}")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,447 @@
"""微信数据库检测模块
提供微信安装检测和数据库发现功能。
基于PyWxDump的检测逻辑。
"""
import os
import re
import psutil
import ctypes
from pathlib import Path
from typing import List, Dict, Any, Union
from ctypes import wintypes
def get_wx_db(msg_dir: str = None,
db_types: Union[List[str], str] = None,
wxids: Union[List[str], str] = None) -> List[dict]:
r"""
获取微信数据库路径基于PyWxDump逻辑
:param msg_dir: 微信数据库目录 eg: C:\Users\user\Documents\WeChat Files 非wxid目录
:param db_types: 需要获取的数据库类型,如果为空,则获取所有数据库
:param wxids: 微信id列表,如果为空,则获取所有wxid下的数据库
:return: [{"wxid": wxid, "db_type": db_type, "db_path": db_path, "wxid_dir": wxid_dir}, ...]
"""
result = []
if not msg_dir or not os.path.exists(msg_dir):
print(f"[-] 微信文件目录不存在: {msg_dir}, 将使用默认路径")
msg_dir = get_wx_dir_by_reg()
if not os.path.exists(msg_dir):
print(f"[-] 目录不存在: {msg_dir}")
return result
wxids = wxids.split(";") if isinstance(wxids, str) else wxids
if not isinstance(wxids, list) or len(wxids) <= 0:
wxids = None
db_types = db_types.split(";") if isinstance(db_types, str) and db_types else db_types
if not isinstance(db_types, list) or len(db_types) <= 0:
db_types = None
wxid_dirs = {} # wx用户目录
if wxids or "All Users" in os.listdir(msg_dir) or "Applet" in os.listdir(msg_dir) or "WMPF" in os.listdir(msg_dir):
for sub_dir in os.listdir(msg_dir):
if os.path.isdir(os.path.join(msg_dir, sub_dir)) and sub_dir not in ["All Users", "Applet", "WMPF"]:
wxid_dirs[os.path.basename(sub_dir)] = os.path.join(msg_dir, sub_dir)
else:
wxid_dirs[os.path.basename(msg_dir)] = msg_dir
for wxid, wxid_dir in wxid_dirs.items():
if wxids and wxid not in wxids: # 如果指定wxid,则过滤掉其他wxid
continue
for root, dirs, files in os.walk(wxid_dir):
# 只处理db_storage目录下的数据库文件
if "db_storage" not in root:
continue
for file_name in files:
if not file_name.endswith(".db"):
continue
# 排除不需要解密的数据库
if file_name in ["key_info.db"]:
continue
db_type = re.sub(r"\d*\.db$", "", file_name)
if db_types and db_type not in db_types: # 如果指定db_type,则过滤掉其他db_type
continue
db_path = os.path.join(root, file_name)
result.append({"wxid": wxid, "db_type": db_type, "db_path": db_path, "wxid_dir": wxid_dir})
return result
# Windows API 常量和结构
PROCESS_QUERY_INFORMATION = 0x0400
PROCESS_VM_READ = 0x0010
MAX_PATH = 260
TH32CS_SNAPPROCESS = 0x00000002
# Windows API 函数
kernel32 = ctypes.windll.kernel32
psapi = ctypes.windll.psapi
OpenProcess = kernel32.OpenProcess
CloseHandle = kernel32.CloseHandle
GetModuleFileNameExW = psapi.GetModuleFileNameExW
CreateToolhelp32Snapshot = kernel32.CreateToolhelp32Snapshot
Process32FirstW = kernel32.Process32FirstW
Process32NextW = kernel32.Process32NextW
class PROCESSENTRY32W(ctypes.Structure):
_fields_ = [
('dwSize', wintypes.DWORD),
('cntUsage', wintypes.DWORD),
('th32ProcessID', wintypes.DWORD),
('th32DefaultHeapID', ctypes.POINTER(wintypes.ULONG)),
('th32ModuleID', wintypes.DWORD),
('cntThreads', wintypes.DWORD),
('th32ParentProcessID', wintypes.DWORD),
('pcPriClassBase', wintypes.LONG),
('dwFlags', wintypes.DWORD),
('szExeFile', wintypes.WCHAR * MAX_PATH)
]
# 删除了WeChatDecryptor类解密功能已移至独立的wechat_decrypt.py脚本
def find_wechat_databases() -> List[str]:
"""在新的xwechat_files目录中查找微信数据库文件
返回值:
数据库文件路径列表
"""
db_files = []
# 获取用户的Documents目录
documents_dir = Path.home() / "Documents"
# 检查新的微信4.0+目录结构
wechat_dirs = [
documents_dir / "xwechat_files", # 新版微信4.0+
documents_dir / "WeChat Files" # 旧版微信
]
for wechat_dir in wechat_dirs:
if not wechat_dir.exists():
continue
# 查找用户目录wxid_*模式)
for user_dir in wechat_dir.iterdir():
if not user_dir.is_dir():
continue
# 跳过系统目录
if user_dir.name in ['All Users', 'Applet', 'WMPF']:
continue
# 查找Msg目录
msg_dir = user_dir / "Msg"
if msg_dir.exists():
# 查找数据库文件
for db_file in msg_dir.glob("*.db"):
if db_file.is_file():
db_files.append(str(db_file))
# 同时检查Multi目录
multi_dir = msg_dir / "Multi"
if multi_dir.exists():
for db_file in multi_dir.glob("*.db"):
if db_file.is_file():
db_files.append(str(db_file))
return db_files
def get_process_exe_path(process_id):
"""获取进程可执行文件路径"""
h_process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, False, process_id)
if not h_process:
return None
exe_path = ctypes.create_unicode_buffer(MAX_PATH)
if GetModuleFileNameExW(h_process, None, exe_path, MAX_PATH) > 0:
CloseHandle(h_process)
return exe_path.value
else:
CloseHandle(h_process)
return None
def get_process_list():
"""获取系统进程列表"""
h_process_snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
if h_process_snap == ctypes.wintypes.HANDLE(-1).value:
return []
pe32 = PROCESSENTRY32W()
pe32.dwSize = ctypes.sizeof(PROCESSENTRY32W)
process_list = []
if not Process32FirstW(h_process_snap, ctypes.byref(pe32)):
CloseHandle(h_process_snap)
return []
while True:
process_list.append((pe32.th32ProcessID, pe32.szExeFile))
if not Process32NextW(h_process_snap, ctypes.byref(pe32)):
break
CloseHandle(h_process_snap)
return process_list
def auto_detect_wechat_data_dirs():
"""
自动检测微信数据目录 - 多策略组合检测
:return: 检测到的微信数据目录列表
"""
detected_dirs = []
# 策略1注册表检测已移除
# 策略2和策略3注册表相关检测已移除
# 策略1常见驱动器扫描微信相关目录
common_wechat_patterns = [
"WeChat Files", "wechat_files", "xwechat_files", "wechatMSG",
"WeChat", "微信", "Weixin", "wechat"
]
# 扫描常见驱动器
drives = ['C:', 'D:', 'E:', 'F:']
for drive in drives:
if not os.path.exists(drive):
continue
try:
# 扫描驱动器根目录和常见目录
scan_paths = [
drive + os.sep,
os.path.join(drive + os.sep, "Users"),
]
for scan_path in scan_paths:
if not os.path.exists(scan_path):
continue
try:
for item in os.listdir(scan_path):
item_path = os.path.join(scan_path, item)
if not os.path.isdir(item_path):
continue
# 检查是否匹配微信目录模式
for pattern in common_wechat_patterns:
if pattern.lower() in item.lower():
# 检查是否包含wxid目录
if has_wxid_directories(item_path):
if item_path not in detected_dirs:
detected_dirs.append(item_path)
print(f"[DEBUG] 目录扫描检测成功: {item_path}")
break
except (PermissionError, OSError):
continue
except (PermissionError, OSError):
continue
# 策略2进程内存分析简化版
try:
process_list = get_process_list()
for pid, process_name in process_list:
if process_name.lower() in ['weixin.exe', 'wechat.exe']:
# 尝试获取进程的工作目录
try:
import psutil
proc = psutil.Process(pid)
cwd = proc.cwd()
# 从进程工作目录向上查找可能的数据目录
parent_dirs = [cwd]
current = cwd
for _ in range(3): # 向上查找3级目录
parent = os.path.dirname(current)
if parent != current:
parent_dirs.append(parent)
current = parent
else:
break
for parent_dir in parent_dirs:
for pattern in common_wechat_patterns:
potential_dir = os.path.join(parent_dir, pattern)
if os.path.exists(potential_dir) and has_wxid_directories(potential_dir):
if potential_dir not in detected_dirs:
detected_dirs.append(potential_dir)
print(f"[DEBUG] 进程分析检测成功: {potential_dir}")
except:
pass
except:
pass
return detected_dirs
# 删除了所有解密相关函数解密功能已移至独立的wechat_decrypt.py脚本
def has_wxid_directories(directory):
"""
检查目录是否包含wxid格式的子目录
:param directory: 要检查的目录
:return: 是否包含wxid目录
"""
try:
for item in os.listdir(directory):
item_path = os.path.join(directory, item)
if os.path.isdir(item_path) and (item.startswith('wxid_') or len(item) > 10):
# 进一步检查是否包含数据库文件
for root, _, files in os.walk(item_path):
for file in files:
if file.endswith('.db'):
return True
return False
except:
return False
def get_wx_dir_by_reg(wxid="all"):
"""
通过多种方法获取微信目录 - 改进的自动检测
:param wxid: 微信id如果为"all"则返回WeChat Files目录否则返回具体wxid目录
:return: 微信目录路径
"""
if not wxid:
return None
# 使用新的自动检测方法
detected_dirs = auto_detect_wechat_data_dirs()
if not detected_dirs:
print(f"[DEBUG] 未检测到任何微信数据目录")
return None
# 返回第一个检测到的目录
wx_dir = detected_dirs[0]
print(f"[DEBUG] 使用检测到的微信目录: {wx_dir}")
# 如果指定了具体的wxid返回wxid目录
if wxid and wxid != "all":
wxid_dir = os.path.join(wx_dir, wxid)
return wxid_dir if os.path.exists(wxid_dir) else None
return wx_dir if os.path.exists(wx_dir) else None
def detect_wechat_installation() -> Dict[str, Any]:
"""
检测微信安装情况 - 完全按照PyWxDump的逻辑实现
"""
result = {
"wechat_version": None,
"wechat_install_path": None,
"wechat_exe_path": None,
"wechat_data_dirs": [],
"message_dirs": [],
"databases": [],
"version_detected": None,
"is_running": False,
"user_accounts": [],
"detection_errors": [],
"detection_methods": []
}
# 进程检测 - 只检测Weixin.exe按照用户要求
result["detection_methods"].append("进程检测")
process_list = get_process_list()
for pid, process_name in process_list:
# 只检查Weixin.exe进程
if process_name.lower() == 'weixin.exe':
try:
exe_path = get_process_exe_path(pid)
if exe_path:
result["wechat_exe_path"] = exe_path
result["wechat_install_path"] = os.path.dirname(exe_path)
result["is_running"] = True
result["detection_methods"].append(f"检测到微信进程: {process_name} (PID: {pid})")
# 尝试获取版本信息
try:
import win32api
version_info = win32api.GetFileVersionInfo(exe_path, "\\")
version = f"{version_info['FileVersionMS'] >> 16}.{version_info['FileVersionMS'] & 0xFFFF}.{version_info['FileVersionLS'] >> 16}.{version_info['FileVersionLS'] & 0xFFFF}"
result["wechat_version"] = version
result["detection_methods"].append(f"获取到微信版本: {version}")
except ImportError:
result["detection_errors"].append("win32api库未安装无法获取版本信息")
except Exception as e:
result["detection_errors"].append(f"版本获取失败: {e}")
break
except Exception as e:
result["detection_errors"].append(f"进程信息获取失败: {e}")
if not result["is_running"]:
result["detection_methods"].append("未检测到微信进程")
# 2. 使用自动检测逻辑获取微信目录和数据库
result["detection_methods"].append("目录自动检测")
try:
wx_dir = get_wx_dir_by_reg()
if wx_dir and os.path.exists(wx_dir):
result["wechat_data_dirs"].append(wx_dir)
result["detection_methods"].append(f"通过自动检测找到微信目录: {wx_dir}")
# 使用PyWxDump的get_wx_db函数获取数据库信息
db_list = get_wx_db(msg_dir=wx_dir) # 移除db_types限制获取所有.db文件
# 统计用户账户和消息目录
user_accounts_set = set()
message_dirs_set = set()
for db_info in db_list:
wxid = db_info["wxid"]
wxid_dir = db_info["wxid_dir"]
db_path = db_info["db_path"]
db_type = db_info["db_type"]
# 添加用户账户
user_accounts_set.add(wxid)
message_dirs_set.add(wxid_dir)
# 添加数据库信息
if os.path.exists(db_path):
result["databases"].append({
"path": db_path,
"name": os.path.basename(db_path),
"type": db_type,
"size": os.path.getsize(db_path),
"user": wxid,
"user_dir": wxid_dir
})
# 转换为列表
result["user_accounts"] = list(user_accounts_set)
result["message_dirs"] = list(message_dirs_set)
result["detection_methods"].append(f"检测到 {len(result['user_accounts'])} 个用户账户")
result["detection_methods"].append(f"检测到 {len(result['databases'])} 个数据库文件")
# 按数据库类型统计
db_type_count = {}
for db in result["databases"]:
db_type = db["type"]
db_type_count[db_type] = db_type_count.get(db_type, 0) + 1
if db_type_count:
type_summary = ", ".join([f"{k}({v})" for k, v in db_type_count.items()])
result["detection_methods"].append(f"数据库类型分布: {type_summary}")
else:
result["detection_methods"].append("自动检测未找到微信目录")
except Exception as e:
result["detection_errors"].append(f"目录检测失败: {str(e)}")
return result
def get_wechat_info() -> Dict[str, Any]:
"""获取微信安装和数据库信息
返回值:
包含微信信息的字典
"""
return detect_wechat_installation()