WeChatFerry/WeChatFerry/sdk/injector.cpp
2024-06-22 22:57:30 +08:00

193 lines
5.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "framework.h"
#include "psapi.h"
#include <filesystem>
#include <string>
#include "injector.h"
#include "../com/util.h"
using namespace std;
HMODULE GetTargetModuleBase(HANDLE process, string dll)
{
DWORD cbNeeded;
HMODULE moduleHandleList[512];
BOOL ret = EnumProcessModulesEx(process, moduleHandleList, sizeof(moduleHandleList), &cbNeeded, LIST_MODULES_64BIT);
if (!ret) {
MessageBox(NULL, L"获取模块失败", L"GetTargetModuleBase", 0);
return NULL;
}
if (cbNeeded > sizeof(moduleHandleList)) {
MessageBox(NULL, L"模块数量过多", L"GetTargetModuleBase", 0);
return NULL;
}
DWORD processCount = cbNeeded / sizeof(HMODULE);
char moduleName[32];
for (DWORD i = 0; i < processCount; i++) {
GetModuleBaseNameA(process, moduleHandleList[i], moduleName, 32);
if (!strncmp(dll.c_str(), moduleName, dll.size())) {
return moduleHandleList[i];
}
}
return NULL;
}
HANDLE InjectDll(DWORD pid, LPCWSTR dllPath, HMODULE *injectedBase)
{
HANDLE hThread;
SIZE_T cszDLL = (wcslen(dllPath) + 1) * sizeof(WCHAR);
// 1. 打开目标进程
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (hProcess == NULL) {
MessageBox(NULL, L"打开进程失败", L"InjectDll", 0);
return NULL;
}
// 2. 在目标进程的内存里开辟空间
LPVOID pRemoteAddress = VirtualAllocEx(hProcess, NULL, cszDLL, MEM_COMMIT, PAGE_READWRITE);
if (pRemoteAddress == NULL) {
MessageBox(NULL, L"DLL 路径写入失败", L"InjectDll", 0);
return NULL;
}
// 3. 把 dll 的路径写入到目标进程的内存空间中
WriteProcessMemory(hProcess, pRemoteAddress, dllPath, cszDLL, NULL);
// 3. 创建一个远程线程,让目标进程调用 LoadLibrary
HMODULE k32 = GetModuleHandle(L"kernel32.dll");
if (k32 == NULL) {
MessageBox(NULL, L"获取 kernel32 失败", L"InjectDll", 0);
return NULL;
}
FARPROC libAddr = GetProcAddress(k32, "LoadLibraryW");
if (!libAddr) {
MessageBox(NULL, L"获取 LoadLibrary 失败", L"InjectDll", 0);
return NULL;
}
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)libAddr, pRemoteAddress, 0, NULL);
if (hThread == NULL) {
VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE);
CloseHandle(hProcess);
MessageBox(NULL, L"CreateRemoteThread 失败", L"InjectDll", 0);
return NULL;
}
WaitForSingleObject(hThread, -1);
CloseHandle(hThread);
*injectedBase = GetTargetModuleBase(hProcess, filesystem::path(Wstring2String(dllPath)).filename().string());
VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE);
// CloseHandle(hProcess); // Close when exit
return hProcess;
}
bool EjectDll(HANDLE process, HMODULE dllBase)
{
HANDLE hThread = NULL;
// 使目标进程调用 FreeLibrary卸载 DLL
HMODULE k32 = GetModuleHandle(L"kernel32.dll");
if (k32 == NULL) {
MessageBox(NULL, L"获取 kernel32 失败", L"InjectDll", 0);
return NULL;
}
FARPROC libAddr = GetProcAddress(k32, "FreeLibraryAndExitThread");
if (!libAddr) {
MessageBox(NULL, L"获取 FreeLibrary 失败", L"InjectDll", 0);
return NULL;
}
hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)libAddr, (LPVOID)dllBase, 0, NULL);
if (hThread == NULL) {
MessageBox(NULL, L"FreeLibrary 调用失败!", L"EjectDll", 0);
return false;
}
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
CloseHandle(process);
return true;
}
static UINT64 GetFuncOffset(LPCWSTR dllPath, LPCSTR funcName)
{
HMODULE dll = LoadLibrary(dllPath);
if (dll == NULL) {
MessageBox(NULL, L"获取 DLL 失败", L"GetFuncOffset", 0);
return 0;
}
LPVOID absAddr = GetProcAddress(dll, funcName);
UINT64 offset = (UINT64)absAddr - (UINT64)dll;
FreeLibrary(dll);
return offset;
}
bool CallDllFunc(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, LPDWORD ret)
{
UINT64 offset = GetFuncOffset(dllPath, funcName);
if (offset == 0) {
return false;
}
UINT64 pFunc = (UINT64)dllBase + GetFuncOffset(dllPath, funcName);
if (pFunc <= (UINT64)dllBase) {
return false;
}
HANDLE hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, NULL, 0, NULL);
if (hThread == NULL) {
return false;
}
WaitForSingleObject(hThread, INFINITE);
if (ret != NULL) {
GetExitCodeThread(hThread, ret);
}
CloseHandle(hThread);
return true;
}
bool CallDllFuncEx(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, LPVOID parameter, size_t sz,
LPDWORD ret)
{
UINT64 offset = GetFuncOffset(dllPath, funcName);
if (offset == 0) {
return false;
}
UINT64 pFunc = (UINT64)dllBase + GetFuncOffset(dllPath, funcName);
if (pFunc <= (UINT64)dllBase) {
return false;
}
LPVOID pRemoteAddress = VirtualAllocEx(process, NULL, sz, MEM_COMMIT, PAGE_READWRITE);
if (pRemoteAddress == NULL) {
MessageBox(NULL, L"申请内存失败", L"CallDllFuncEx", 0);
return NULL;
}
WriteProcessMemory(process, pRemoteAddress, parameter, sz, NULL);
HANDLE hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, pRemoteAddress, 0, NULL);
if (hThread == NULL) {
VirtualFree(pRemoteAddress, 0, MEM_RELEASE);
MessageBox(NULL, L"远程调用失败", L"CallDllFuncEx", 0);
return false;
}
WaitForSingleObject(hThread, INFINITE);
VirtualFree(pRemoteAddress, 0, MEM_RELEASE);
if (ret != NULL) {
GetExitCodeThread(hThread, ret);
}
CloseHandle(hThread);
return true;
}