加快wxinfo获取,速度再次提升40%

This commit is contained in:
xaoyaoo 2024-07-21 01:35:47 +08:00
parent 9e3e4cb5ae
commit d08ae98b26
3 changed files with 197 additions and 26 deletions

View File

@ -9,6 +9,27 @@ PROCESS_QUERY_INFORMATION = 0x0400
PROCESS_VM_READ = 0x0010
# MEMORY_BASIC_INFORMATION 结构体定义
class MEMORY_BASIC_INFORMATION(ctypes.Structure):
_fields_ = [
('BaseAddress', ctypes.wintypes.LPVOID),
('AllocationBase', ctypes.wintypes.LPVOID),
('AllocationProtect', ctypes.wintypes.DWORD),
('RegionSize', ctypes.c_size_t),
('State', ctypes.wintypes.DWORD),
('Protect', ctypes.wintypes.DWORD),
('Type', ctypes.wintypes.DWORD)
]
class MODULEINFO(ctypes.Structure):
_fields_ = [
("lpBaseOfDll", ctypes.c_void_p), # remote pointer
("SizeOfImage", ctypes.c_ulong),
("EntryPoint", ctypes.c_void_p), # remote pointer
]
# 定义PROCESSENTRY32结构
class PROCESSENTRY32(ctypes.Structure):
_fields_ = [("dwSize", ctypes.wintypes.DWORD),
@ -74,23 +95,15 @@ VerQueryValueW.argtypes = [ctypes.c_void_p, ctypes.wintypes.LPCWSTR, ctypes.POIN
ctypes.POINTER(ctypes.wintypes.UINT)]
VerQueryValueW.restype = ctypes.wintypes.BOOL
# 获取模块信息
GetModuleInformation = psapi.GetModuleInformation
GetModuleInformation.argtypes = [ctypes.wintypes.HANDLE, ctypes.wintypes.HMODULE, ctypes.POINTER(MODULEINFO),
ctypes.wintypes.DWORD]
GetModuleInformation.restype = ctypes.c_bool
# 读取进程内存
ReadProcessMemory = ctypes.windll.kernel32.ReadProcessMemory
# MEMORY_BASIC_INFORMATION 结构体定义
class MEMORY_BASIC_INFORMATION(ctypes.Structure):
_fields_ = [
('BaseAddress', ctypes.wintypes.LPVOID),
('AllocationBase', ctypes.wintypes.LPVOID),
('AllocationProtect', ctypes.wintypes.DWORD),
('RegionSize', ctypes.c_size_t),
('State', ctypes.wintypes.DWORD),
('Protect', ctypes.wintypes.DWORD),
('Type', ctypes.wintypes.DWORD)
]
# 定义VirtualQueryEx函数
VirtualQueryEx = kernel32.VirtualQueryEx
VirtualQueryEx.argtypes = [ctypes.wintypes.HANDLE, ctypes.wintypes.LPCVOID, ctypes.POINTER(MEMORY_BASIC_INFORMATION),
@ -139,6 +152,10 @@ def get_memory_maps(pid):
else:
file_name = None
# module_info = MODULEINFO()
# if GetModuleInformation(hProcess, mbi.BaseAddress, ctypes.byref(module_info), ctypes.sizeof(module_info)):
# file_name = get_file_version_info(module_info.lpBaseOfDll)
memory_maps.append({
'BaseAddress': mbi.BaseAddress,
'RegionSize': mbi.RegionSize,

View File

@ -14,8 +14,23 @@ import psutil
import pymem
from typing import List, Union
from .utils import pattern_scan_all, verify_key, get_exe_version, get_exe_bit, info_error
from .memory_search import search_memory
import ctypes.wintypes as wintypes
ReadProcessMemory = ctypes.windll.kernel32.ReadProcessMemory
# 定义常量
PROCESS_QUERY_INFORMATION = 0x0400
PROCESS_VM_READ = 0x0010
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
OpenProcess = kernel32.OpenProcess
OpenProcess.restype = wintypes.HANDLE
OpenProcess.argtypes = [wintypes.DWORD, wintypes.BOOL, wintypes.DWORD]
CloseHandle = kernel32.CloseHandle
CloseHandle.restype = wintypes.BOOL
CloseHandle.argtypes = [wintypes.HANDLE]
ReadProcessMemory = kernel32.ReadProcessMemory
void_p = ctypes.c_void_p
@ -59,7 +74,7 @@ def get_info_name(h_process, address, address_len=8, n_size=64):
@info_error
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)
addrs = search_memory(h_process, br'\\Msg\\FTSContact', max_num=find_num)
wxids = []
for addr in addrs:
array = ctypes.create_string_buffer(80)
@ -69,6 +84,7 @@ def get_info_wxid(h_process):
array = array.split(b"\\")[-1]
wxids.append(array.decode('utf-8', errors='ignore'))
wxid = max(wxids, key=wxids.count) if wxids else "None"
CloseHandle(h_process)
return wxid
@ -76,7 +92,7 @@ def get_info_wxid(h_process):
@info_error
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)
addrs = search_memory(h_process, wxid.encode() + br'\\Msg\\FTSContact', max_num=find_num)
filePath = []
for addr in addrs:
win_addr_len = 260
@ -86,6 +102,7 @@ def get_info_filePath_base_wxid(h_process, wxid=""):
array = array.split(b"\00")[-1]
filePath.append(array.decode('utf-8', errors='ignore'))
filePath = max(filePath, key=filePath.count) if filePath else "None"
CloseHandle(h_process)
return filePath
@ -157,7 +174,6 @@ def get_key(pid, db_path, addr_len):
: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"
@ -171,11 +187,27 @@ def get_key(pid, db_path, addr_len):
phone_type2 = "android\x00"
phone_type3 = "ipad\x00"
pm = pymem.Pymem(pid)
module_name = "WeChatWin.dll"
MicroMsg_path = os.path.join(db_path, "MSG", "MicroMsg.db")
# start_adress = 0
# end_adress = 0x7FFFFFFFFFFFFFFF
#
# memory_maps = get_memory_maps(pid)
# for module in memory_maps:
# if module.FileName and 'WeChatWin.dll' in module.FileName:
# start_adress = module.BaseAddress
# end_adress = module.BaseAddress + module.RegionSize
# # print(start_adress, end_adress)
# hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, False, pid)
# type1_addrs = search_memory(hProcess, phone_type1.encode(), start_adress, end_adress)
# type2_addrs = search_memory(hProcess, phone_type2.encode(), start_adress, end_adress)
# type3_addrs = search_memory(hProcess, phone_type3.encode(), start_adress, end_adress)
#
# print(type1_addrs, type2_addrs, type3_addrs)
pm = pymem.Pymem(pid)
module_name = "WeChatWin.dll"
type1_addrs = pm.pattern_scan_module(phone_type1.encode(), module_name, return_multiple=True)
type2_addrs = pm.pattern_scan_module(phone_type2.encode(), module_name, return_multiple=True)
type3_addrs = pm.pattern_scan_module(phone_type3.encode(), module_name, return_multiple=True)
@ -210,9 +242,10 @@ def get_details(pid, version_list: dict = None, is_logging: bool = False):
"account": "None", "mobile": "None", "name": "None", "mail": "None",
"wxid": "None", "key": "None", "filePath": "None"}
try:
Handle = ctypes.windll.kernel32.OpenProcess(0x1F0FFF, False, pid)
bias_list = version_list.get(rd['version'], None)
Handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, False, pid)
addrLen = get_exe_bit(path) // 8
if not isinstance(bias_list, list) or len(bias_list) <= 4:
error = f"[-] WeChat Current Version Is Not Supported(maybe not get account,mobile,name,mail)"
@ -240,19 +273,22 @@ def get_details(pid, version_list: dict = None, is_logging: bool = False):
rd['mobile'] = get_info_string(Handle, mobile_baseaddr, 64) if bias_list[2] != 0 else "None"
rd['name'] = get_info_name(Handle, name_baseaddr, addrLen, 64) if bias_list[0] != 0 else "None"
rd['mail'] = get_info_string(Handle, mail_baseaddr, 64) if bias_list[3] != 0 else "None"
rd['key'] = get_info_with_key(Handle, key_baseaddr, addrLen) if bias_list[4] != 0 else "None"
# rd['key'] = get_info_with_key(Handle, key_baseaddr, addrLen) if bias_list[4] != 0 else "None"
rd['wxid'] = get_info_wxid(Handle)
rd['filePath'] = get_info_filePath(rd['wxid']) if rd['wxid'] != "None" else "None"
if rd['wxid'] != "None" and rd['filePath'] == "None": # 通过wxid获取filePath,如果filePath为空则通过wxid获取filePath
rd['filePath'] = get_info_filePath_base_wxid(Handle, rd['wxid'])
rd['filePath'] = get_info_filePath_base_wxid(Handle, wxid=rd['wxid'])
isKey = verify_key(bytes.fromhex(rd["key"]),
os.path.join(rd['filePath'], "MSG", "MicroMsg.db")) if rd['key'] != "None" and rd[
isKey = verify_key(
bytes.fromhex(rd["key"]),
os.path.join(rd['filePath'], "MSG", "MicroMsg.db")) if rd['key'] != "None" and rd[
'filePath'] != "None" else False
if rd['filePath'] != "None" and rd['key'] == "None" and not isKey:
rd['key'] = get_key(rd['pid'], rd['filePath'], addrLen)
CloseHandle(Handle)
except Exception as e:
error = f"[-] WeChat Get Info Error:{e}"
if is_logging: print(error)

View File

@ -0,0 +1,118 @@
import ctypes
import ctypes.wintypes as wintypes
import logging
from ctypes.wintypes import HANDLE
import re
import sys
# 定义常量
PROCESS_QUERY_INFORMATION = 0x0400
PROCESS_VM_READ = 0x0010
PAGE_EXECUTE = 0x10
PAGE_EXECUTE_READ = 0x20
PAGE_EXECUTE_READWRITE = 0x40
PAGE_EXECUTE_WRITECOPY = 0x80
PAGE_NOACCESS = 0x01
PAGE_READONLY = 0x02
PAGE_READWRITE = 0x04
PAGE_WRITECOPY = 0x08
PAGE_GUARD = 0x100
PAGE_NOCACHE = 0x200
PAGE_WRITECOMBINE = 0x400
MEM_COMMIT = 0x1000
MEM_FREE = 0x10000
MEM_RESERVE = 0x2000
MEM_DECOMMIT = 0x4000
MEM_RELEASE = 0x8000
# 定义结构体
class MEMORY_BASIC_INFORMATION(ctypes.Structure):
_fields_ = [
("BaseAddress", ctypes.c_void_p),
("AllocationBase", ctypes.c_void_p),
("AllocationProtect", wintypes.DWORD),
("RegionSize", ctypes.c_size_t),
("State", wintypes.DWORD),
("Protect", wintypes.DWORD),
("Type", wintypes.DWORD),
]
# 加载Windows API函数
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
OpenProcess = kernel32.OpenProcess
OpenProcess.restype = wintypes.HANDLE
OpenProcess.argtypes = [wintypes.DWORD, wintypes.BOOL, wintypes.DWORD]
ReadProcessMemory = kernel32.ReadProcessMemory
VirtualQueryEx = kernel32.VirtualQueryEx
VirtualQueryEx.restype = ctypes.c_size_t
VirtualQueryEx.argtypes = [wintypes.HANDLE, ctypes.c_void_p, ctypes.POINTER(MEMORY_BASIC_INFORMATION), ctypes.c_size_t]
CloseHandle = kernel32.CloseHandle
CloseHandle.restype = wintypes.BOOL
CloseHandle.argtypes = [wintypes.HANDLE]
def search_memory(hProcess, pattern=br'\\Msg\\FTSContact', max_num=100,start_address=0x0,end_address=0x7FFFFFFFFFFFFFFF):
"""
在进程内存中搜索字符串
:param p: 进程ID或者进程句柄
:param pattern: 要搜索的字符串
:param max_num: 最多找到的数量
"""
result = []
# 打开进程
if not hProcess:
raise ctypes.WinError(ctypes.get_last_error())
mbi = MEMORY_BASIC_INFORMATION()
address = start_address
max_address = end_address if sys.maxsize > 2 ** 32 else 0x7fff0000
pattern = re.compile(pattern)
while address < max_address:
if VirtualQueryEx(hProcess, address, ctypes.byref(mbi), ctypes.sizeof(mbi)) == 0:
break
# 读取内存数据
allowed_protections = [PAGE_EXECUTE, PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_READWRITE, PAGE_READONLY, ]
if mbi.State != MEM_COMMIT or mbi.Protect not in allowed_protections:
address += mbi.RegionSize
continue
# 使用正确的类型来避免OverflowError
base_address_c = ctypes.c_ulonglong(mbi.BaseAddress)
region_size_c = ctypes.c_size_t(mbi.RegionSize)
page_bytes = ctypes.create_string_buffer(mbi.RegionSize)
bytes_read = ctypes.c_size_t()
if ReadProcessMemory(hProcess, base_address_c, page_bytes, region_size_c, ctypes.byref(bytes_read)) == 0:
address += mbi.RegionSize
continue
# 搜索字符串 re print(page_bytes.raw)
find = [address + match.start() for match in pattern.finditer(page_bytes, re.DOTALL)]
if find:
result.extend(find)
if len(result) >= max_num:
break
address += mbi.RegionSize
return result
if __name__ == '__main__':
# 示例用法
pid = 29320 # 将此替换为你要查询的进程ID
try:
maps = search_memory(pid)
print(len(maps))
for m in maps:
print(hex(m))
except Exception as e:
logging.error(e, exc_info=True)