diff --git a/MultiWechat/MultiWeChat.sln b/MultiWechat/MultiWeChat.sln index 2b290fd..f6e296d 100644 --- a/MultiWechat/MultiWeChat.sln +++ b/MultiWechat/MultiWeChat.sln @@ -5,16 +5,30 @@ VisualStudioVersion = 15.0.28010.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MultiWeChat", "MultiWebchat.vcxproj", "{06ABD385-B50D-491D-8FBD-2B26B46568CC}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WeChatResource", "..\WeChatResource\WeChatResource.vcxproj", "{CC8544D5-1A6E-4515-B737-4DA205371032}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 + Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {06ABD385-B50D-491D-8FBD-2B26B46568CC}.Debug|Win32.ActiveCfg = Debug|Win32 {06ABD385-B50D-491D-8FBD-2B26B46568CC}.Debug|Win32.Build.0 = Debug|Win32 + {06ABD385-B50D-491D-8FBD-2B26B46568CC}.Debug|x64.ActiveCfg = Debug|Win32 {06ABD385-B50D-491D-8FBD-2B26B46568CC}.Release|Win32.ActiveCfg = Release|Win32 {06ABD385-B50D-491D-8FBD-2B26B46568CC}.Release|Win32.Build.0 = Release|Win32 + {06ABD385-B50D-491D-8FBD-2B26B46568CC}.Release|x64.ActiveCfg = Release|Win32 + {CC8544D5-1A6E-4515-B737-4DA205371032}.Debug|Win32.ActiveCfg = Debug|Win32 + {CC8544D5-1A6E-4515-B737-4DA205371032}.Debug|Win32.Build.0 = Debug|Win32 + {CC8544D5-1A6E-4515-B737-4DA205371032}.Debug|x64.ActiveCfg = Debug|x64 + {CC8544D5-1A6E-4515-B737-4DA205371032}.Debug|x64.Build.0 = Debug|x64 + {CC8544D5-1A6E-4515-B737-4DA205371032}.Release|Win32.ActiveCfg = Release|Win32 + {CC8544D5-1A6E-4515-B737-4DA205371032}.Release|Win32.Build.0 = Release|Win32 + {CC8544D5-1A6E-4515-B737-4DA205371032}.Release|x64.ActiveCfg = Release|x64 + {CC8544D5-1A6E-4515-B737-4DA205371032}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/MultiWechat/MultiWebchat.aps b/MultiWechat/MultiWebchat.aps index 9720c57..60b6e24 100644 Binary files a/MultiWechat/MultiWebchat.aps and b/MultiWechat/MultiWebchat.aps differ diff --git a/MultiWechat/MultiWebchat.rc b/MultiWechat/MultiWebchat.rc index 1834999..da64ad1 100644 --- a/MultiWechat/MultiWebchat.rc +++ b/MultiWechat/MultiWebchat.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,1,2,0 - PRODUCTVERSION 1,1,2,0 + FILEVERSION 1,1,3,0 + PRODUCTVERSION 1,1,3,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -69,12 +69,12 @@ BEGIN BEGIN VALUE "CompanyName", "Anhkgg. China" VALUE "FileDescription", "WeChat电脑端多开器" - VALUE "FileVersion", "1.1.2.0" + VALUE "FileVersion", "1.1.3.0" VALUE "InternalName", "MultiWeChat" VALUE "LegalCopyright", "Copyright (C) 2017 by Anhkgg" VALUE "OriginalFilename", "MultiWeChat.exe" VALUE "ProductName", "WeChat电脑端多开器" - VALUE "ProductVersion", "1.1.2.0" + VALUE "ProductVersion", "1.1.3.0" END END BLOCK "VarFileInfo" diff --git a/MultiWechat/MultiWebchat.vcxproj b/MultiWechat/MultiWebchat.vcxproj index 0f1b053..a062bc3 100644 --- a/MultiWechat/MultiWebchat.vcxproj +++ b/MultiWechat/MultiWebchat.vcxproj @@ -15,6 +15,7 @@ {06ABD385-B50D-491D-8FBD-2B26B46568CC} MultiWebchat Win32Proj + 8.1 @@ -22,6 +23,7 @@ v141 Unicode true + Static Application @@ -74,7 +76,7 @@ MaxSpeed true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL + MultiThreaded true Level3 diff --git a/MultiWechat/main.cpp b/MultiWechat/main.cpp index bec9af5..5b44a7c 100644 --- a/MultiWechat/main.cpp +++ b/MultiWechat/main.cpp @@ -5,6 +5,9 @@ #include "main.h" #include +#pragma comment(lib, "Advapi32") +#pragma comment(lib, "Shell32") + //进程提权 BOOL ElevatePrivileges() { @@ -238,14 +241,24 @@ bool InstallRevokeDll(LPWSTR Path, bool Update) WCHAR wszDll[MAX_PATH] = { 0 }; WCHAR wszDllOrig[MAX_PATH] = { 0 }; WCHAR wszDll1[MAX_PATH] = { 0 }; + WCHAR wszConfig[MAX_PATH] = { 0 }; + WCHAR wszConfig1[MAX_PATH] = { 0 }; + GetModuleFileName(NULL, wszDll, MAX_PATH); - PathRemoveFileSpec(wszDll); - wcscpy_s(wszDll1, Path); + PathRemoveFileSpec(wszDll); + + wcscpy_s(wszConfig1, Path); + PathAppend(wszConfig1, L"superwx.ini"); + wcscpy_s(wszConfig, wszDll); + PathAppend(wszConfig, L"superwx.ini"); + + CopyFile(wszConfig, wszConfig1, false); + + wcscpy_s(wszDll1, Path); PathAppend(wszDll, L"WeChatResource.dll"); PathAppend(wszDll1, L"WeChatResource.dll.1"); wcscpy_s(wszDllOrig, Path); PathAppend(wszDllOrig, L"WeChatResource.dll"); - if (!PathFileExists(wszDll1)) { MoveFile(wszDllOrig, wszDll1); diff --git a/WeChatResource/Resource.rc b/WeChatResource/Resource.rc index 827097d..5255e22 100644 Binary files a/WeChatResource/Resource.rc and b/WeChatResource/Resource.rc differ diff --git a/WeChatResource/WeChatResource.cpp b/WeChatResource/WeChatResource.cpp index d9ddcdb..afeb369 100644 Binary files a/WeChatResource/WeChatResource.cpp and b/WeChatResource/WeChatResource.cpp differ diff --git a/WeChatResource/WeChatResource.vcxproj b/WeChatResource/WeChatResource.vcxproj index 13ffd96..14484a3 100644 --- a/WeChatResource/WeChatResource.vcxproj +++ b/WeChatResource/WeChatResource.vcxproj @@ -149,19 +149,25 @@ + + + + + NotUsing NotUsing + Create Create @@ -169,11 +175,17 @@ Create + + + + Document + + diff --git a/WeChatResource/WeChatResource.vcxproj.filters b/WeChatResource/WeChatResource.vcxproj.filters index cabd18a..c6f3623 100644 --- a/WeChatResource/WeChatResource.vcxproj.filters +++ b/WeChatResource/WeChatResource.vcxproj.filters @@ -33,6 +33,18 @@ 澶存枃浠 + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + @@ -50,6 +62,18 @@ 婧愭枃浠 + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + diff --git a/WeChatResource/common.cpp b/WeChatResource/common.cpp new file mode 100644 index 0000000..75c6ed2 --- /dev/null +++ b/WeChatResource/common.cpp @@ -0,0 +1,48 @@ +#include "stdafx.h" +#include "common.h" +#include "util.h" + +bool IsSupportedWxVersion( + const SuppWxCfg* cfg, + INT cfg_count, + DWORD* offset/* = NULL*/, + BYTE* orig_code/* = NULL*/, + DWORD* orig_code_count/* = NULL*/, + BYTE* fake_code/* = NULL*/, + DWORD* fake_code_count/* = NULL*/) +{ + TCHAR tszDllPath[MAX_PATH] = { 0 }; + + GetModuleFileName(NULL, tszDllPath, MAX_PATH); + PathRemoveFileSpec(tszDllPath); + PathAppend(tszDllPath, WECHATWINDLL); + + TCHAR version[100] = { 0 }; + if (!GetFileVersion(tszDllPath, version)) + { + return false; + } + + for (int i = 0; i < cfg_count; i++) { + if (!_tcsicmp(cfg[i].version, version)) { + if (offset) { + *offset = cfg[i].revoke_offset; + } + if (orig_code) { + memcpy(orig_code, cfg[i].code.orig_code, cfg[i].code.orig_code_count); + } + if (fake_code) { + memcpy(fake_code, cfg[i].code.fake_code, cfg[i].code.fake_code_count); + } + if (orig_code_count) { + *orig_code_count = cfg[i].code.orig_code_count; + } + if (fake_code_count) { + *fake_code_count = cfg[i].code.fake_code_count; + } + return true; + } + } + + return false; +} \ No newline at end of file diff --git a/WeChatResource/common.h b/WeChatResource/common.h new file mode 100644 index 0000000..e2d756d --- /dev/null +++ b/WeChatResource/common.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +#define WECHATWINDLL TEXT("WeChatWin.dll") +#define WECHATRESOURCE TEXT("WeChatResource.dll") +#define ORGWECHATRESOURCE TEXT("WeChatResource.dll.1") + +typedef struct _FAKE_WX_CODE +{ + DWORD orig_code_count; + BYTE orig_code[100]; + DWORD fake_code_count; + BYTE fake_code[100]; +}FakeWxCode, *PFakeWxCode; + +typedef struct _SUP_WX_CFG +{ + const TCHAR* version; + DWORD revoke_offset; + FakeWxCode code; +}SuppWxCfg, *PSuppWxCfg; + +bool IsSupportedWxVersion( + const SuppWxCfg* cfg, + INT cfg_count, + DWORD* offset = NULL, + BYTE* orig_code = NULL, + DWORD* orig_code_count = NULL, + BYTE* fake_code = NULL, + DWORD* fake_code_count = NULL); \ No newline at end of file diff --git a/WeChatResource/config.cpp b/WeChatResource/config.cpp new file mode 100644 index 0000000..5461047 --- /dev/null +++ b/WeChatResource/config.cpp @@ -0,0 +1,47 @@ +#include "stdafx.h" +#include "config.h" + +#define CONFIGFILE TEXT("superwx.ini") + +WxFuncConfig::WxFuncConfig() +{ + Init(); +} + +WxFuncConfig::~WxFuncConfig() +{ + +} + +void WxFuncConfig::Init() +{ + TCHAR tszCfgPath[MAX_PATH] = { 0 }; + + GetModuleFileName(GetModuleHandle(WECHATRESOURCE), tszCfgPath, MAX_PATH); + PathRemoveFileSpec(tszCfgPath); + PathAppend(tszCfgPath, CONFIGFILE); + + _tcscpy_s(m_configPath, tszCfgPath); +} + +bool WxFuncConfig::IsRevokeMsg() +{ + return GetPrivateProfileInt(TEXT("config"), TEXT("revokemsg"), 0, m_configPath) != 0; +} + +bool WxFuncConfig::IsSaveVoiceMsg(TCHAR * path) +{ + TCHAR voiceMsgPath[MAX_PATH] = { 0 }; + + GetPrivateProfileString(TEXT("config"), TEXT("voicemsg"), TEXT(""), voiceMsgPath, MAX_PATH, m_configPath); + if (_tcslen(voiceMsgPath) > 0) { + if (path) { + _tcscpy_s(path, MAX_PATH, voiceMsgPath); + } + return true; + } + else { + return false; + } +} + diff --git a/WeChatResource/config.h b/WeChatResource/config.h new file mode 100644 index 0000000..f44fe25 --- /dev/null +++ b/WeChatResource/config.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +class WxFuncConfig +{ +public: + WxFuncConfig(); + ~WxFuncConfig(); + + bool IsRevokeMsg(); + bool IsSaveVoiceMsg(TCHAR* path); +private: + void Init(); + +private: + TCHAR m_configPath[MAX_PATH]; +}; \ No newline at end of file diff --git a/WeChatResource/dllmain.cpp b/WeChatResource/dllmain.cpp index 004af8c..cb96bcb 100644 Binary files a/WeChatResource/dllmain.cpp and b/WeChatResource/dllmain.cpp differ diff --git a/WeChatResource/hook.cpp b/WeChatResource/hook.cpp new file mode 100644 index 0000000..acd0152 --- /dev/null +++ b/WeChatResource/hook.cpp @@ -0,0 +1,48 @@ +#include "stdafx.h" +#include "hook.h" +#include "voice.h" + +#include "mhook.h" +#pragma comment(lib, "mhook.lib") + +extern WxFuncConfig g_WxFuncConfig; + +const SuppWxCfg g_Supported_wxVoiceMsg_Version[] = { + //{ TEXT("2.6.5.38"), 0x247EF1 ,{3, {0x8A, 0x45, 0xF3}, 3, {0x33, 0xc0, 0x90}}}, + //{ TEXT("2.6.6.25"), 0x24BA81 ,{3, {0x8A, 0x45, 0xF3}, 3, {0x33, 0xc0, 0x90}}}, + { TEXT("2.6.6.28"), 0x24D5A0 ,{0}}, //voiicemsg +}; + +bool InitHook() +{ + HMODULE hMod = GetModuleHandle(WECHATWINDLL); + if (hMod == NULL) { + return false; + } + + TCHAR voiceMsgPath[MAX_PATH] = { 0 }; + + if (g_WxFuncConfig.IsSaveVoiceMsg(voiceMsgPath)) { + SetSildDirPath(voiceMsgPath); + DWORD voiceMsgOffset = 0; + if (IsSupportedWxVersion( + g_Supported_wxVoiceMsg_Version, + ARRAYSIZE(g_Supported_wxVoiceMsg_Version), + &voiceMsgOffset)) { + PVOID* p = GetOrigVocieDecodeInternal(); + *p = (PVOID)((DWORD)hMod + voiceMsgOffset); + if (!Mhook_SetHook(p, fakeVoiceDecodeInternal)) { + *p = NULL; + } + } + } + return true; +} + +void UninitHook() +{ + PVOID* p = GetOrigVocieDecodeInternal(); + if (*p) { + Mhook_Unhook(p); + } +} \ No newline at end of file diff --git a/WeChatResource/hook.h b/WeChatResource/hook.h new file mode 100644 index 0000000..7b6d285 --- /dev/null +++ b/WeChatResource/hook.h @@ -0,0 +1,4 @@ +#pragma once + +bool InitHook(); +void UninitHook(); \ No newline at end of file diff --git a/WeChatResource/mhook.h b/WeChatResource/mhook.h new file mode 100644 index 0000000..1c6c64a --- /dev/null +++ b/WeChatResource/mhook.h @@ -0,0 +1,31 @@ +//Copyright (c) 2007-2008, Marton Anka +// +//Permission is hereby granted, free of charge, to any person obtaining a +//copy of this software and associated documentation files (the "Software"), +//to deal in the Software without restriction, including without limitation +//the rights to use, copy, modify, merge, publish, distribute, sublicense, +//and/or sell copies of the Software, and to permit persons to whom the +//Software is furnished to do so, subject to the following conditions: +// +//The above copyright notice and this permission notice shall be included +//in all copies or substantial portions of the Software. +// +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +//OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +//THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +//FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +//IN THE SOFTWARE. + +#ifdef _M_IX86 +#define _M_IX86_X64 +#elif defined _M_X64 +#define _M_IX86_X64 +#endif + +BOOL Mhook_SetHook(PVOID *ppSystemFunction, PVOID pHookFunction); +BOOL Mhook_Unhook(PVOID *ppHookedFunction); + +#define MHOOKS_MAX_SUPPORTED_HOOKS 64 + diff --git a/WeChatResource/mhook.lib b/WeChatResource/mhook.lib new file mode 100644 index 0000000..175c9c9 Binary files /dev/null and b/WeChatResource/mhook.lib differ diff --git a/WeChatResource/stdafx.h b/WeChatResource/stdafx.h index aaa635a..76a4960 100644 Binary files a/WeChatResource/stdafx.h and b/WeChatResource/stdafx.h differ diff --git a/WeChatResource/voice.cpp b/WeChatResource/voice.cpp new file mode 100644 index 0000000..07660db --- /dev/null +++ b/WeChatResource/voice.cpp @@ -0,0 +1,126 @@ +#include "stdafx.h" +#include "voice.h" + +typedef struct _wxstring +{ + wchar_t* buf; + int len; + int maxlen; +}wxstring, *pwxstring; + +typedef struct _wxstring_ansi +{ + char* buf; + int len; + int maxlen; +}wxstring_ansi, *pwxstring_ansi; + +typedef struct _wxmsg +{ + char unk[0x40];// + wxstring wxid1;//40 from + wxstring_ansi wxid1_ansi;//4c + char unk1[0x10];//58 + wxstring msg;//68 xml + wxstring_ansi msg_ansi;//74 + char unk2[0x50];//80 + char unk3[0x44];//d0 + wxstring wxid2;//0x114 + DWORD unk4;//120 + DWORD unk5;//124 + wxstring hash;//128 + //134 +} wxmsg, *pwxmsg; + + +typedef int(__stdcall* PFNVoiceDecodeInternal)(int voice, int size, int from, int a4); + +PFNVoiceDecodeInternal pfnVoiceDecodeInternal = NULL; +TCHAR SildDirPath[MAX_PATH] = { 0 }; + +void CreateSilkDir(const TCHAR* path) +{ + TCHAR pathDir[MAX_PATH] = { 0 }; + + _tcscpy_s(pathDir, path); + if (!PathFileExists(pathDir)) { + PathRemoveFileSpec(pathDir); + CreateSilkDir(pathDir); + CreateDirectory(path, NULL); + } +} + +void* Silk2Mp3(void* data, int size) +{ + //https://github.com/kn007/silk-v3-decoder + return NULL; +} + +void SaveSilk(void* data, int size, const TCHAR* path, const TCHAR* name) +{ + DWORD dwWritten = 0; + TCHAR FullPath[MAX_PATH] = { 0 }; + + _tcscpy_s(FullPath, path); + PathAppend(FullPath, name); + + if (PathFileExists(FullPath)) { + return; + } + + CreateSilkDir(path); + + if (PathFileExists(path)) { + HANDLE hFile = CreateFile(FullPath, GENERIC_ALL, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile != INVALID_HANDLE_VALUE) { + //TODO: convert silk to mp3 + Silk2Mp3(data, size); + WriteFile(hFile, data, size, &dwWritten, NULL); + CloseHandle(hFile); + } + } +} + +VOID SetSildDirPath(const TCHAR* path) +{ + _tcscpy_s(SildDirPath, path); +} + +PVOID * GetOrigVocieDecodeInternal() +{ + return (PVOID *)&pfnVoiceDecodeInternal; +} + +/* + +*/ +const WCHAR* GetBufId(const WCHAR* xml, WCHAR* bufid) +{ + const WCHAR* p = _tcsstr(xml, L"bufid=\""); + if (p) { + p = p + _tcslen(L"bufid=\""); + WCHAR* p1 = (WCHAR*)_tcsstr(p, L"\""); + if (p1) { + memcpy(bufid, p, (p1 - p) * sizeof(WCHAR)); + } + } + return bufid; +} + +int __stdcall fakeVoiceDecodeInternal(int voice, int size, int from, int a4) +{ + wxmsg* m = (wxmsg*)from; + WCHAR bufid[100] = { 0 }; + TCHAR name[MAX_PATH] = { 0 }; + PVOID pData = (PVOID)voice; + int nDataSize = size; + + + if (SildDirPath) { + wsprintf(name, TEXT("%ws_%ws.silk"), m->wxid1.buf, GetBufId((const WCHAR*)(m->msg.buf), bufid)); + SaveSilk(pData, nDataSize, SildDirPath, name); + } + + return pfnVoiceDecodeInternal(voice, size, from, a4); +} + \ No newline at end of file diff --git a/WeChatResource/voice.h b/WeChatResource/voice.h new file mode 100644 index 0000000..e558315 --- /dev/null +++ b/WeChatResource/voice.h @@ -0,0 +1,5 @@ +#pragma once + +VOID SetSildDirPath(const TCHAR* path); +PVOID* GetOrigVocieDecodeInternal(); +int __stdcall fakeVoiceDecodeInternal(int voice, int size, int from, int a4); \ No newline at end of file diff --git a/bin/WeChatResource.dll b/bin/WeChatResource.dll index fbfbfa8..d3d768c 100644 Binary files a/bin/WeChatResource.dll and b/bin/WeChatResource.dll differ diff --git "a/bin/WeChat\345\244\232\345\274\200(\351\230\262\346\222\244\351\224\200).exe" "b/bin/WeChat\345\244\232\345\274\200(\351\230\262\346\222\244\351\224\200).exe" index 2a7a6eb..494b5b8 100644 Binary files "a/bin/WeChat\345\244\232\345\274\200(\351\230\262\346\222\244\351\224\200).exe" and "b/bin/WeChat\345\244\232\345\274\200(\351\230\262\346\222\244\351\224\200).exe" differ diff --git a/bin/superwx.ini b/bin/superwx.ini new file mode 100644 index 0000000..90201ee --- /dev/null +++ b/bin/superwx.ini @@ -0,0 +1,3 @@ +[config] +revokemsg=1 +voicemsg=c:\ \ No newline at end of file diff --git a/readme.md b/readme.md index 0f3db96..e9d14a8 100644 --- a/readme.md +++ b/readme.md @@ -1,7 +1,7 @@ # 概述 -微信电脑客户端多开工具,支持防消息撤销。 +微信电脑客户端多开工具,支持防消息撤销,支持语音消息备份(demo)。 1. WeChatResource目录是防撤销插件源码,暂时只支持固定版本(非通用,[具体见更新日志](#更新日志)),如有需要请联系我兼容或者自行修改。 2. MultiWeChat是多开源码 @@ -11,9 +11,20 @@ 1. 双击运行WeChat多开(防撤销).exe即可。 2. 如更新了WeChatResource.dll,请使用如下参数运行:`WeChat多开(防撤销).exe n`。 +3. `superex.ini`配置如下: +``` + [config] + revokemsg=1 #0:关闭防消息撤销,1:打开消息防撤销 + voicemsg=c:\ #填入备份语音消息的目录,空为关闭语音消息备份功能 +``` # 更新日志 +**2019年2月1日(v1.1.3)** +1. 增加支持语音消息备份(仅支持2.6.6.28),只是个demo,有特殊需要请自行修改或者联系我。 +2. 增加`superex.ini`配置文件,可自行开关防消息撤销和语音消息备份 +3. [下载地址](https://github.com/anhkgg/SuperWeChatPC/releases/tag/v1.1.3) + **2018年12月28日(v1.1.2)** 1. 更新支持微信(2.6.6.28) 2. 更新支持随机mutex多开