最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++ 微信多開的實現(xiàn)

 更新時間:2022年02月16日 09:25:52   作者:喬安生  
本文主要介紹了C++ 微信多開的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

應(yīng)用是如何判斷多開

一、通過查找窗口標(biāo)題或者類名來判斷程序是否正在運行。

二、通過互斥對象確定程序是否運行,大多數(shù)軟件都是使用CreateMutexW 判斷多開的。

三、內(nèi)存映射物理文件,控制多開。

微信是使用 CreateMutexW 函數(shù)判斷多開的。

CreateMutexW 是如何判斷多開的。

微軟 MSDN 文檔

CreateMutexW 這個函數(shù)就是根據(jù)變量創(chuàng)建一個鎖,下回再用相同的變量調(diào)用CreateMutexW 的時候就可以控制是否允許多開。

如何找到微信中的 CreateMutexW 方法和互斥體

使用 procexp.exe 尋找互斥體,這個軟件是微軟官方出的 微軟官網(wǎng)下載地址

登陸微信后

打開 Process Explorer

找到微信的進(jìn)程 WeChat.exe

CTRL + L 查看微信這個進(jìn)程占用的各種資源

根據(jù)這個字符串的名字判斷出來的_WeChat_App_Instance_Identity_Mutex_Name 這個字符串就是微信的互斥體

找到 CreateMutexW 這個函數(shù)

使用 OD 直接在內(nèi)存中找 CreateMutexW 方法,并調(diào)試 CreateMutexW 方法,手動修改互斥體,啟動多個微信實例。

使用 OD 打開微信

CTRL + G 搜索 CreateMutexW 方法

跳轉(zhuǎn)到 CreateMutexW 方法后,在這個位置打一個斷點 F2

打完斷點之后繼續(xù)運行

在堆棧窗口可以看到 CreateMutexW 方法傳遞的三個參數(shù)

第一個參數(shù):NULL

第二個參數(shù):FALSE

第三個參數(shù):_WeChat_App_Instance_Identity_Mutex_Name

獲取到 _WeChat_App_Instance_Identity_Mutex_Name 這個互斥體在內(nèi)存中的地址 02BBB198

使用 CE 修改 _WeChat_App_Instance_Identity_Mutex_Name 這個字符串

打開CE后選擇進(jìn)程

選擇當(dāng)前進(jìn)程

選擇微信進(jìn)程

打開

點擊 手動添加地址

輸入互斥體的內(nèi)存地址

選擇字符串

字符串長度設(shè)置成110

勾選 Unicode

選擇數(shù)值這列,雙擊 _WeChat_App_Instance_Identity_Mutex_Name

在彈框中修改一下這個字符串

內(nèi)存修改完成,回到 OD

F2 取消斷點

繼續(xù)運行,直到打開一個微信

這個微信他身上的互斥體就是手動修改的那個字符串

通過正常途徑在啟動一個微信

正常啟動

正常登陸

代碼思路

思路
PC:啟動微信到登陸頁面(那個頁面都行,只要微信進(jìn)程起來就可以了)
代碼:
一、提升當(dāng)前進(jìn)程權(quán)限,提升到最大
二、獲取當(dāng)前操作系統(tǒng)中指定的所有進(jìn)程(多開的時候會有多個微信進(jìn)程,進(jìn)程名字是一模一樣的)
三、獲取到系統(tǒng)中所有資源(內(nèi)存中的資源,包含 文件,路徑,鎖,事件,線程等等)
四、通過指定的進(jìn)程和已找到的資源,匹配到防多開的那個互斥體
4.1 干掉這個互斥體
PC:可以正常啟動下一個微信

使用
啟動微信后,如果想在啟動一個微信,執(zhí)行一遍代碼就可以正常啟動了
微信版本:3.4.5.27
已在三臺電腦上測試(物理機)
理論上應(yīng)該是所有版本的微信都能用 (只要這個互斥體的字符串不變)

缺點:直接修改了微信進(jìn)程中的資源

