Overall this is a job for 2 functions: one return pid s qualified name of a certain process, and one DLL injection process with a particular name (of course, this is only her job to take care of things like full path of the DLL). It is important to emphasize that can be several processes with the same name, and therefore need to have a good realization that process until it is successful. Here is an exercise in C ++ 11 I was writing, which takes into account the points I was talking about:
Code:
#include <iostream>
#include <cstdint>
#include <memory>
#include <vector>
#undef UNICODE
#include <windows.h>
#include <TlHelp32.h>
using std::uint32_t;
std::vector<uint32_t> pids(const std::string& processName, uint32_t delay = 100)
{
std::vector<uint32_t> list;
while (list.empty())
{
auto snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 entry = { sizeof entry };
if (Process32First(snapshot, &entry))
while (Process32Next(snapshot, &entry))
if (entry.szExeFile == processName)
list.push_back(entry.th32ProcessID);
Sleep(delay); // Win32 API is extremely retarded
CloseHandle(snapshot);
}
return list;
}
bool inject(const std::string& processName, std::string dll)
{
char path[MAX_PATH] = "";
GetFullPathName(dll.c_str(), sizeof path, path, 0);
dll = path;
// iterate through all matching processes. stop with the first success.
for (auto pid : pids(processName))
{
const auto processFlags = PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD;
using ProcessHandle = std::unique_ptr<void, decltype(&::CloseHandle)>;
ProcessHandle process(OpenProcess(processFlags, false, pid), CloseHandle);
if (!process)
continue;
const auto memFlags = MEM_RESERVE | MEM_COMMIT;
auto mem = VirtualAllocEx(process.get(), nullptr, dll.length() + 1, memFlags, PAGE_READWRITE);
if (!mem)
continue;
auto rc = WriteProcessMemory(process.get(), mem, dll.c_str(), dll.length() + 1, nullptr);
if (!rc)
continue;
auto loadLibrary = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");
if (!loadLibrary)
continue;
auto tid = CreateRemoteThread(process.get(), nullptr, 0, loadLibrary, mem, 0, nullptr);
if (!tid)
continue;
return true;
}
return false;
}
How to use the function to inject very simple - it gets there a process where the DLL (without using full path) and returns whether the injection was successful. Use example:
Code:
std::string process;
std::cout << "Enter process name: ";
std::cin >> process;
std::string dll;
std::cout << "Enter DLL: ";
std::cin >> dll;
if (inject(process, dll))
std::cout << "Injection succeeded" << '\n';
else
std::cout << "Injection failed" << '\n';