c#调用c++多开个人企业微信并注入微信源码api接口

本文章主要写怎么用c#调用c++写的dll,然后用这个c++写的dll,把自己写的其他dll注入微信并多开。

开发工具 Visual Studio 2019,开发语言:c#,c++,开发环境:win10

下面是c#的代码,是winform窗体程序:其中wechathelper.dll 是自己写的需要注入到微信的dll,wechatload.dll 是c++封装的动态链接库,里面的代码作用是多开微信和把wechathelper.dll注入微信。下面的代码的作用是调用 wechatload.dll ,来执行里面的函数。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace wechatmore
{

    public partial class Form1 : Form
    {
        string dllPath = System.AppDomain.CurrentDomain.BaseDirectory.ToString() + "\\wechathelper.dll";

        [DllImport("wechatload.dll")]
        public static extern int WeChatMultiOpen(string dllPath);

        [DllImport("wechatload.dll")]
        public static extern int WeChatInject(string dllPath);

        public Form1()
        {
            InitializeComponent();
        }
        int i = 0;
        /// <summary>
        /// 打开新微信
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnopennew_Click(object sender, EventArgs e)
        {
            int pid = WeChatMultiOpen(dllPath);
            if (pid > 0)
            {
                i++;
                this.txtlog.AppendText("进程:"+pid + ",成功打开了" + i + "个微信!" + Environment.NewLine);
            }
            else
            {
                MessageBox.Show("打开失败");
            }
        }

        /// <summary>
        /// 注入已打开的微信
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btninitwx_Click(object sender, EventArgs e)
        {
            int issuc = WeChatInject(dllPath);
            if (issuc > 0)
            {
                this.txtlog.AppendText("注入成功!" + Environment.NewLine);
            }
        }
    }
}

下面的c++动态链接库代码,作用是多开和注入自己写的其他dll到微信,用上面写的winform程序进行调用这个生成的dll

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <string>
#include "dllmain.h"
#include <TlHelp32.h>
#include <Shlwapi.h>
#include "atlconv.h"
#include <tchar.h>

#pragma comment(lib, "shlwapi")


#define WECHAT_PROCESS_NAME "WeChat.exe"
using namespace std;

int PatchWeChat();

BOOL ElevatePrivileges();
int GetProcIds(DWORD* Pids);
BOOL IsTargetPid(DWORD Pid, DWORD* Pids, int num);
HANDLE DuplicateHandleEx(DWORD pid, HANDLE h, DWORD flags);
int OpenWeChat(char* dllPath, int isCreateGolb);
BOOL CheckIsInject(DWORD dwProcessid);
DWORD ProcessNameFindPID(const char* ProcessName);


#pragma region 打开微信并注入


BOOL CheckIsInject(DWORD dwProcessid)
{
    HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
    //初始化模块信息结构体
    MODULEENTRY32 me32 = { sizeof(MODULEENTRY32) };
    //创建模块快照 1 快照类型 2 进程ID
    hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessid);
    //如果句柄无效就返回false
    if (hModuleSnap == INVALID_HANDLE_VALUE)
    {
        MessageBoxA(NULL, "创建模块快照失败", "错误", MB_OK);
        return FALSE;
    }
    //通过模块快照句柄获取第一个模块的信息
    if (!Module32First(hModuleSnap, &me32))
    {
        MessageBoxA(NULL, "获取第一个模块的信息失败", "错误", MB_OK);
        //获取失败则关闭句柄
        CloseHandle(hModuleSnap);
        return FALSE;
    }
    do
    {
        if (StrCmpW(me32.szModule,L"wechathelper.dll") == 0)
        {
            return FALSE;
        }

    } while (Module32Next(hModuleSnap, &me32));
    return TRUE;
}



