xaoyaoo / PyWxDump

获取微信账号信息(昵称/账号/手机/邮箱/数据库密钥/wxid);PC微信数据库读取、解密脚本;聊天记录查看工具;聊天记录导出为html(包含语音图片)。支持多账户信息获取,支持所有微信版本。

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

关于代码的建议

SnowMeteors opened this issue · comments

result = pywxdump.read_info(pywxdump.VERSION_LIST)

一旦上面的代码,出现异常你的整个程序就没法获取正确的信息了,报错信息为Windows api error, error_code: 5

而换成

result = pywxdump.read_info(pywxdump.VERSION_LIST, True)

信息为

================================
[+]      pid: 1032
[+]  version: 3.9.10.27
[+]  account: ******
[+]   mobile: None
-----------------------------------

我的建议是,不管是否发生异常,都应该抛出结果,也就是pid那些等等数据都应该返回给用户,即使数据为None,用户不必关心你中间是否有异常,只关心数据是否获取完整,是否获取到

其二,我发现你尝试从wechat.exe来获取版本号,我遇到过wechat.exe获取版本号不正确的情况,而我用wechatwin.dll来获取,没出现过错误。 关于这个我现在无法提供复现的,当时我是把每个微信版本全部安装了一遍,发现的版本号获取错误问题,开始我也用的wechat.exe来获取版本号。你可以去这个仓库获取到微信历史版本 https://github.com/tom-snow/wechat-windows-versions/
示例代码

def _FindWinDll(root_dir) -> Optional[str]:
    root_dir = os.path.dirname(root_dir)
    for root, dirs, files in os.walk(root_dir):
        for file in files:
            if file.lower() == "wechatwin.dll":
                return os.path.join(root, file)

    return None
      
exePath = r"D:\Entertainment\WeChat\WeChat.exe"
dllpath = _FindWinDll(exePath)

上面的wechatwin.dll获取到的就是 下面的版本信息
image

我建议 不要过度依赖pymem的其他模块,我大量实战发现pymem的代码有很多bug。
它的匹配内存和read数据的功能,这两个问题不大,其他的问题都或多或少有

result = pywxdump.read_info(pywxdump.VERSION_LIST)

一旦上面的代码,出现异常你的整个程序就没法获取正确的信息了,报错信息为Windows api error, error_code: 5

而换成

result = pywxdump.read_info(pywxdump.VERSION_LIST, True)

信息为

================================
[+]      pid: 1032
[+]  version: 3.9.10.27
[+]  account: ******
[+]   mobile: None
-----------------------------------

我的建议是,不管是否发生异常,都应该抛出结果,也就是pid那些等等数据都应该返回给用户,即使数据为None,用户不必关心你中间是否有异常,只关心数据是否获取完整,是否获取到

好的

都有哪些微信版本是不一致的?

都有哪些微信版本是不一致的?

微信的机制很奇怪,就算是同一个版本,在不同电脑上安装,都有可能导致wechat.exe和wechatwin.dll的版本不一样,我目前遇到过好像是3.8.x及以下的。复现的步骤是,直接在已有的微信基础上,直接安装旧版本的微信,不要卸载原来的微信。你会注意到一个事情:1.有些版本wechatwin.dll在上层目录。2.有些wechatwin.dll在wechat.exe同级目录。
所以只有全部遍历所有文件来获取wechatwin.dll。最开始我是使用pymem来获取wechat.exe中加载的内存wechatwin.dll的模块,通过模块来定位wechatwin.dll的内容。但是pymem即使能正确定位到了wechatwin.dll的模块数据,但有些时候我尝试获取wechatwin.dll的磁盘位置,就会报错,反正就是pymem有问题,我的使用感受是它只适合操控内存,其他的一些功能,都不是太适合

psutil 我现在用的是这个库,获取的dl路径,然后通过这个路径进行的判断。
pymem现在只用来搜索内存

psutil 我现在用的是这个库,获取的dl路径,然后通过这个路径进行的判断。 pymem现在只用来搜索内存

还有在get_wx_info.py 第200行中,你的代码如下

try:
        .... 省略代码

         rd['account'] = get_info_string(Handle, account__baseaddr, 32) if bias_list[1] != 0 else "None"
         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"
except Exception as e:
        error = f"[-] WeChat Get Info Error:{e}"
        if is_logging: print(error)

这样的异常处理是不合理的,如果rd['account'] = get_info_string(Handle, account__baseaddr, 32) if bias_list[1] != 0 else "None"这行代码出现异常,后面的所有数据都无法正确获取到。你应该分别处理每条语句的异常,也就是
rd['account'] = get_info_string(Handle, account__baseaddr, 32) if bias_list[1] != 0 else "None"能不能正确获取到和rd['mobile'] = get_info_string(Handle, mobile_baseaddr, 64) if bias_list[2] != 0 else "None" 以及后面的数据能不能正确到,都没有任何关系,请分开处理

请多检查你的异常处理结构,分开处理各个异常,只有当后面的数据和前面数据有关联的时候才使用一大堆try,不然会造成本来很多可以获取到的数据,都返回None了。所以这也是为什么一个try尽量细小化的原因

好的,我重新增加了错误处理装饰器

我不明白你写 字符串"None"的原因是什么

rd = {'pid': process.pid, 'version': get_exe_version(process.exe()),
          "account": "None", "mobile": "None", "name": "None", "mail": "None",
          "wxid": "None", "key": "None", "filePath": "None"}

完全可以直接写

rd = {'pid': process.pid, 'version': get_exe_version(process.exe()),
          "account": None, "mobile": None, "name": None, "mail": None,
          "wxid": None" "key": None, "filePath": None}

上面的写法,对None的判断也很简单
例如

a = None
if a:
    print("Not None")
else:
    print("None")

这样我感觉简单得多,判断也不复杂
python对于if的判断条件很宽泛,只要数据有值都是真,否则false,None,空列表[] 等等都是假,

还有对函数的返回值都是可以表示的,例如

# 表示 无返回值
def HandleInfo(wxinfoList, wxdumpList) -> None: 

# 表示 要么返回None,要么返回一个列表
def GetProcess(name) -> Optional[list]: 

这些都是可以规范起的,让使用者清晰明了

最开始是你说的这样的,后面忘记是为了兼容什么,就统一用的字符串

好像只能支持64位,我测试了最新版的64位,手机号能抓到,32位抓不到,是不支持32位的手机号码?