微信双开代码实现



微信双开代码实现

作者: cj13888

全网最全的网络资源分享网站

手机扫码查看

标签:

特别声明:本站资源分别为免费资源、查看密码或解压密码资源、三个级别VIP会员资源。本站所有发布的内容都是安全,请放心下载!本站不可能所有资源都可以商业用途,原创或部分除外!如:商业用途请联系原作者购买正版。与本站无关!若侵犯到您的权益,请联系本站删除,我们将及时处理!

分享

互斥量是一个很好玩的东西,可以实现进程的单例。WeChat也是用的Mutant技术实现的防止多开。无事练习下Win32 API编程,于是便有了此贴。
   实现双开的原理就是跨进程关闭互斥量句柄。各位看官可以自行完善下面代码实现多开。

#include<Windows.h>
#include<TlHelp32.h>
#include<stdio.h>
#include<memory>
 
#pragma comment(lib,"ntdll")
 
#define NT_SUCCESS(status) (status>=0)
 
#define STATUS_INFO_LENGTH_MISMATCH  ((NTSTATUS)0xC0000004L)
 
enum PROCESSINFOCLASS {
        ProcessHandleInformation = 51
};
 
typedef struct _PROCESS_HANDLE_TABLE_ENTRY_INFO {
        HANDLE HandleValue;
        ULONG_PTR HandleCount;
        ULONG_PTR PointerCount;
        ULONG GrantedAccess;
        ULONG ObjectTypeIndex;
        ULONG HandleAttributes;
        ULONG Reserved;
}PROCESS_HANDLE_TABLE_ENTRY_INFO,*PROCESS_HANDLE_TABLE_ENTRY;
 
 
// private
typedef struct _PROCESS_HANDLE_SNAPSHOT_INFORMATION {
ULONG_PTR NumberOfHandles;
ULONG_PTR Reserved;
PROCESS_HANDLE_TABLE_ENTRY_INFO Handles[1];
}PROCESS_HANDLE_SNAPSHOT_INFORMATION, *PROCESS_HANDLE_SNAPSHOT;
 
 
extern "C" NTSTATUS NTAPI NtQueryInformationProcess(
        _In_ HANDLE ProcessHandle,
        _In_ PROCESSINFOCLASS ProcessInformationClass,
        _In_ _Out_writes_bytes_(ProcessInformationLength) PVOID ProcessInformation,
        _In_ ULONG ProcessInformationLength,
        _Out_opt_ PULONG ReturnLength);
 
typedef enum _OBJECT_INFORMATION_CLASS {
        ObjectNameInformation = 1
} OBJECT_INFORMATION_CLASS;
 
typedef struct _UNICODE_STRING {
        USHORT Length;
        USHORT MaximumLength;
        PWSTR  Buffer;
} UNICODE_STRING;
 
typedef struct _OBJECT_NAME_INFORMATION {
        UNICODE_STRING Name;
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
 
extern "C" NTSTATUS NTAPI NtQueryObject(
        _In_opt_ HANDLE Handle,
        _In_ OBJECT_INFORMATION_CLASS ObjectInformationClass,
        _Out_writes_bytes_opt_(ObjectInformationLength) PVOID ObjectInformation,
        _In_ ULONG ObjectInformationLength,
        _Out_opt_ PULONG ReturnLength);
 
DWORD FindWeChat() {
        HANDLE hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
        if (hSnapshot == INVALID_HANDLE_VALUE)
                return 0;
 
        PROCESSENTRY32 pe;
        pe.dwSize = sizeof(pe);
 
        // skip the idle process
        ::Process32First(hSnapshot, &pe);
 
        DWORD pid = 0;
        while (::Process32Next(hSnapshot, &pe)) {
                if (::_wcsicmp(pe.szExeFile, L"WeChat.exe") == 0) {
                        // found it
                        pid = pe.th32ProcessID;
                        break;
                }
        }
        ::CloseHandle(hSnapshot);
        return pid;
}
 
int main() {
        DWORD pid = FindWeChat();
        if (pid == 0) {
                printf("Failed to locate WeChat\n");
                return 1;
        }
        printf("Located WeChat : PID=%u\n", pid);
 
        HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_DUP_HANDLE,
                FALSE, pid);
        if (!hProcess) {
                printf("Failed to open WeChat process handle (error=%u)\n",
                        GetLastError());
                return 1;
        }
 
        ULONG size = 1 << 10;
        std::unique_ptr<BYTE[]> buffer;
        for (;;) {
                buffer = std::make_unique<BYTE[]>(size);
                auto status = ::NtQueryInformationProcess(hProcess, ProcessHandleInformation,
                        buffer.get(), size, &size);
                if (NT_SUCCESS(status))
                        break;
                if (status == STATUS_INFO_LENGTH_MISMATCH) {
                        size += 1 << 10;
                        continue;
                }
                printf("Error enumerating handles\n");
                return 1;
        }
 
        WCHAR targetName[256];
        DWORD sessionId;
        ::ProcessIdToSessionId(pid, &sessionId);
        ::swprintf_s(targetName,
                L"\\Sessions\\%u\\BaseNamedObjects\\_WeChat_App_Instance_Identity_Mutex_Name",
                sessionId);
        auto len = ::wcslen(targetName);
 
        WCHAR targetName2[256];
        ::swprintf_s(targetName2,
                L"\\Sessions\\%u\\BaseNamedObjects\\WeChat_GlobalConfig_Multi_Process_Mutex",
                sessionId);
        auto len2 = ::wcslen(targetName2);
 
        auto info = reinterpret_cast<PROCESS_HANDLE_SNAPSHOT_INFORMATION*>(buffer.get());
        for (ULONG i = 0; i < info->NumberOfHandles; i++) {
                HANDLE h = info->Handles[i].HandleValue;
                HANDLE hTarget;
                if (!::DuplicateHandle(hProcess, h, ::GetCurrentProcess(), &hTarget,
                        0, FALSE, DUPLICATE_SAME_ACCESS)) {
                        continue;        // move to next handle
                }
                BYTE nameBuffer[1 << 10];
                auto status = ::NtQueryObject(hTarget, ObjectNameInformation,
                        nameBuffer, sizeof(nameBuffer), nullptr);
                auto name = reinterpret_cast<UNICODE_STRING*>(nameBuffer);
                if (name->Buffer&&::wcsnicmp(name->Buffer, targetName, len) == 0) {
                        // found it!
                        ::DuplicateHandle(hProcess, h, ::GetCurrentProcess(), &h,
                                0, false, DUPLICATE_CLOSE_SOURCE);
                        printf("Found it! and closed it!\n");
                }
                if (name->Buffer&&::wcsnicmp(name->Buffer, targetName2, len2) == 0) {
                        // found it!
                        ::DuplicateHandle(hProcess, h, ::GetCurrentProcess(), &h,
                                0, false, DUPLICATE_CLOSE_SOURCE);
                        printf("Found it! and closed it!\n");
                }
        }
         
        return 0;
}

最终效果:
 

分享到:
打赏
未经允许不得转载:

作者: cj13888, 转载或复制请以 超链接形式 并注明出处 易启发资源网
原文地址: 《微信双开代码实现》 发布于2020-7-17

评论


切换注册

登录

忘记密码?

您也可以使用第三方帐号快捷登录

切换登录

注册

微信双开代码实现

长按图片转发给朋友

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