/*
    processName 微信進(jìn)程名稱
    nutexName 微信互斥體字符串
*/
void CloseMutex(const WCHAR* processName, const WCHAR* nutexName) {
    // 提升當(dāng)前進(jìn)程的訪問權(quán)限
    ElevatePrivileges();
    // 找到所有的指定的進(jìn)程 (多開的情況下會有多個)
    vector<DWORD> pidList;
    pidList = GetProcessIdsByName((WCHAR*)processName);
    if (pidList.size() == 0)
    {
        // 沒有開啟或者沒有找到指定的進(jìn)程
        return;
    }
    // 獲取到操作系統(tǒng)所有進(jìn)程的資源
    LPVOID lp = GetSystemProcessHandleInfo();
    // 遍歷所有的指定進(jìn)程
    for (int i = 0; i < pidList.size(); i++)
    {
        // 遍歷從系統(tǒng)中獲取到的所有進(jìn)程 與 指定進(jìn)程進(jìn)行匹配
        // 遍歷指定進(jìn)程中的資源
        // 找到互斥體
        // 直接干掉這個互斥體
        // 完成,后面就可以繼續(xù)打開PC端微信了
        EnumObjInfo(lp, pidList[i], processName);
    }
}

提升權(quán)限

bool ElevatePrivileges() {
    HANDLE hToken = NULL;
    //打開當(dāng)前進(jìn)程的訪問令牌
    int hRet = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken);
    if (hRet)
    {
        TOKEN_PRIVILEGES tp;
        tp.PrivilegeCount = 1;
        //取得描述權(quán)限的LUID
        LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        //調(diào)整訪問令牌的權(quán)限
        AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
        CloseHandle(hToken);
    }
    return TRUE;
}

根據(jù)進(jìn)程名字,獲取到系統(tǒng)中全部的進(jìn)程信息

vector<DWORD> GetProcessIdsByName(WCHAR* processName) {
    vector<DWORD> pidList;
    //HANDLE 
    HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hProcessSnap == FALSE)
    {
        return pidList;
    }
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(PROCESSENTRY32);

    BOOL bRet = Process32First(hProcessSnap, &pe32);
    while (bRet)
    {
        if (wcscmp(pe32.szExeFile, processName) == 0)
        {
            pidList.push_back(pe32.th32ProcessID);
        }
        bRet = Process32Next(hProcessSnap, &pe32);
    }
    CloseHandle(hProcessSnap);
    return pidList;
}

獲取系統(tǒng)中的所有資源

LPVOID GetSystemProcessHandleInfo()
{
    ULONG cbBuffer = 0x4000;
    LPVOID pBuffer = NULL;
    NTSTATUS sts;
    do
    {
        pBuffer = malloc(cbBuffer);
        if (pBuffer == NULL)
        {
            return NULL;
        }
        memset(pBuffer, 0, cbBuffer);
        hNtDLL = GetModuleHandle(TEXT("ntdll.dll"));
        if (!hNtDLL)
            return 0;

        ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION)
            GetProcAddress(hNtDLL, "ZwQuerySystemInformation");
        sts = ZwQuerySystemInformation(SystemHandleInformation, pBuffer, cbBuffer, NULL);
        if (sts == STATUS_INFO_LENGTH_MISMATCH)
        {
            free(pBuffer);
            pBuffer = NULL;
            cbBuffer = cbBuffer + 0x4000; // 初始分配的空間不足+4000h
        }
    } while (sts == STATUS_INFO_LENGTH_MISMATCH);
    return pBuffer;
}

匹配到互斥體,并干掉他

