From fbc4086e07c75acbc3a5fabd20f6aac8a88d5c20 Mon Sep 17 00:00:00 2001 From: xaoyo Date: Tue, 31 Oct 2023 18:04:04 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D3.9.2.*=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E6=AD=A3=E5=B8=B8=E8=BF=90=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pywxdump/bias_addr/get_bias_addr.py | 39 +++++++++++------ pywxdump/command.py | 5 ++- pywxdump/version_list.json | 4 +- pywxdump/wx_info/get_wx_info.py | 67 +++++++++++++++++++---------- setup.py | 2 +- 5 files changed, 75 insertions(+), 42 deletions(-) diff --git a/pywxdump/bias_addr/get_bias_addr.py b/pywxdump/bias_addr/get_bias_addr.py index 6dabfe6..e8b33f1 100644 --- a/pywxdump/bias_addr/get_bias_addr.py +++ b/pywxdump/bias_addr/get_bias_addr.py @@ -57,9 +57,18 @@ class BiasAddr: self.pm = Pymem("WeChat.exe") self.bits = self.get_osbits() + self.version = self.get_file_version(self.process_name) + self.address_len = self.get_addr_len() self.islogin = True + def get_addr_len(self): + version_nums = list(map(int, self.version.split("."))) # 将版本号拆分为数字列表 + if version_nums[0] <= 3 and version_nums[1] <= 9 and version_nums[2] <= 2: + return 4 + else: + return 8 + def find_all(self, c: bytes, string: bytes, base_addr=0): """ 查找字符串中所有子串的位置 @@ -92,14 +101,15 @@ class BiasAddr: return result def search_key(self, key: bytes): - byteLen = 4 if self.bits == 32 else 8 # 4字节或8字节 + byteLen = self.address_len # if self.bits == 32 else 8 # 4字节或8字节 + key = re.escape(key) # 转义特殊字符 key_addr = self.pm.pattern_scan_all(key, return_multiple=True)[-1] if len(key) > 0 else 0 key = key_addr.to_bytes(byteLen, byteorder='little', signed=True) result = self.search_memory_value(key, self.module_name) return result def get_key_bias_test(self): - byteLen = 4 if self.bits == 32 else 8 # 4字节或8字节 + byteLen = self.address_len # 4 if self.bits == 32 else 8 # 4字节或8字节 keyLenOffset = 0x8c if self.bits == 32 else 0xd0 keyWindllOffset = 0x90 if self.bits == 32 else 0xd8 @@ -129,7 +139,7 @@ class BiasAddr: return keyWinAddr - module.lpBaseOfDll def get_wxid_bias(self): - byteLen = 4 if self.bits == 32 else 8 # 4字节或8字节 + byteLen = self.address_len # 4 if self.bits == 32 else 8 # 4字节或8字节 keyLenOffset = 0x8c if self.bits == 32 else 0xd0 keyWindllOffset = 0x90 if self.bits == 32 else 0xd8 @@ -178,8 +188,8 @@ class BiasAddr: def get_maybe_key(mem_data): maybe_key = [] - for i in range(0, len(mem_data), 8): - addr = mem_data[i:i + 8] + for i in range(0, len(mem_data), self.address_len): + addr = mem_data[i:i + self.address_len] addr = int.from_bytes(addr, byteorder='little') # 去掉不可能的地址 if min_addr < addr < max_addr: @@ -226,7 +236,7 @@ class BiasAddr: maybe_key = [] for i in [0x24, 0x40]: addr = start_addr + account_bias - i - mem_data = pm.read_bytes(addr, 8) + mem_data = pm.read_bytes(addr, self.address_len) key = read_key(int.from_bytes(mem_data, byteorder='little')) if key != b"": maybe_key.append([key, addr - start_addr]) @@ -256,15 +266,16 @@ class BiasAddr: account_bias = self.search_memory_value(self.account) # version_bias = self.search_memory_value(self.version.encode("utf-8")) - try: - key_bias = self.get_key_bias_test() - except: - key_bias = 0 try: wxid_bias = self.get_wxid_bias() except: wxid_bias = 0 + try: + key_bias = self.get_key_bias_test() + except: + key_bias = 0 + if key_bias <= 0: if self.key: key_bias = self.search_key(self.key) @@ -281,8 +292,8 @@ if __name__ == '__main__': parser.add_argument("--mobile", type=str, help="手机号", required=True) parser.add_argument("--name", type=str, help="微信昵称", required=True) parser.add_argument("--account", type=str, help="微信账号", required=True) - parser.add_argument("--key", type=str, help="密钥") - parser.add_argument("--db_path", type=str, help="微信文件夹(已经登录微信)路径") + parser.add_argument("--key", type=str, help="(可选)密钥") + parser.add_argument("--db_path", type=str, help="(可选)已登录账号的微信文件夹路径") # 解析命令行参数 args = parser.parse_args() @@ -290,8 +301,7 @@ if __name__ == '__main__': # 检查是否缺少必要参数,并抛出错误 if not args.mobile or not args.name or not args.account: raise ValueError("缺少必要的命令行参数!请提供手机号、微信昵称、微信账号。") - if not args.key and not args.db_path: - raise ValueError("缺少必要的命令行参数!请提供密钥或微信文件夹(已经登录微信)路径。") + # 从命令行参数获取值 mobile = args.mobile name = args.name @@ -301,6 +311,7 @@ if __name__ == '__main__': # 调用 run 函数,并传入参数 rdata = BiasAddr(account, mobile, name, key, db_path).run() + print("{版本:昵称,账号,手机号,邮箱,KEY,原始ID(wxid_******)}") print(rdata) # 添加到version_list.json diff --git a/pywxdump/command.py b/pywxdump/command.py index 61cd730..108ca01 100644 --- a/pywxdump/command.py +++ b/pywxdump/command.py @@ -22,8 +22,8 @@ class MainBiasAddr(): 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="(与db_path二选一)密钥") - sb_bias_addr.add_argument("--db_path", type=str, help="(与key二选一)已登录账号的微信文件夹路径") + 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", type=str, help="(可选)微信版本偏移文件路径,如有,则自动更新", default=None) self.sb_bias_addr = sb_bias_addr @@ -43,6 +43,7 @@ class MainBiasAddr(): vlp = args.vlp # 调用 run 函数,并传入参数 rdata = BiasAddr(account, mobile, name, key, db_path).run() + print("{版本:微信昵称,微信账号,微信手机号,微信邮箱,微信KEY,微信原始ID(wxid_******)}") print(rdata) if vlp is not None: diff --git a/pywxdump/version_list.json b/pywxdump/version_list.json index 0e05bb0..e72eda9 100644 --- a/pywxdump/version_list.json +++ b/pywxdump/version_list.json @@ -309,7 +309,7 @@ 50320640, 38986104, 50321676, - 0 + 50592864 ], "3.9.2.26": [ 50329040, @@ -372,7 +372,7 @@ 63488320, 63486792, 0, - 63488256, + 0, 63488352 ] } \ No newline at end of file diff --git a/pywxdump/wx_info/get_wx_info.py b/pywxdump/wx_info/get_wx_info.py index 151ceba..a44ce95 100644 --- a/pywxdump/wx_info/get_wx_info.py +++ b/pywxdump/wx_info/get_wx_info.py @@ -5,6 +5,7 @@ # Author: xaoyaoo # Date: 2023/08/21 # ------------------------------------------------------------------------------- +import argparse import json import ctypes from win32com.client import Dispatch @@ -23,18 +24,19 @@ def get_info_without_key(h_process, address, n_size=64): return text.strip() if text.strip() != "" else "None" -def get_info_wxid(h_process, address, n_size=32): - array = ctypes.create_string_buffer(8) - if ReadProcessMemory(h_process, void_p(address), array, 8, 0) == 0: return "None" +def get_info_wxid(h_process, address, n_size=32, address_len=8): + array = ctypes.create_string_buffer(address_len) + if ReadProcessMemory(h_process, void_p(address), array, address_len, 0) == 0: return "None" address = int.from_bytes(array, byteorder='little') # 逆序转换为int地址(key地址) wxid = get_info_without_key(h_process, address, n_size) + if not wxid.startswith("wxid_"): wxid = "None" return wxid # 读取内存中的key -def get_key(h_process, address): - array = ctypes.create_string_buffer(8) - if ReadProcessMemory(h_process, void_p(address), array, 8, 0) == 0: return "None" +def get_key(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" address = int.from_bytes(array, byteorder='little') # 逆序转换为int地址(key地址) key = ctypes.create_string_buffer(32) if ReadProcessMemory(h_process, void_p(address), key, 32, 0) == 0: return "None" @@ -60,8 +62,8 @@ def read_info(version_list): tmp_rd['pid'] = process.pid tmp_rd['version'] = Dispatch("Scripting.FileSystemObject").GetFileVersion(process.exe()) - support_list = version_list.get(tmp_rd['version'], None) - if not isinstance(support_list, list): + bias_list = version_list.get(tmp_rd['version'], None) + if not isinstance(bias_list, list): return f"[-] WeChat Current Version {tmp_rd['version']} Is Not Supported" wechat_base_address = 0 @@ -74,29 +76,48 @@ def read_info(version_list): Handle = ctypes.windll.kernel32.OpenProcess(0x1F0FFF, False, process.pid) - name_baseaddr = wechat_base_address + support_list[0] - account__baseaddr = wechat_base_address + support_list[1] - mobile_baseaddr = wechat_base_address + support_list[2] - mail_baseaddr = wechat_base_address + support_list[3] - key_baseaddr = wechat_base_address + support_list[4] - wxid_baseaddr = wechat_base_address + support_list[5] + name_baseaddr = wechat_base_address + bias_list[0] + account__baseaddr = wechat_base_address + bias_list[1] + mobile_baseaddr = wechat_base_address + bias_list[2] + mail_baseaddr = wechat_base_address + bias_list[3] + key_baseaddr = wechat_base_address + bias_list[4] + wxid_baseaddr = wechat_base_address + bias_list[5] - tmp_rd['account'] = get_info_without_key(Handle, account__baseaddr, 32) - tmp_rd['mobile'] = get_info_without_key(Handle, mobile_baseaddr, 64) - tmp_rd['name'] = get_info_without_key(Handle, name_baseaddr, 64) - tmp_rd['mail'] = get_info_without_key(Handle, mail_baseaddr, 64) if support_list[3] != 0 else "None" - tmp_rd['wxid'] = get_info_wxid(Handle, wxid_baseaddr, 24) if support_list[5] != 0 else "None" - if not tmp_rd['wxid'].startswith("wxid_"): tmp_rd['wxid'] = "None" - tmp_rd['key'] = get_key(Handle, key_baseaddr) + addrLen = 4 if tmp_rd['version'] in ["3.9.2.23", "3.9.2.26"] else 8 + + tmp_rd['account'] = get_info_without_key(Handle, account__baseaddr, 32) if bias_list[1] != 0 else "None" + tmp_rd['mobile'] = get_info_without_key(Handle, mobile_baseaddr, 64) if bias_list[2] != 0 else "None" + tmp_rd['name'] = get_info_without_key(Handle, name_baseaddr, 64) if bias_list[0] != 0 else "None" + tmp_rd['mail'] = get_info_without_key(Handle, mail_baseaddr, 64) if bias_list[3] != 0 else "None" + tmp_rd['wxid'] = get_info_wxid(Handle, wxid_baseaddr, 24, addrLen) if bias_list[5] != 0 else "None" + tmp_rd['key'] = get_key(Handle, key_baseaddr, addrLen) if bias_list[4] != 0 else "None" result.append(tmp_rd) return result if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--vlfile", type=str, help="手机号", required=False) + parser.add_argument("--vldict", type=str, help="微信昵称", required=False) + + args = parser.parse_args() + # 读取微信各版本偏移 - version_list = json.load(open("../version_list.json", "r", encoding="utf-8")) - result = read_info(version_list) # 读取微信信息 + if args.vlfile: + VERSION_LIST_PATH = args.vlfile + with open(VERSION_LIST_PATH, "r", encoding="utf-8") as f: + VERSION_LIST = json.load(f) + if args.vldict: + VERSION_LIST = json.loads(args.vldict) + + if not args.vlfile and not args.vldict: + VERSION_LIST_PATH = "../version_list.json" + + with open(VERSION_LIST_PATH, "r", encoding="utf-8") as f: + VERSION_LIST = json.load(f) + + result = read_info(VERSION_LIST) # 读取微信信息 print("=" * 32) if isinstance(result, str): # 输出报错 diff --git a/setup.py b/setup.py index 8faa8f8..fd2f081 100644 --- a/setup.py +++ b/setup.py @@ -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.1.7" +version = "2.1.9" setup( name="pywxdump", author="xaoyaoo",