吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 14712|回复: 37
收起左侧

[C&C++ 原创] 微信双开代码实现

  [复制链接]
BeneficialWeb 发表于 2020-3-22 23:34
   互斥量是一个很好玩的东西,可以实现进程的单例。WeChat也是用的Mutant技术实现的防止多开。无事练习下Win32 API编程,于是便有了此贴。
   实现双开的原理就是跨进程关闭互斥量句柄。各位看官可以自行完善下面代码实现多开。
   
[C++] 纯文本查看 复制代码
#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;
}



最终效果:
wx.png
   

免费评分

参与人数 10吾爱币 +14 热心值 +9 收起 理由
Jack + 1 用心讨论,共获提升!
461735945 + 1 + 1 谢谢@Thanks!
古月不傲 + 1 + 1 我很赞同!
hezhijian90 + 1 + 1 我很赞同!
涛之雨 + 2 + 1 终于见到讲解原理的大佬了
finally123 + 1 + 1 热心回复!
伤心的笔 + 1 + 1 用心讨论,共获提升!
yang4502981 + 1 热心回复!
凯咪 + 1 + 1 大佬牛逼
苏紫方璇 + 5 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

涛之雨 发表于 2020-3-23 00:49
VIPAccount 发表于 2020-3-23 00:04
楼主牛逼!从代码角度解析了如何双卡,牛!
这里插个楼,也可以用bat实现双开,下面代码保存成.bat文件, ...

还可以在weichat文件夹里放一个bat
[Bash shell] 纯文本查看 复制代码
start WeChat.exe ""
%0

能开几个就看电脑性能了
VIPAccount 发表于 2020-3-23 00:04
楼主牛逼!从代码角度解析了如何双卡,牛!
这里插个楼,也可以用bat实现双开,下面代码保存成.bat文件,双击也可以打开两个微信:
PATH E:\Program Files (x86)\Tencent\WeChat
start WeChat.exe&WeChat.exe

第一行路径为微信安装的跟路径,第二行不变。

点评

WIN10不支持  发表于 2020-3-23 00:50
尔等幼稚 发表于 2020-3-23 11:52
虽然看不懂,但是我电脑微信双开的时候,就是用鼠标快速点击微信图标,能点几次就点几次,最后至少会出现3个登陆界面,我电脑是win7系统,微信是最新版本,多开屡试不爽,大家可以试试
微信截图_20200323115038.png
萌新想学习 发表于 2021-7-16 15:12
虽然看不懂,但是我喜欢用下面的代码
[Asm] 纯文本查看 复制代码
start D:\微信\WeChat\WeChat.exe
start D:\微信\WeChat\WeChat.exe
伤心的笔 发表于 2020-3-22 23:49
666 原来是文件锁
希望这个锁只有这一个用途
suixuersheng 发表于 2020-3-22 23:51
希望只有这一个用途
Parkourr 发表于 2020-3-23 00:05
感谢大佬分享感谢
Crazy开发仔 发表于 2020-3-23 00:08
使用沙箱貌似也可以吧?
sd4060483 发表于 2020-3-23 00:48
跟着大神又学习了
昔日天才 发表于 2020-3-23 02:01
感谢分享
q10123 发表于 2020-3-23 04:38
厉害了。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 08:32

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表