void EnumObjInfo(LPVOID pBuffer, DWORD pid, const WCHAR* processName) {
    char szType[128] = { 0 };
    char szName[512] = { 0 };
    DWORD dwFlags = 0;
    POBJECT_NAME_INFORMATION pNameInfo;
    POBJECT_NAME_INFORMATION pNameType;
    PSYSTEM_HANDLE_INFORMATION_EX pInfo = (PSYSTEM_HANDLE_INFORMATION_EX)pBuffer;
    ULONG OldPID = 0;
    for (DWORD i = 0; i < pInfo->NumberOfHandles; i++)
    {
        if (OldPID != pInfo->Information[i].ProcessId)
        {
            if (pInfo->Information[i].ProcessId == pid)
            {
                HANDLE newHandle;
                NtQueryObject p_NtQueryObject = (NtQueryObject)GetProcAddress(hNtDLL, "NtQueryObject");
                if (p_NtQueryObject == NULL)
                {
                    return;
                }
                DuplicateHandle(OpenProcess(PROCESS_ALL_ACCESS, FALSE, pInfo->Information[i].ProcessId), (HANDLE)pInfo->Information[i].Handle, GetCurrentProcess(), &newHandle, DUPLICATE_SAME_ACCESS, FALSE, DUPLICATE_SAME_ACCESS);
                NTSTATUS status1 = p_NtQueryObject(newHandle, ObjectNameInformation, szName, 512, &dwFlags);
                NTSTATUS status2 = p_NtQueryObject(newHandle, ObjectTypeInformation, szType, 128, &dwFlags);

                pNameInfo = (POBJECT_NAME_INFORMATION)szName;
                pNameType = (POBJECT_NAME_INFORMATION)szType;

                if (strcmp(szName, "") && strcmp(szType, "") && status1 != 0xc0000008 && status2 != 0xc0000008)
                {
                    if (wcsstr(pNameType->Name.Buffer, L"Mutant"))
                    {
                        pNameInfo = (POBJECT_NAME_INFORMATION)szName;
                        pNameType = (POBJECT_NAME_INFORMATION)szType;
                        if (wcsstr(pNameInfo->Name.Buffer, L"_WeChat_App_Instance_Identity_Mutex_Name"))
                        {
                            if (DuplicateHandle(OpenProcess(PROCESS_ALL_ACCESS, FALSE, pInfo->Information[i].ProcessId), (HANDLE)pInfo->Information[i].Handle, GetCurrentProcess(), &newHandle, 0, FALSE, DUPLICATE_CLOSE_SOURCE))
                            {
                                CloseHandle(newHandle);
                            };
                        }
                    }
                }
            }
        }
    }
}

 到此這篇關(guān)于C++ 微信多開的實現(xiàn)的文章就介紹到這了,更多相關(guān)C++ 微信多開內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用C++實現(xiàn)迷宮游戲

    使用C++實現(xiàn)迷宮游戲

    這篇文章主要為大家詳細(xì)介紹了C++實現(xiàn)迷宮游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • 在C語言中輸入中文字符串講解

    在C語言中輸入中文字符串講解

    這篇文章主要介紹了在C語言中輸入中文字符串講解,本文通過概念和案例相結(jié)合講述了如何在C語言中使用中文,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • 深入解讀C語言中的符號常量EOF

    深入解讀C語言中的符號常量EOF

    這篇文章主要介紹了C語言中的符號常量EOF,文中還介紹了EOF的驗證和打印方法,需要的朋友可以參考下
    2015-11-11
  • C++實現(xiàn)班級成績管理系統(tǒng)

    C++實現(xiàn)班級成績管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C++實現(xiàn)班級成績管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C++?重載運算符在HotSpot?VM中的應(yīng)用小結(jié)

    C++?重載運算符在HotSpot?VM中的應(yīng)用小結(jié)

    C++支持運算符重載,對于Java開發(fā)者來說,這個可能比較陌生一些,因為Java不支持運算符重載,下面介紹一下HotSpot?VM中的運算符重載,感興趣的朋友跟隨小編一起看看吧
    2023-09-09
  • 深入講解Socket原理

    深入講解Socket原理

    這篇文章深入的講解Socket原理,并附帶實例代碼。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2021-12-12
  • 對for循環(huán)中表達(dá)式和循環(huán)體的執(zhí)行順序詳解

    對for循環(huán)中表達(dá)式和循環(huán)體的執(zhí)行順序詳解

    今天小編就為大家分享一篇對for循環(huán)中表達(dá)式和循環(huán)體的執(zhí)行順序詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-06-06
  • C++ 實現(xiàn)帶監(jiān)視哨的順序查找算法

    C++ 實現(xiàn)帶監(jiān)視哨的順序查找算法

    這篇文章主要介紹了C++ 實現(xiàn)帶監(jiān)視哨的順序查找算法,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03
  • C語言尋找無向圖兩點間的最短路徑

    C語言尋找無向圖兩點間的最短路徑

    這篇文章主要為大家詳細(xì)介紹了C語言尋找無向圖兩點間的最短路徑,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • C語言接口與實現(xiàn)方法實例詳解

    C語言接口與實現(xiàn)方法實例詳解

    這篇文章主要介紹了C語言接口與實現(xiàn)方法,包括接口的概念、實現(xiàn)方法及抽象數(shù)據(jù)類型等,并配合實例予以說明,需要的朋友可以參考下
    2014-09-09

最新評論

徐汇区| 宝山区| 南京市| 泾阳县| 弥勒县| 隆德县| 永城市| 依兰县| 图木舒克市| 丰城市| 临颍县| 绥化市| 武强县| 吉首市| 铁岭县| 汉寿县| 乌鲁木齐市| 拉孜县| 义乌市| 建始县| 大悟县| 滦平县| 周宁县| 青州市| 景洪市| 涿鹿县| 睢宁县| 长丰县| 高台县| 长白| 军事| 田林县| 门头沟区| 宜昌市| 汉川市| 信宜市| 塔河县| 启东市| 济阳县| 五莲县| 边坝县|