C++/CLI 注入是可能的吗?
C++/CLI injection is possible?
所以我的 C++/CLI 应用程序将自身注入到目标进程中。
但是虽然注入似乎成功了,但入口点并没有被调用。这是我的注射器:
#include "stdafx.h"
#include <Windows.h>
#include <TlHelp32.h>
#include <string>
#include <stdlib.h>
#include <comdef.h>
#include "Hooking.h"
#include "HCommonEnsureCleanup.h"
VOID Hooking::HookProcess()
{
DWORD firefox = Hooking::FindProcessId("firefox.exe");
Inject(firefox);
}
BOOL Hooking::Inject(DWORD pID)
{
const wchar_t* DLL_NAME = (const wchar_t*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(System::Windows::Forms::Application::ExecutablePath);
HANDLE Proc;
HMODULE hLib;
char buf[50] = { 0 };
LPVOID RemoteString, LoadLibAddy;
if (!pID)
return false;
Proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
if (!Proc)
{
return false;
}
LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");
RemoteString = (LPVOID)VirtualAllocEx(Proc, NULL, (wcslen(DLL_NAME) + 1) * sizeof(wchar_t), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(Proc, (LPVOID)RemoteString, DLL_NAME, (wcslen(DLL_NAME) + 1) * sizeof(wchar_t), NULL);
CreateRemoteThread(Proc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, NULL, NULL);
CloseHandle(Proc);
return true;
}
DWORD Hooking::FindProcessId(const char *processname)
{
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;
DWORD result = NULL;
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == hProcessSnap) return(FALSE);
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hProcessSnap, &pe32))
{
CloseHandle(hProcessSnap);
return(NULL);
}
do
{
if (0 == strcmp(processname, _bstr_t(pe32.szExeFile)))
{
result = pe32.th32ProcessID;
break;
}
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
return result;
}
然后(因为我的程序是可执行的)我创建了一个 dll 入口点:
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
Hooking::HookProcess();
return 0;
}
BOOL WINAPI DllMain(
HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved
)
{
MessageBoxA(NULL, "Injection OK", "Injection OK", NULL);
}
但是,无论是 Dll 还是 exe,我的入口点都没有被调用。所以我在想这可能是因为这个 exe 包含 .Net 代码但在更改它之前我想在这里问一下。
感谢您的宝贵时间
首先将“(wcslen(DLL_NAME) + 1) * sizeof(wchar_t)”改为"wcslen(DLL_NAME)"即可。确保同时更新内存分配。
其次,您将一个 unicode 编码的缓冲区传递给 LoadLibraryA。这是行不通的,因为 LoadLibraryA 不接受 unicode 编码的缓冲区,它需要一个 Ascii 编码的缓冲区。请改用 LoadLibraryW。
第三,您没有进行任何错误检查。不能就假设这两个虚拟内存操作和创建远程线程的操作都会成功,需要检查每个操作的return状态,确保成功,否则就停止追寻注入的套路。这也将深入了解操作失败的原因。您需要将调试器附加到目标进程,以确保内存在分配和写入后也能正常运行。
最后但同样重要的是,确保您有足够的权限来定位目标进程。例如,如果您是 运行 标准权限,则不能将提升的进程作为目标,也不能将启用自我保护的传统安全解决方案作为目标。这里有很多不同的因素。
所以我的 C++/CLI 应用程序将自身注入到目标进程中。 但是虽然注入似乎成功了,但入口点并没有被调用。这是我的注射器:
#include "stdafx.h"
#include <Windows.h>
#include <TlHelp32.h>
#include <string>
#include <stdlib.h>
#include <comdef.h>
#include "Hooking.h"
#include "HCommonEnsureCleanup.h"
VOID Hooking::HookProcess()
{
DWORD firefox = Hooking::FindProcessId("firefox.exe");
Inject(firefox);
}
BOOL Hooking::Inject(DWORD pID)
{
const wchar_t* DLL_NAME = (const wchar_t*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(System::Windows::Forms::Application::ExecutablePath);
HANDLE Proc;
HMODULE hLib;
char buf[50] = { 0 };
LPVOID RemoteString, LoadLibAddy;
if (!pID)
return false;
Proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
if (!Proc)
{
return false;
}
LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");
RemoteString = (LPVOID)VirtualAllocEx(Proc, NULL, (wcslen(DLL_NAME) + 1) * sizeof(wchar_t), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(Proc, (LPVOID)RemoteString, DLL_NAME, (wcslen(DLL_NAME) + 1) * sizeof(wchar_t), NULL);
CreateRemoteThread(Proc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, NULL, NULL);
CloseHandle(Proc);
return true;
}
DWORD Hooking::FindProcessId(const char *processname)
{
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;
DWORD result = NULL;
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == hProcessSnap) return(FALSE);
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hProcessSnap, &pe32))
{
CloseHandle(hProcessSnap);
return(NULL);
}
do
{
if (0 == strcmp(processname, _bstr_t(pe32.szExeFile)))
{
result = pe32.th32ProcessID;
break;
}
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
return result;
}
然后(因为我的程序是可执行的)我创建了一个 dll 入口点:
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
Hooking::HookProcess();
return 0;
}
BOOL WINAPI DllMain(
HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved
)
{
MessageBoxA(NULL, "Injection OK", "Injection OK", NULL);
}
但是,无论是 Dll 还是 exe,我的入口点都没有被调用。所以我在想这可能是因为这个 exe 包含 .Net 代码但在更改它之前我想在这里问一下。
感谢您的宝贵时间
首先将“(wcslen(DLL_NAME) + 1) * sizeof(wchar_t)”改为"wcslen(DLL_NAME)"即可。确保同时更新内存分配。
其次,您将一个 unicode 编码的缓冲区传递给 LoadLibraryA。这是行不通的,因为 LoadLibraryA 不接受 unicode 编码的缓冲区,它需要一个 Ascii 编码的缓冲区。请改用 LoadLibraryW。
第三,您没有进行任何错误检查。不能就假设这两个虚拟内存操作和创建远程线程的操作都会成功,需要检查每个操作的return状态,确保成功,否则就停止追寻注入的套路。这也将深入了解操作失败的原因。您需要将调试器附加到目标进程,以确保内存在分配和写入后也能正常运行。
最后但同样重要的是,确保您有足够的权限来定位目标进程。例如,如果您是 运行 标准权限,则不能将提升的进程作为目标,也不能将启用自我保护的传统安全解决方案作为目标。这里有很多不同的因素。