From 9dfcaf5d0d5aef9301b3e955c10994a69a5563ad Mon Sep 17 00:00:00 2001 From: xaoyaoo Date: Sat, 18 May 2024 16:35:54 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pywxdump/wx_info/get_wx_info.py | 25 +++++++++++++++++++++++++ pywxdump/wx_info/utils.py | 27 +++++++++++++++++---------- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/pywxdump/wx_info/get_wx_info.py b/pywxdump/wx_info/get_wx_info.py index b5da03f..2d58d7f 100644 --- a/pywxdump/wx_info/get_wx_info.py +++ b/pywxdump/wx_info/get_wx_info.py @@ -39,6 +39,7 @@ def get_info_string(h_process, address, n_size=64): return text.strip() if text.strip() != "" else "None" +# 读取内存中的字符串(昵称部分name) def get_info_name(h_process, address, address_len=8, n_size=64): array = ctypes.create_string_buffer(n_size) if ReadProcessMemory(h_process, void_p(address), array, n_size, 0) == 0: return "None" @@ -51,6 +52,7 @@ def get_info_name(h_process, address, address_len=8, n_size=64): return text.strip() if text.strip() != "" else "None" +# 读取内存中的wxid def get_info_wxid(h_process): find_num = 100 addrs = pattern_scan_all(h_process, br'\\Msg\\FTSContact', return_multiple=True, find_num=find_num) @@ -66,6 +68,7 @@ def get_info_wxid(h_process): return wxid +# 读取内存中的filePath基于wxid(慢) def get_info_filePath_base_wxid(h_process, wxid=""): find_num = 10 addrs = pattern_scan_all(h_process, wxid.encode() + br'\\Msg\\FTSContact', return_multiple=True, find_num=find_num) @@ -82,6 +85,11 @@ def get_info_filePath_base_wxid(h_process, wxid=""): def get_info_filePath(wxid="all"): + """ + # 读取filePath (微信文件路径) (快) + :param wxid: 微信id + :return: 返回filePath + """ if not wxid: return "None" w_dir = "MyDocument:" @@ -135,6 +143,14 @@ def get_info_filePath(wxid="all"): def get_key(pid, db_path, addr_len): + """ + 获取key (慢) + :param pid: 进程id + :param db_path: 微信数据库路径 + :param addr_len: 地址长度 + :return: 返回key + """ + def read_key_bytes(h_process, address, address_len=8): array = ctypes.create_string_buffer(address_len) if ReadProcessMemory(h_process, void_p(address), array, address_len, 0) == 0: return "None" @@ -179,6 +195,15 @@ def get_key(pid, db_path, addr_len): # 读取微信信息(account,mobile,name,mail,wxid,key) def read_info(version_list: dict = None, is_logging: bool = False, save_path: str = None): + """ + 读取微信信息(account,mobile,name,mail,wxid,key) + :param version_list: 版本偏移量 + :param is_logging: 是否打印日志 + :param save_path: 保存路径 + :return: 返回微信信息 [{"pid": pid, "version": version, "account": account, + "mobile": mobile, "name": name, "mail": mail, "wxid": wxid, + "key": key, "filePath": filePath}, ...] + """ if version_list is None: version_list = {} diff --git a/pywxdump/wx_info/utils.py b/pywxdump/wx_info/utils.py index 57b50ee..ef54df9 100644 --- a/pywxdump/wx_info/utils.py +++ b/pywxdump/wx_info/utils.py @@ -7,28 +7,28 @@ # ------------------------------------------------------------------------------- import re import sys - -import pymem -from win32com.client import Dispatch import hmac +import pymem import hashlib +from win32com.client import Dispatch def verify_key(key, wx_db_path): + """ + 验证key是否正确 + """ KEY_SIZE = 32 DEFAULT_PAGESIZE = 4096 DEFAULT_ITER = 64000 with open(wx_db_path, "rb") as file: blist = file.read(5000) salt = blist[:16] - byteKey = hashlib.pbkdf2_hmac("sha1", key, salt, DEFAULT_ITER, KEY_SIZE) + pk = hashlib.pbkdf2_hmac("sha1", key, salt, DEFAULT_ITER, KEY_SIZE) first = blist[16:DEFAULT_PAGESIZE] - mac_salt = bytes([(salt[i] ^ 58) for i in range(16)]) - mac_key = hashlib.pbkdf2_hmac("sha1", byteKey, mac_salt, 2, KEY_SIZE) - hash_mac = hmac.new(mac_key, first[:-32], hashlib.sha1) + pk = hashlib.pbkdf2_hmac("sha1", pk, mac_salt, 2, KEY_SIZE) + hash_mac = hmac.new(pk, first[:-32], hashlib.sha1) hash_mac.update(b'\x01\x00\x00\x00') - if hash_mac.digest() != first[-32:-12]: return False return True @@ -54,10 +54,10 @@ def find_all(c: bytes, string: bytes, base_addr=0): return [base_addr + m.start() for m in re.finditer(re.escape(c), string)] -# 获取exe文件的位数 def get_exe_bit(file_path): """ - 获取 PE 文件的位数: 32 位或 64 位 + # 获取exe文件的位数 + PE 文件的位数: 32 位或 64 位 :param file_path: PE 文件路径(可执行文件) :return: 如果遇到错误则返回 64 """ @@ -90,6 +90,13 @@ def get_exe_bit(file_path): def pattern_scan_all(handle, pattern, *, return_multiple=False, find_num=100): + """ + 扫描内存中所有匹配的模式 + :param handle: 进程句柄 + :param pattern: 模式 + :param return_multiple: 是否返回所有匹配 + :param find_num: 最多查找数量 + """ next_region = 0 found = [] user_space_limit = 0x7FFFFFFF0000 if sys.maxsize > 2 ** 32 else 0x7fff0000