获取key基址偏移可以根据微信文件夹获取,不需要输入key

This commit is contained in:
xaoyo 2023-10-09 11:30:51 +08:00
parent 2fc599a8f6
commit d2b31f0120
2 changed files with 120 additions and 23 deletions

View File

@ -7,25 +7,47 @@
# -------------------------------------------------------------------------------
import argparse
import ctypes
import hashlib
import json
import multiprocessing
import os
import re
import time
import winreg
import threading
import psutil
import win32api
from pymem import Pymem
import pymem
import hmac
ReadProcessMemory = ctypes.windll.kernel32.ReadProcessMemory
void_p = ctypes.c_void_p
KEY_SIZE = 32
DEFAULT_PAGESIZE = 4096
DEFAULT_ITER = 64000
def validate_key(key, salt, first, mac_salt):
byteKey = hashlib.pbkdf2_hmac("sha1", key, salt, DEFAULT_ITER, KEY_SIZE)
mac_key = hashlib.pbkdf2_hmac("sha1", byteKey, mac_salt, 2, KEY_SIZE)
hash_mac = hmac.new(mac_key, first[:-32], hashlib.sha1)
hash_mac.update(b'\x01\x00\x00\x00')
if hash_mac.digest() == first[-32:-12]:
return True
else:
return False
class BaseAddr:
def __init__(self, account, mobile, name, key):
def __init__(self, account, mobile, name, key, db_path):
self.account = account.encode("utf-8")
self.mobile = mobile.encode("utf-8")
self.name = name.encode("utf-8")
self.key = bytes.fromhex(key)
self.key = bytes.fromhex(key) if key else b""
self.db_path = db_path if db_path else ""
self.process_name = "WeChat.exe"
self.module_name = "WeChatWin.dll"
@ -66,22 +88,20 @@ class BaseAddr:
pid = self.pm.process_id
# print(self.pm.process_base.lpBaseOfDll, self.pm.process_base.SizeOfImage)
batch = 4096
module_start_addr = 34199871460642
module_end_addr = 0
for process in psutil.process_iter(['name', 'exe', 'pid', 'cmdline']):
if process.name() == self.process_name:
for module in process.memory_maps(grouped=False):
if "WeChat" in module.path:
start_addr = int(module.addr, 16)
end_addr = start_addr + module.rss
process = psutil.Process(pid)
for module in process.memory_maps(grouped=False):
if "WeChat" in module.path:
start_addr = int(module.addr, 16)
end_addr = start_addr + module.rss
if module_start_addr > start_addr:
module_start_addr = start_addr
if module_end_addr < end_addr:
module_end_addr = end_addr
if module_start_addr > start_addr:
module_start_addr = start_addr
if module_end_addr < end_addr:
module_end_addr = end_addr
batch = 4096
Handle = ctypes.windll.kernel32.OpenProcess(0x1F0FFF, False, pid)
array = ctypes.create_string_buffer(batch)
key_addr = 0
@ -93,19 +113,91 @@ class BaseAddr:
if len(key_addr) > 0:
key_addr = key_addr[0]
break
# print(key_addr)
# print(hex(key_addr))
key = key_addr.to_bytes(8, byteorder='little')
# print(key.hex())
result = self.search_memory_value(key, self.module_name)
return result
def get_key_bias(self, wx_db_path):
wx_db_path = os.path.join(wx_db_path, "Msg", "MicroMsg.db")
if not os.path.exists(wx_db_path):
return False
module_name = "WeChatWin.dll"
pm = self.pm
module = pymem.process.module_from_name(pm.process_handle, module_name)
start_addr = module.lpBaseOfDll
size = module.SizeOfImage
mem_data = pm.read_bytes(start_addr, size)
min_addr = 0xffffffffffffffffffffffff
max_addr = 0
for module1 in pm.list_modules():
if module1.lpBaseOfDll < min_addr:
min_addr = module1.lpBaseOfDll
if module1.lpBaseOfDll > max_addr:
max_addr = module1.lpBaseOfDll
def read_key(addr):
key = ctypes.create_string_buffer(35)
if ReadProcessMemory(pm.process_handle, void_p(addr - 1), key, 35, 0) == 0:
return b""
if b"\x00\x00" in key.raw[1:33]:
return b""
if b"\x00\x00" == key.raw[33:35] and b"\x90" == key.raw[0:1]:
return key.raw[1:33]
return b""
def get_maybe_key(mem_data):
maybe_key = []
for i in range(0, len(mem_data), 8):
addr = mem_data[i:i + 8]
addr = int.from_bytes(addr, byteorder='little')
# 去掉不可能的地址
if min_addr < addr < max_addr:
key = read_key(addr)
if key == b"":
continue
maybe_key.append([key, i])
return maybe_key
def verify_key(keys, wx_db_path):
with open(wx_db_path, "rb") as file:
blist = file.read(5000)
salt = blist[:16]
first = blist[16:DEFAULT_PAGESIZE]
mac_salt = bytes([(salt[i] ^ 58) for i in range(16)])
with multiprocessing.Pool(processes=8) as pool:
results = [pool.apply_async(validate_key, args=(key, salt, first, mac_salt)) for key, i in keys[-1::-1]]
results = [p.get() for p in results]
for i, result in enumerate(results[-1::-1]):
if result:
return keys[i]
return b"", 0
maybe_key = get_maybe_key(mem_data)
key, bais = verify_key(maybe_key, wx_db_path)
return bais
def run(self):
self.version = self.get_file_version(self.process_name)
if not self.islogin:
return "[-] WeChat No Run"
key_bias = self.search_key(self.key)
mobile_bias = self.search_memory_value(self.mobile)
name_bias = self.search_memory_value(self.name)
account_bias = self.search_memory_value(self.account)
if self.key:
key_bias = self.search_key(self.key)
elif self.db_path:
key_bias = self.get_key_bias(self.db_path)
else:
key_bias = 0
return {self.version: [name_bias, account_bias, mobile_bias, 0, key_bias]}
@ -116,24 +208,25 @@ if __name__ == '__main__':
parser.add_argument("--name", type=str, help="微信昵称")
parser.add_argument("--account", type=str, help="微信账号")
parser.add_argument("--key", type=str, help="密钥")
parser.add_argument("--db_path", type=str, help="加密数据库路径(登录的微信文件夹路径)")
# 解析命令行参数
args = parser.parse_args()
# 检查是否缺少必要参数,并抛出错误
if not args.mobile or not args.name or not args.account or not args.key:
raise ValueError("缺少必要的命令行参数!请提供手机号、微信昵称、微信账号和密钥。")
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
account = args.account
key = args.key
db_path = args.db_path
# 调用 run 函数,并传入参数
# rdata = run(mobile, name, account, key)
# print(rdata)
rdata = BaseAddr(account, mobile, name, key).run()
rdata = BaseAddr(account, mobile, name, key, db_path).run()
print(rdata)

View File

@ -1,6 +1,7 @@
# <center>PyWxDump</center>
* 更新日志(如果有[version_list.json](./Program/version_list.json)缺少的版本,请帮忙添加。)
* 2023.10.09 获取key基址偏移可以根据微信文件夹获取不需要输入key
* 2023.10.09 优化代码,删减没必要代码,重新修改获取基址代码,加快运行速度(需要安装新的库 pymem
* 2023.10.07 修改获取基址内存搜索方式,防止进入死循环
* 2023.10.07 增加了3.9.7.29版本的偏移地址
@ -113,7 +114,10 @@ print(data)
**3.1 通过python脚本获取**
```shell
python get_base_addr.py --mobile 152******** --name ****** --account ****** --key **********************************************
python get_base_addr.py --mobile 152***** --name **** --account *** --key ********** --db_path "****\WeChat Files\wxid_******"
```
# mobile、name、account为必填参数, key、db_path二者必填其一使用key时执行速度快db_path时执行速度慢大约需要10s-60s也可能更长
# return{'3.9.7.29': [63486984, 63488320, 63486792, 0, 63488256]}
# (十进制)按顺序代表微信昵称、微信账号、微信手机号、微信邮箱默认0、微信KEY