int OpenWeChat(char* dllPath, int isCreateGolb)
{
    int pid = 0;
    //HKEY_CURRENT_USER\Software\Tencent\WeChat InstallPath = xx
    HKEY hKey = NULL;
    if (ERROR_SUCCESS != RegOpenKey(HKEY_CURRENT_USER, L"Software\\Tencent\\WeChat", &hKey))
    {
        return pid;
    }

    DWORD Type = REG_SZ;
    WCHAR Path[MAX_PATH] = { 0 };
    DWORD cbData = MAX_PATH * sizeof(WCHAR);
    if (ERROR_SUCCESS != RegQueryValueEx(hKey, L"InstallPath", 0, &Type, (LPBYTE)Path, &cbData))
    {
        goto __exit;
    }

    PathAppend(Path, L"WeChat.exe");

    //ShellExecute(NULL, L"Open", Path, NULL, NULL, SW_SHOW);

__exit:
    if (hKey)
    {
        RegCloseKey(hKey);
    }

    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(si));
    ZeroMemory(&pi, sizeof(pi));
    CreateProcess(Path, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
    HWND  hWechatMainForm = NULL;
    //WeChatLoginWndForPC
    while (NULL == hWechatMainForm)
    {
        hWechatMainForm = FindWindow(TEXT("WeChatLoginWndForPC"), NULL);
        Sleep(500);
    }
    if (NULL == hWechatMainForm)
    {
        return FALSE;
    }
    DWORD dwPid = pi.dwProcessId;
    HANDLE wxPid = pi.hProcess;
    pid = dwPid;
    //检测dll是否已经注入
    if (CheckIsInject(dwPid))
    {
        //打开进程
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
        if (hProcess == NULL)
        {
            MessageBoxA(NULL, "进程打开失败", "错误", 0);
            return FALSE;
        }
        //在微信进程中申请内存
        LPVOID pAddress = VirtualAllocEx(hProcess, NULL, MAX_PATH, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        if (pAddress == NULL)
        {
            MessageBoxA(NULL, "内存分配失败", "错误", 0);
            return FALSE;
        }
        //写入dll路径到微信进程
        if (WriteProcessMemory(hProcess, pAddress, dllPath, MAX_PATH, NULL) == 0)
        {
            MessageBoxA(NULL, "路径写入失败", "错误", 0);
            return FALSE;
        }

        //获取LoadLibraryA函数地址
        FARPROC pLoadLibraryAddress = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");
        if (pLoadLibraryAddress == NULL)
        {
            MessageBoxA(NULL, "获取LoadLibraryA函数地址失败", "错误", 0);
            return FALSE;
        }
        //远程线程注入dll
        HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pLoadLibraryAddress, pAddress, 0, NULL);
        if (hRemoteThread == NULL)
        {
            MessageBoxA(NULL, "远程线程注入失败", "错误", 0);
            return FALSE;
        }

        CloseHandle(hRemoteThread);
        CloseHandle(hProcess);
    }
    else
    {
        MessageBoxA(NULL, "dll已经注入,请勿重复注入", "提示", 0);
        return FALSE;
    }
    return pid;
}



#pragma endregion


#pragma region hook互斥体




