-
How to refresh LoadLibrary to inject into every WoW process that's open?
My injector has a bunch of limitations, and I want to improve it. I enumerate through process modules and can easily find which WoW windows haven't been injected to yet, but it seems like LoadLibrary needs to be reset in some fashion because the second or subsequent injects fail.
Code:
int main()
{
auto hProcesses = EnumProcs(); // find WoW procs
for (auto hProcess : hProcesses)
{
DWORD pid = EnumModules(hProcess); // find if the module is already injected
if (pid)
StartProcess(pid); // pass the pid to my injector.exe and repeat for each one
Sleep(20);
}
return 0;
}
I'm able to inject one at a time, but I would love to be able to mass inject or have a gui that I can map/unmap.
- Injector -
Code:
LPVOID MapBuffer(HANDLE hProcess, LPBYTE buffer, SIZE_T bufferSize, DWORD protect = PAGE_EXECUTE_READWRITE)
{
LPVOID remoteAddress = VirtualAllocEx(hProcess, nullptr, bufferSize, MEM_COMMIT | MEM_RESERVE, protect);
if (remoteAddress == nullptr) {
printf("Could not allocate memory in the remote process\n");
return nullptr;
}
if (!WriteProcessMemory(hProcess, remoteAddress, buffer, bufferSize, nullptr)) {
VirtualFreeEx(hProcess, remoteAddress, bufferSize, MEM_FREE);
return nullptr;
}
return remoteAddress;
}
HANDLE Inject(HANDLE hProcess, const wchar_t* path)
{
SIZE_T inject_path_size = wcslen(path) * sizeof(WCHAR);
PVOID remotePtr = MapBuffer(hProcess, (BYTE*)path, inject_path_size, PAGE_READWRITE);
HMODULE hModule = GetModuleHandle(L"kernel32.dll");
if (!hModule) return nullptr;
FARPROC hLoadLib = GetProcAddress(hModule, "LoadLibraryW");
if (!hLoadLib) return nullptr;
return CreateRemoteThread(hProcess, nullptr, 0, (LPTHREAD_START_ROUTINE)hLoadLib, remotePtr, 0, nullptr);
}
int main(int argc, char* argv[])
{
wchar_t* pEnd;
auto pid = (DWORD)atoi(argv[0]);
auto hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
char szPath[] = DLL_PATH;
wstring wPath(&szPath[0], &szPath[strlen(szPath)]);
if (hProcess)
Inject(hProcess, wPath.c_str());
return 0;
}
I wanted to use blackbone, but my OCD is getting in the way because it's oddly organized (you can build a static lib but you still need to include all these cpp files in the program that uses the lib???). I figured if I passed cmd args to a seperate exe with the pids needed it would get around the one at a time issue but no luck
-
Contributor
if you build a lib all you need are headers and to link against that lib. There is also no need for two programs to do this. Why dont you just build the process list inside your injectors main method and do the loop in there. The nice thing about injectors is you can debug them one step at a time. So maybe remove the complexity of two programs add the loop in your injector and step through to see why the second injection fails.
-
Post Thanks / Like - 1 Thanks
eqdrp (1 members gave Thanks to aeo for this useful post)
-
Originally Posted by
aeo
if you build a lib all you need are headers and to link against that lib. There is also no need for two programs to do this. Why dont you just build the process list inside your injectors main method and do the loop in there. The nice thing about injectors is you can debug them one step at a time. So maybe remove the complexity of two programs add the loop in your injector and step through to see why the second injection fails.
I'll take another attempt at it, but it was difficult for me to debug. I could verify that the pid was correct and different from the first inject, and the strange thing is that it would corrupt the inject of the first one if I have more than one WoW window open. If I have just one WoW window that doesn't have my module in it yet, then it will keep working, but the moment it has two or more to choose from (event with the correct pid verified in PE, it will fail)
My assumption was that I'm not freeing or writing the memory space correctly, so the LoadLib just executes the former inject or something like that if it makes any sense.
Last edited by GlittPrizes; 03-24-2021 at 07:35 PM.
Reason: edit: not exactly sure where it was going wrong but I rewrote it and can now mass inject
-
Originally Posted by
GlittPrizes
My assumption was that I'm not freeing or writing the memory space correctly, so the LoadLib just executes the former inject or something like that if it makes any sense.
It depends on how your injector code works as well as the injected library. Trying to inject a library twice should not cause any issues if you follow common library best practices. I've got my share of weired crashes by doing things in DllMain that you shouldn't do. I've removed DllMain from my library completly since it's technically not needed.
From Dynamic-Link Library Best Practices - Win32 apps | Microsoft Docs
You should never perform the following tasks from within DllMain:
- Call LoadLibrary or LoadLibraryEx (either directly or indirectly). This can cause a deadlock or a crash.
- Call GetStringTypeA, GetStringTypeEx, or GetStringTypeW (either directly or indirectly). This can cause a deadlock or a crash.
- Synchronize with other threads. This can cause a deadlock.
- Acquire a synchronization object that is owned by code that is waiting to acquire the loader lock. This can cause a deadlock.
- Initialize COM threads by using CoInitializeEx. Under certain conditions, this function can call LoadLibraryEx.
- Call the registry functions. These functions are implemented in Advapi32.dll. If Advapi32.dll is not initialized before your DLL, the DLL can access uninitialized memory and cause the process to crash.
- Call CreateProcess. Creating a process can load another DLL.
- Call ExitThread. Exiting a thread during DLL detach can cause the loader lock to be acquired again, causing a deadlock or a crash.
- Call CreateThread. Creating a thread can work if you do not synchronize with other threads, but it is risky.
- Create a named pipe or other named object (Windows 2000 only). In Windows 2000, named objects are provided by the Terminal Services DLL. If this DLL is not initialized, calls to the DLL can cause the process to crash.
- Use the memory management function from the dynamic C Run-Time (CRT). If the CRT DLL is not initialized, calls to these functions can cause the process to crash.
- Call functions in User32.dll or Gdi32.dll. Some functions load another DLL, which may not be initialized.
- Use managed code.
"Threads should always commit suicide - they should never be murdered" - DirectX SDK
-
Post Thanks / Like - 1 Thanks
GlittPrizes (1 members gave Thanks to xalcon for this useful post)