momo_eqM5IR · 2022年05月04日

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]
\`

推荐阅读
关注数
0
文章数
2
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息