diff --git a/.gitignore b/.gitignore index ddc61fb..ff693cf 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ frida-example +.DS_Store +**/__pycache__ diff --git a/README.md b/README.md index 78493af..7b735fe 100644 --- a/README.md +++ b/README.md @@ -32,10 +32,14 @@ | Windows 微信版本 | 小程序版本 | 是否为最新版 | | ---------------- | ---------- | ------------ | +| | 11275_x64 | ✅ | +| | 11253_x64 | ✅ | +| | 11205_x64 | ✅ | +| | 11159_x64 | ✅ | | 3.9.10.19_x64 | 9129_x64 | ✅ | | 3.9.10.19_x64 | 9115_x64 | ✅ | -| 3.9.10.19_x64 | 8555_x64 | ✅ | -| 3.9.10.19_x64 | 9105_x64 | ✅ | +| 3.9.10.19_x64 | 8555_x64 | ❌ | +| 3.9.10.19_x64 | 9105_x64 | ❌ | | 3.9.9.43_x64 | 8555_x64 | ❌ | | 3.9.9.43_x64 | 9079_x64 | ❌ | | 3.9.8.25_x64 | 8531_x64 | ❌ | @@ -50,8 +54,8 @@ | Mac x64微信版本 | 是否为最新版 | x | ---------------- | ------------ | ------------ -| MacWechat/3.8.7(0x13080712) | ✅ | [点我下载](https://github.com/JaveleyQAQ/WeChatOpenDevTools-Python/releases/download/0.3.1/WeChatOpenDevTools-macos-x64.zip) - +| MacWechat/3.8.8(0x13080811) | ✅ | 源码运行 +| MacWechat/3.8.8(0x13080812) | ✅ | 源码运行 ## 如何查看当前运行版本? diff --git a/__pycache__/__init__.cpython-312.pyc b/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 5c1bbe4..0000000 Binary files a/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/__pycache__/banner.cpython-312.pyc b/__pycache__/banner.cpython-312.pyc deleted file mode 100644 index fb48ea0..0000000 Binary files a/__pycache__/banner.cpython-312.pyc and /dev/null differ diff --git a/__pycache__/extract.cpython-312.pyc b/__pycache__/extract.cpython-312.pyc deleted file mode 100644 index 4900c20..0000000 Binary files a/__pycache__/extract.cpython-312.pyc and /dev/null differ diff --git a/configs/address_11159_x64.json b/configs/address_11159_x64.json new file mode 100644 index 0000000..0feb587 --- /dev/null +++ b/configs/address_11159_x64.json @@ -0,0 +1,6 @@ +{ + "LaunchAppletBegin": "0x2888A20", + "MenuItemDevToolsString":"0x69461F8", + "SwitchVersion":"0x26BA076", + "Version":11159 +} diff --git a/configs/address_11205_x64.json b/configs/address_11205_x64.json new file mode 100644 index 0000000..fad39fe --- /dev/null +++ b/configs/address_11205_x64.json @@ -0,0 +1,6 @@ +{ + "LaunchAppletBegin": "0x28A070C", + "MenuItemDevToolsString": "0x28AE121", + "SwitchVersion": "0x26D1CE8", + "Version": 11205 + } diff --git a/configs/address_11253_x64.json b/configs/address_11253_x64.json new file mode 100644 index 0000000..2a812ce --- /dev/null +++ b/configs/address_11253_x64.json @@ -0,0 +1,6 @@ +{ + "LaunchAppletBegin": "0x28A246B", + "MenuItemDevToolsString": "0x2AC446F", + "SwitchVersion": "0x26D3A38", + "Version": 11253 +} \ No newline at end of file diff --git a/configs/address_11275_x64.json b/configs/address_11275_x64.json new file mode 100644 index 0000000..a5b3d1e --- /dev/null +++ b/configs/address_11275_x64.json @@ -0,0 +1,6 @@ +{ + "LaunchAppletBegin": "0x28A255C", + "MenuItemDevToolsString": "0x2AC456F", + "SwitchVersion": "0x26D3B38", + "Version": 11275 + } diff --git a/configs/address_13080811_x64.json b/configs/address_13080811_x64.json new file mode 100644 index 0000000..f0fe3ae --- /dev/null +++ b/configs/address_13080811_x64.json @@ -0,0 +1,7 @@ +{ + "WechatAppHtml": "0x2C86E2B", + "WechatWebHtml": "0x8023935", + "LaunchAppletBegin":"0x2E1D9A8", + "MenuItemDevToolsString":"0x2E295AD", + "Version":13080811 +} diff --git a/configs/address_13080812_x64.json b/configs/address_13080812_x64.json new file mode 100644 index 0000000..9133520 --- /dev/null +++ b/configs/address_13080812_x64.json @@ -0,0 +1,7 @@ +{ + "WechatAppHtml": "0x2C86E2B", + "WechatWebHtml": "0x8023935", + "LaunchAppletBegin":"0x2E1D9A8", + "MenuItemDevToolsString":"0x2E295AD", + "Version":13080812 +} diff --git a/configs/address_9193_x64.json b/configs/address_9193_x64.json new file mode 100644 index 0000000..9709ac3 --- /dev/null +++ b/configs/address_9193_x64.json @@ -0,0 +1,6 @@ +{ + "LaunchAppletBegin": "0x26F1B50", + "MenuItemDevToolsString":"0x290816C", + "SwitchVersion":"0x2554A54", + "Version":9193 +} diff --git a/scripts/hook.js b/scripts/hook.js index b210b41..f4a602c 100644 --- a/scripts/hook.js +++ b/scripts/hook.js @@ -1,6 +1,6 @@ ; //获取WeChatAppEx.exe的基址 -var module = Process.findModuleByName("WeChatAppEx.exe"); +var module = Process.findModuleByName("WeChatAppEx.exe") || Process.findModuleByName('WeChatAppEx Framework') var base = module.base; // console.log("模块名称:",module.name); // console.log("模块地址:",module.base); @@ -9,9 +9,9 @@ var base = module.base; Object.keys(address).forEach(key => { key != "Version" ? address[key] = base.add(address[key]) : false - }); -send("[+] WeChatAppEx.exe 注入成功!"); + +send("[+] WeChatAppEx 注入成功!"); send("[+] 当前小程序版本: " + address.Version); send("[+] 等待小程序加载..."); @@ -19,7 +19,7 @@ function readStdString(s) { var flag = s.add(23).readU8() if (flag == 0x80) { // 从堆中读取 - var size = s.add(8).readUInt() + var size = s.add(8).readUInt() return s.readPointer().readUtf8String(size) } else { // 从栈中读取 @@ -46,9 +46,7 @@ function writeStdString(s, content) { } } function sendMessage(msg) { - - - msg===null || undefined ?send(msg):send("[+] 已还原完整F12") + msg === null || undefined ? send(msg) : send("[+] 已还原完整F12") // send("[+] 已还原完整F12") } @@ -57,31 +55,31 @@ function replaceParams() { Interceptor.attach(address.LaunchAppletBegin, { onEnter(args) { send("[+] HOOK到小程序加载! " + readStdString(args[1])) - for (var i = 0; i < 0x1000; i+=8) { + for (var i = 0; i < 0x1000; i += 8) { try { var s = readStdString(args[2].add(i)) - var s1 = s.replaceAll("md5", "md6") - .replaceAll('"enable_vconsole":false', '"enable_vconsole": true') - .replaceAll('"frameset":false', '"frameset": true') - //"frameset":false + var s1 = s.replaceAll('"enable_vconsole":false', '"enable_vconsole": true') + // .replaceAll("md5", "md6") + // .replaceAll('"frameset":false', '"frameset": true') + //"frameset":false if (s !== s1) { writeStdString(args[2].add(i), s1) - } + } } catch (a) { } } } }) - + } // 过新版8555检测 -if(address.MenuItemDevToolsString){ +if (address.MenuItemDevToolsString) { var menuItemDevToolsStringCr = new Uint8Array(address.MenuItemDevToolsString.readByteArray(7)); var intptr_ = (menuItemDevToolsStringCr[3] & 0xFF) | ((menuItemDevToolsStringCr[4] & 0xFF) << 8) | ((menuItemDevToolsStringCr[5] & 0xFF) << 16) | ((menuItemDevToolsStringCr[6] & 0xFF) << 24); - var menuItemDevToolsStringPtrData = address.MenuItemDevToolsString.add(intptr_+7); + var menuItemDevToolsStringPtrData = address.MenuItemDevToolsString.add(intptr_ + 7); Memory.protect(menuItemDevToolsStringPtrData, 8, 'rw-') menuItemDevToolsStringPtrData.writeUtf8String("DevTools"); replaceParams() @@ -89,15 +87,14 @@ if(address.MenuItemDevToolsString){ } - function setupInterceptor() { /** * */ - + switch (address.Version) { - + case 8555: Interceptor.attach(address.WechatAppHtml, { onEnter(args) { @@ -105,49 +102,106 @@ function setupInterceptor() { sendMessage() } }); - + break; - - + + case 9105: Interceptor.attach(address.SwitchVersion, { onEnter(args) { - this.context.r8= this.context.rax + this.context.r8 = this.context.rax sendMessage() } }) break; - + case 9079: Interceptor.attach(address.SwitchVersion, { onEnter(args) { - this.context.r8= this.context.rax + this.context.r8 = this.context.rax sendMessage() } }) break; - + case 9115: Interceptor.attach(address.SwitchVersion, { onEnter(args) { - this.context.r8= this.context.rax + this.context.r8 = this.context.rax sendMessage() } }) break; case 9129: - Interceptor.attach(address.SwitchVersion, { - onEnter(args) { - this.context.r8= this.context.rax - sendMessage() - } - }) - break; - - + Interceptor.attach(address.SwitchVersion, { + onEnter(args) { + this.context.r8 = this.context.rax + sendMessage() + } + }) + break; + case 11159: + Interceptor.attach(address.SwitchVersion, { + onEnter(args) { + this.context.r8 = this.context.rax + sendMessage() + } + }) + break; + case 13080811: + Interceptor.attach(address.WechatAppHtml, { + onEnter(args) { + this.context.rsi = address.WechatWebHtml + sendMessage() + } + }) + break; + + case 13080812: + Interceptor.attach(address.WechatAppHtml, { + onEnter(args) { + this.context.rsi = address.WechatWebHtml + sendMessage() + } + }) + break; + + case 9193: + Interceptor.attach(address.SwitchVersion, { + onEnter(args) { + this.context.r8 = this.context.rax + sendMessage() + } + }) + break; + case 11205: + Interceptor.attach(address.SwitchVersion, { + onEnter(args) { + this.context.r8 = this.context.rax + sendMessage() + } + }) + break; + case 11275: + Interceptor.attach(address.SwitchVersion, { + onEnter(args) { + this.context.r8 = this.context.rax + sendMessage() + } + }) + break; + case 11253: + Interceptor.attach(address.SwitchVersion, { + onEnter(args) { + this.context.r8 = this.context.rax + sendMessage() + } + }) + break; default: + console.log(address.Version); Interceptor.attach(address.WechatAppHtml, { onEnter(args) { this.context.rdx = address.WechatWebHtml; @@ -156,41 +210,38 @@ function setupInterceptor() { }); break; - - - - - // case "null": - // Interceptor.attach(address.WechatAppHtml, { - // onEnter(args) { - // const webhtml= "68 74 74 70 73 3A 2F 2F 61 70 70 6C 65 74 2D 64 65 62 75 67 2E 63 6F 6D 2F 64 65 76 74 6F 6F 6C 73 2F 77 65 63 68 61 74 5F 77 65 62 2E 68 74 6D 6C"; - // var data; - // Process.enumerateModules({ - // onMatch: function(module){ - // var ranges = module.enumerateRanges('r--'); - // for (var i = 0; i < ranges.length; i++) { - // var range = ranges[i]; - // var scanResults = Memory.scanSync(range.base, range.size, webhtml); - // if (scanResults.length > 0){ - // data = scanResults[0].address - // // console.log('Memory.scanSync() result for range ' + range.base + '-' + range.size + ':\n' + JSON.stringify(scanResults)); - // } - // } - - // }, - // onComplete: function(){ - - // }}); - - // this.context.rdx = data - // sendMessage() - - // } - // }) - - // break; - - - + + // case "null": + // Interceptor.attach(address.WechatAppHtml, { + // onEnter(args) { + // const webhtml= "68 74 74 70 73 3A 2F 2F 61 70 70 6C 65 74 2D 64 65 62 75 67 2E 63 6F 6D 2F 64 65 76 74 6F 6F 6C 73 2F 77 65 63 68 61 74 5F 77 65 62 2E 68 74 6D 6C"; + // var data; + // Process.enumerateModules({ + // onMatch: function(module){ + // var ranges = module.enumerateRanges('r--'); + // for (var i = 0; i < ranges.length; i++) { + // var range = ranges[i]; + // var scanResults = Memory.scanSync(range.base, range.size, webhtml); + // if (scanResults.length > 0){ + // data = scanResults[0].address + // // console.log('Memory.scanSync() result for range ' + range.base + '-' + range.size + ':\n' + JSON.stringify(scanResults)); + // } + // } + + // }, + // onComplete: function(){ + + // }}); + + // this.context.rdx = data + // sendMessage() + + // } + // }) + + // break; + + + } } diff --git a/utils/__pycache__/Student.cpython-312.pyc b/utils/__pycache__/Student.cpython-312.pyc deleted file mode 100644 index d70eb67..0000000 Binary files a/utils/__pycache__/Student.cpython-312.pyc and /dev/null differ diff --git a/utils/__pycache__/__init__.cpython-312.pyc b/utils/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index bd0b744..0000000 Binary files a/utils/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/utils/__pycache__/banner.cpython-312.pyc b/utils/__pycache__/banner.cpython-312.pyc deleted file mode 100644 index b8bd5fa..0000000 Binary files a/utils/__pycache__/banner.cpython-312.pyc and /dev/null differ diff --git a/utils/__pycache__/colors.cpython-312.pyc b/utils/__pycache__/colors.cpython-312.pyc deleted file mode 100644 index 687f4ad..0000000 Binary files a/utils/__pycache__/colors.cpython-312.pyc and /dev/null differ diff --git a/utils/__pycache__/commons.cpython-312.pyc b/utils/__pycache__/commons.cpython-312.pyc deleted file mode 100644 index 841f3d2..0000000 Binary files a/utils/__pycache__/commons.cpython-312.pyc and /dev/null differ diff --git a/utils/__pycache__/extract.cpython-312.pyc b/utils/__pycache__/extract.cpython-312.pyc deleted file mode 100644 index 4900c20..0000000 Binary files a/utils/__pycache__/extract.cpython-312.pyc and /dev/null differ diff --git a/utils/__pycache__/wechatutils.cpython-312.pyc b/utils/__pycache__/wechatutils.cpython-312.pyc deleted file mode 100644 index cf805b0..0000000 Binary files a/utils/__pycache__/wechatutils.cpython-312.pyc and /dev/null differ diff --git a/utils/commons.py b/utils/commons.py index 4e0ec9f..18e43e7 100644 --- a/utils/commons.py +++ b/utils/commons.py @@ -1,18 +1,19 @@ -#commons.py //2024年3月5日23点25分 - +# commons.py from utils.colors import Color from utils.wechatutils import WechatUtils -import frida,sys,time - +import frida +import sys +import time +import platform class Commons: def __init__(self): self.wechatutils_instance = WechatUtils() self.device = frida.get_local_device() self.process = self.device.enumerate_processes() - self.pid = -1 self.version_list = [] self.configs_path = "" + self.active_sessions = [] def onMessage(self, message, data): if message['type'] == 'send': @@ -20,13 +21,17 @@ def onMessage(self, message, data): elif message['type'] == 'error': print(Color.RED + message['stack'], Color.END) - def inject_wehcatEx(self, pid, code): - session = frida.attach(pid) - script = session.create_script(code) - script.on("message", self.onMessage) - script.load() - sys.stdin.read() - # session.detach() + def inject_wechatEx(self, pid, code): + try: + session = frida.attach(pid) + script = session.create_script(code) + script.on("message", self.onMessage) + script.load() + print(Color.GREEN + f"[+] 成功注入微信PID: {pid}", Color.END) + return session + except Exception as e: + print(Color.RED + f"[-] 注入微信失败PID {pid}: {e}", Color.END) + return None def inject_wechatDLL(self, path, code): pid = self.device.spawn(path) @@ -37,34 +42,70 @@ def inject_wechatDLL(self, path, code): self.device.resume(pid) time.sleep(10) session.detach() - # sys.stdin.read() def load_wechatEx_configs(self): path = self.wechatutils_instance.get_configs_path() - pid, version = self.wechatutils_instance.get_wechat_pid_and_version() - if pid or version is not None: - wehcatEx_hookcode = open(path + "..\\scripts\\hook.js", "r", encoding="utf-8").read() - wechatEx_addresses = open(path + "..\\configs\\address_{}_x64.json".format(version)).read() - wehcatEx_hookcode = "var address=" + wechatEx_addresses + wehcatEx_hookcode - self.inject_wehcatEx(pid, wehcatEx_hookcode) + if get_cpu_architecture() == "MacOS x64": + wechat_instances = self.wechatutils_instance.get_wechat_pids_and_versions_mac() + else: + wechat_instances = self.wechatutils_instance.get_wechat_pids_and_versions() + + if wechat_instances: + for pid, version in wechat_instances: + try: + wechatEx_hookcode = open(path + "../scripts/hook.js", "r", encoding="utf-8").read() + wechatEx_addresses = open(path + f"../configs/address_{version}_x64.json").read() + wechatEx_hookcode = "var address=" + wechatEx_addresses + wechatEx_hookcode + session = self.inject_wechatEx(pid, wechatEx_hookcode) + if session: + self.active_sessions.append(session) + print(Color.GREEN +f"[+] 成功注入{version}小程序版本,PID: {pid}", Color.END) + except Exception as e: + print(Color.RED + f"[-] 注入{version}小程序版本失败!", Color.END) else: self.wechatutils_instance.print_process_not_found_message() + # 管理会话 + while self.active_sessions: + self.manage_sessions() + time.sleep(5) # 每5秒检查一次 + def load_wechatEXE_configs(self): - pid, version = self.wechatutils_instance.get_wechat_pid_and_version() - if pid or version is not None: - print(Color.RED+f"[-] 请退出微信后在执行该命令 "+Color.END) + wechat_instances = self.wechatutils_instance.get_wechat_pids_and_versions() + if wechat_instances: + print(Color.RED + f"[-] 请退出所有微信实例后再执行该命令 " + Color.END) return 0 wechatEXEpath = self.wechatutils_instance.find_installation_path("微信") path = self.wechatutils_instance.get_configs_path() - wehcatEXE_hookcode = open(path + "..\\scripts\\WechatWin.dll\\hook.js", "r", encoding="utf-8").read() - self.inject_wechatDLL(wechatEXEpath, wehcatEXE_hookcode) + wechatEXE_hookcode = open(path + "..\\scripts\\WechatWin.dll\\hook.js", "r", encoding="utf-8").read() + self.inject_wechatDLL(wechatEXEpath, wechatEXE_hookcode) def load_wechatEXE_and_wechatEx(self): - pid, version = self.wechatutils_instance.get_wechat_pid_and_version() - if pid or version is not None: - print(Color.RED+f"[-] 请关闭微信后在执行该命令 "+Color.END) + wechat_instances = self.wechatutils_instance.get_wechat_pids_and_versions() + if wechat_instances: + print(Color.RED + f"[-] 请关闭所有微信实例后再执行该命令 " + Color.END) return 0 self.load_wechatEXE_configs() - self.load_wechatEx_configs() \ No newline at end of file + self.load_wechatEx_configs() + + def manage_sessions(self): + for session in self.active_sessions[:]: # 使用切片创建副本以便在迭代时修改 + if session.is_detached: + print(f"Session {session} detached, removing from active sessions.") + self.active_sessions.remove(session) + +def get_cpu_architecture(): + try: + cpu_arch = platform.platform().lower() + if "64bit" in cpu_arch and "macos" in cpu_arch: + return "MacOS x64" + return "Windows" # 默认返回Windows + except Exception as e: + print(Color.RED, f"[-] Error detecting CPU architecture: {e} ", Color.END) + return "Windows" + +# 主函数示例 +if __name__ == "__main__": + commons = Commons() + commons.load_wechatEx_configs() diff --git a/utils/wechatutils.py b/utils/wechatutils.py index 6b00517..649a6ff 100644 --- a/utils/wechatutils.py +++ b/utils/wechatutils.py @@ -1,18 +1,19 @@ -import os,re,winreg -import psutil +import os,re,sys +import psutil,subprocess from utils.colors import Color class WechatUtils: def __init__(self): self.configs_path = self.get_configs_path() self.version_list = self.get_version_list() + # self.pid , self.version = self.get_wechat_pid_and_version() # if self.pid is None and self.version is None: # self.print_process_not_found_message() def get_configs_path(self): current_path = os.path.abspath(__file__) - relative_path = '..\\configs\\' + relative_path = '../configs/' return os.path.join(os.path.dirname(current_path), relative_path) def get_version_list(self): @@ -24,9 +25,38 @@ def get_version_list(self): def is_wechatEx_process(self, cmdline): process_name = "WeChatAppEx" return cmdline and process_name in cmdline[0] and "--type=" not in ' '.join(cmdline) + def get_wechat_pids_and_versions(self): + processes = (proc.info for proc in psutil.process_iter(['pid', 'cmdline'])) + wechatEx_processes = (p for p in processes if self.is_wechatEx_process(p['cmdline'])) + wechat_instances = [] + for process in wechatEx_processes: + pid = process['pid'] + version = self.extract_version_number(process['cmdline']) + if version in self.version_list: + wechat_instances.append((pid, version)) + return wechat_instances + + def get_wechat_pid_and_version(self): + wechat_instances = self.get_wechat_pids_and_versions() + return wechat_instances[0] if wechat_instances else (None, None) + + def get_wechat_pids_and_versions_mac(self): + try: + pid_command = "ps aux | grep 'WeChatAppEx' | grep -v 'grep' | grep ' --client_version' | grep '-user-agent=' | awk '{print $2}'" + version_command = "ps aux | grep 'WeChatAppEx' | grep -v 'grep' | grep ' --client_version' | grep '-user-agent=' | grep -oE 'MacWechat/([0-9]+\.)+[0-9]+\(0x\d+\)' | grep -oE '(0x\d+)' | sed 's/0x//g'" + pids = subprocess.run(pid_command, shell=True, check=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.split() + versions = subprocess.run(version_command, shell=True, check=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.split() + return list(zip(map(int, pids), versions)) + except subprocess.CalledProcessError as e: + print(Color.RED + f"Error getting MacOS WeChat instances: {e.stderr}" + Color.END) + return [] + + def print_process_not_found_message(self): + print(Color.RED + "[-] 未找到匹配版本的微信进程或微信未运行" + Color.END) def find_installation_path(self, program_name): try: + import winreg reg_path = r"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall" reg_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, reg_path) @@ -37,7 +67,7 @@ def find_installation_path(self, program_name): display_name = winreg.QueryValueEx(sub_key, "DisplayName")[0] # 排除企业微信 和 适配英文区域安装的WeChat if program_name == display_name or display_name == 'WeChat': - install_location = winreg.QueryValueEx(sub_key, "InstallLocation")[0]+"\WeChat.exe" + install_location = winreg.QueryValueEx(sub_key, "InstallLocation")[0]+"\\WeChat.exe" print(Color.GREEN + f"[+] 查找到{program_name}的安装路径是:{install_location}" + Color.END) print(Color.GREEN + f"[+] 正在尝试重启微信..."+ Color.END) return install_location @@ -67,4 +97,13 @@ def get_wechat_pid_and_version(self): def print_process_not_found_message(self): print(Color.RED + "[-] 未找到匹配版本的微信进程或微信未运行" + Color.END) + def get_wechat_pid_and_version_mac(self): + try: + pid_command="ps aux | grep 'WeChatAppEx' | grep -v 'grep' | grep ' --client_version' | grep '-user-agent=' | awk '{print $2}' | tail -n 1" + version_command = "ps aux | grep 'WeChatAppEx' | grep -v 'grep' | grep ' --client_version' | grep '-user-agent=' | grep -oE 'MacWechat/([0-9]+\.)+[0-9]+\(0x\d+\)' | grep -oE '(0x\d+)' | sed 's/0x//g' | head -n 1" + pid = subprocess.run(pid_command, shell=True, check=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.replace("\n","") + version = subprocess.run(version_command, shell=True, check=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.replace("\n","") + return int(pid),version + except subprocess.CalledProcessError as e: + return e.stderr