int PatchWeChat()
{
    DWORD dwSize = 0;
    POBJECT_NAME_INFORMATION pNameInfo;
    POBJECT_NAME_INFORMATION pNameType;
    PVOID pbuffer = NULL;
    NTSTATUS Status;
    int nIndex = 0;
    DWORD dwFlags = 0;
    char szType[128] = { 0 };
    char szName[512] = { 0 };

    ElevatePrivileges();

    DWORD Pids[100] = { 0 };

    DWORD Num = GetProcIds(Pids);
    if (Num == 0)
    {
        return 0;
    }

    if (!ZwQuerySystemInformation)
    {
        goto Exit0;
    }

    pbuffer = VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_READWRITE);

    if (!pbuffer)
    {
        goto Exit0;
    }

    Status = ZwQuerySystemInformation(SystemHandleInformation, pbuffer, 0x1000, &dwSize);

    if (!NT_SUCCESS(Status))
    {
        if (STATUS_INFO_LENGTH_MISMATCH != Status)
        {
            goto Exit0;
        }
        else
        {
            // 这里大家可以保证程序的正确性使用循环分配稍好
            if (NULL != pbuffer)
            {
                VirtualFree(pbuffer, 0, MEM_RELEASE);
            }

            if (dwSize * 2 > 0x4000000)  // MAXSIZE
            {
                goto Exit0;
            }

            pbuffer = VirtualAlloc(NULL, dwSize * 2, MEM_COMMIT, PAGE_READWRITE);

            if (!pbuffer)
            {
                goto Exit0;
            }

            Status = ZwQuerySystemInformation(SystemHandleInformation, pbuffer, dwSize * 2, NULL);

            if (!NT_SUCCESS(Status))
            {
                goto Exit0;
            }
        }
    }

    {
        PSYSTEM_HANDLE_INFORMATION1 pHandleInfo = (PSYSTEM_HANDLE_INFORMATION1)pbuffer;

        for (nIndex = 0; nIndex < pHandleInfo->NumberOfHandles; nIndex++)
        {
            if (IsTargetPid(pHandleInfo->Handles[nIndex].UniqueProcessId, Pids, Num))
            {
                //
                HANDLE hHandle = DuplicateHandleEx(pHandleInfo->Handles[nIndex].UniqueProcessId,
                    (HANDLE)pHandleInfo->Handles[nIndex].HandleValue,
                    DUPLICATE_SAME_ACCESS
                );
                if (hHandle == NULL) continue;

                Status = NtQueryObject(hHandle, ObjectNameInformation, szName, 512, &dwFlags);

                if (!NT_SUCCESS(Status))
                {
                    CloseHandle(hHandle);
                    continue;
                }

                Status = NtQueryObject(hHandle, ObjectTypeInformation, szType, 128, &dwFlags);

                if (!NT_SUCCESS(Status))
                {
                    CloseHandle(hHandle);
                    continue;
                }

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

                WCHAR TypName[1024] = { 0 };
                WCHAR Name[1024] = { 0 };

                wcsncpy_s(TypName, (WCHAR*)pNameType->Name.Buffer, pNameType->Name.Length / 2);
                wcsncpy_s(Name, (WCHAR*)pNameInfo->Name.Buffer, pNameInfo->Name.Length / 2);

                // 匹配是否为需要关闭的句柄名称
                if (0 == wcscmp(TypName, L"Mutant"))
                {
                    //WeChat_aj5r8jpxt_Instance_Identity_Mutex_Name
                    //if (wcsstr(Name, L"_WeChat_App_Instance_Identity_Mutex_Name"))
                    if (wcsstr(Name, L"_WeChat_") &&
                        wcsstr(Name, L"_Instance_Identity_Mutex_Name"))
                    {
                        CloseHandle(hHandle);

                        hHandle = DuplicateHandleEx(pHandleInfo->Handles[nIndex].UniqueProcessId,
                            (HANDLE)pHandleInfo->Handles[nIndex].HandleValue,
                            DUPLICATE_CLOSE_SOURCE
                        );

                        if (hHandle)
                        {
                            //printf("+ Patch wechat success!\n");
                            CloseHandle(hHandle);
                        }
                        else
                        {
                            //printf("- Patch error: %d\n", GetLastError());
                        }

                        goto Exit0;
                    }
                }

                CloseHandle(hHandle);
            }

        }
    }
Exit0:
    if (NULL != pbuffer)
    {
        VirtualFree(pbuffer, 0, MEM_RELEASE);
    }

    return 0;
}


//进程提权
BOOL ElevatePrivileges()
{
    HANDLE hToken;
    TOKEN_PRIVILEGES tkp;
    tkp.PrivilegeCount = 1;
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
        return FALSE;
    LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid);
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
    {
        return FALSE;
    }

    return TRUE;
}


int GetProcIds(DWORD* Pids)
{
    PROCESSENTRY32 pe32 = { sizeof(pe32) };
    int num = 0;

    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnap)
    {
        if (Process32First(hSnap, &pe32))
        {
            do {
                if (!_wcsicmp(L"WeChat.exe", pe32.szExeFile))
                {
                    if (Pids)
                    {
                        Pids[num++] = pe32.th32ProcessID;
                    }
                }
            } while (Process32Next(hSnap, &pe32));
        }
        CloseHandle(hSnap);
    }

    return num;
}

