本文章主要写怎么用 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]
\`