BOOL IsTargetPid(DWORD Pid, DWORD* Pids, int num)
{
    for (int i = 0; i < num; i++)
    {
        if (Pid == Pids[i])
        {
            return TRUE;
        }
    }
    return FALSE;
}

HANDLE DuplicateHandleEx(DWORD pid, HANDLE h, DWORD flags)
{
    HANDLE hHandle = NULL;

    HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (hProc)
    {
        if (!DuplicateHandle(hProc,
            (HANDLE)h, GetCurrentProcess(),
            &hHandle, 0, FALSE, /*DUPLICATE_SAME_ACCESS*/flags))
        {
            hHandle = NULL;
        }
    }

    CloseHandle(hProc);
    return hHandle;
}

#pragma endregion



#pragma region 单独注入dll



BOOL InjectDll(char* dllPath)
{
    //获取微信Pid
    DWORD dwPid = ProcessNameFindPID(WECHAT_PROCESS_NAME);

    if (dwPid == 0) 
    {
        MessageBoxA(NULL, "没有找到微信进程 请先启动微信", "错误", 0);
        return FALSE;
    }

    //检测dll是否已经注入
    if (CheckIsInject(dwPid))
    {
        //打开进程
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
        if (hProcess == NULL)
        {
            MessageBoxA(NULL, "进程打开失败", "错误", 0);
            return FALSE;
        }
        //在微信进程中申请内存
        LPVOID pAddress = VirtualAllocEx(hProcess, NULL, MAX_PATH, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        if (pAddress == NULL)
        {
            MessageBoxA(NULL, "内存分配失败", "错误", 0);
            return FALSE;
        }
        //写入dll路径到微信进程
        if (WriteProcessMemory(hProcess, pAddress, dllPath, MAX_PATH, NULL) == 0)
        {
            MessageBoxA(NULL, "路径写入失败", "错误", 0);
            return FALSE;
        }

        //获取LoadLibraryA函数地址
        FARPROC pLoadLibraryAddress = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");
        if (pLoadLibraryAddress == NULL)
        {
            MessageBoxA(NULL, "获取LoadLibraryA函数地址失败", "错误", 0);
            return FALSE;
        }
        //远程线程注入dll
        HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pLoadLibraryAddress, pAddress, 0, NULL);
        if (hRemoteThread == NULL)
        {
            MessageBoxA(NULL, "远程线程注入失败", "错误", 0);
            return FALSE;
        }

        CloseHandle(hRemoteThread);
        CloseHandle(hProcess);
    }
    else
    {
        MessageBoxA(NULL, "dll已经注入,请勿重复注入", "提示", 0);
        return FALSE;
    }

    return TRUE;
}


DWORD ProcessNameFindPID(const char* ProcessName)
{
    PROCESSENTRY32 pe32 = { 0 };
    pe32.dwSize = sizeof(PROCESSENTRY32);
    HANDLE hProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
    if (Process32First(hProcess, &pe32) == TRUE)
    {
        do
        {
            USES_CONVERSION;
            if (strcmp(ProcessName, W2A(pe32.szExeFile)) == 0)
            {
                return pe32.th32ProcessID;
            }
        } while (Process32Next(hProcess, &pe32));
    }
    return 0;
}

#pragma endregion




/// <summary>
/// 多开并注入微信
/// </summary>
/// <param name="dllPath">要注入的dll的绝对路径</param>
/// <returns></returns>
extern "C" _declspec(dllexport) int __stdcall WeChatMultiOpen(char* dllPath)
{
    PatchWeChat();
    int pid=OpenWeChat(dllPath, true);
    return pid;
}

/// <summary>
/// 只注入微信
/// </summary>
/// <param name="dllPath">要注入的dll的绝对路径</param>
/// <returns></returns>
extern "C" _declspec(dllexport) int __stdcall WeChatInject(char* dllPath)
{

    int pid = InjectDll(dllPath);
    return pid;
}

目前已实现个微和企微的api接口,支持其他语言二次开发各种有趣的功能,欢迎技术交流:


HWND Qq[]=2645542961;
wchar_t buffdata[0x1030]

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 1

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!