diff --git a/EFTCheatPVE1.0.sln b/EFTCheatPVE1.0.sln index 341c447..24ee7f2 100644 --- a/EFTCheatPVE1.0.sln +++ b/EFTCheatPVE1.0.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 18 VisualStudioVersion = 18.0.11222.15 d18.0 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "battleyent", "battleyent\battleyent.vcxproj", "{E27A8A44-4579-488B-9D79-C5634C6A9650}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iOperator", "ioperator\ioperator.vcxproj", "{E27A8A44-4579-488B-9D79-C5634C6A9650}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "operator", "operator\operator.vcxproj", "{74BBBA60-A5FB-4621-8389-40DCEF552CC0}" EndProject diff --git a/battleyent/dllmain.cpp b/ioperator/dllmain.cpp similarity index 99% rename from battleyent/dllmain.cpp rename to ioperator/dllmain.cpp index 45c0fdb..2e747af 100644 --- a/battleyent/dllmain.cpp +++ b/ioperator/dllmain.cpp @@ -536,6 +536,14 @@ void start() { printf("freopen_s failed\n"); } + if (freopen_s(&conout, "CONOUT$", "w", stderr) != 0) + { + printf("freopen_s failed\n"); + } + if (freopen_s(&conout, "CONIN$", "r", stdin) != 0) + { + printf("freopen_s failed\n"); + } // 1. Wait for GameAssembly.dll to load and get IL2CPP API addresses HMODULE il2cpp = nullptr; diff --git a/battleyent/framework.h b/ioperator/framework.h similarity index 100% rename from battleyent/framework.h rename to ioperator/framework.h diff --git a/battleyent/battleyent.vcxproj b/ioperator/iOperator.vcxproj similarity index 98% rename from battleyent/battleyent.vcxproj rename to ioperator/iOperator.vcxproj index 29b5a0c..2f88915 100644 --- a/battleyent/battleyent.vcxproj +++ b/ioperator/iOperator.vcxproj @@ -24,7 +24,7 @@ {e27a8a44-4579-488b-9d79-c5634c6a9650} battleyent 10.0 - battleyent_helper + iOperator @@ -43,7 +43,7 @@ DynamicLibrary true - v145 + v143 Unicode diff --git a/battleyent/battleyent.vcxproj.filters b/ioperator/iOperator.vcxproj.filters similarity index 100% rename from battleyent/battleyent.vcxproj.filters rename to ioperator/iOperator.vcxproj.filters diff --git a/battleyent/imconfig_custom.h b/ioperator/imconfig_custom.h similarity index 100% rename from battleyent/imconfig_custom.h rename to ioperator/imconfig_custom.h diff --git a/battleyent/imgui/imconfig.h b/ioperator/imgui/imconfig.h similarity index 100% rename from battleyent/imgui/imconfig.h rename to ioperator/imgui/imconfig.h diff --git a/battleyent/imgui/imgui.cpp b/ioperator/imgui/imgui.cpp similarity index 100% rename from battleyent/imgui/imgui.cpp rename to ioperator/imgui/imgui.cpp diff --git a/battleyent/imgui/imgui.h b/ioperator/imgui/imgui.h similarity index 100% rename from battleyent/imgui/imgui.h rename to ioperator/imgui/imgui.h diff --git a/battleyent/imgui/imgui_draw.cpp b/ioperator/imgui/imgui_draw.cpp similarity index 100% rename from battleyent/imgui/imgui_draw.cpp rename to ioperator/imgui/imgui_draw.cpp diff --git a/battleyent/imgui/imgui_impl_dx11.cpp b/ioperator/imgui/imgui_impl_dx11.cpp similarity index 100% rename from battleyent/imgui/imgui_impl_dx11.cpp rename to ioperator/imgui/imgui_impl_dx11.cpp diff --git a/battleyent/imgui/imgui_impl_dx11.h b/ioperator/imgui/imgui_impl_dx11.h similarity index 100% rename from battleyent/imgui/imgui_impl_dx11.h rename to ioperator/imgui/imgui_impl_dx11.h diff --git a/battleyent/imgui/imgui_impl_win32.cpp b/ioperator/imgui/imgui_impl_win32.cpp similarity index 100% rename from battleyent/imgui/imgui_impl_win32.cpp rename to ioperator/imgui/imgui_impl_win32.cpp diff --git a/battleyent/imgui/imgui_impl_win32.h b/ioperator/imgui/imgui_impl_win32.h similarity index 100% rename from battleyent/imgui/imgui_impl_win32.h rename to ioperator/imgui/imgui_impl_win32.h diff --git a/battleyent/imgui/imgui_internal.h b/ioperator/imgui/imgui_internal.h similarity index 100% rename from battleyent/imgui/imgui_internal.h rename to ioperator/imgui/imgui_internal.h diff --git a/battleyent/imgui/imgui_tables.cpp b/ioperator/imgui/imgui_tables.cpp similarity index 100% rename from battleyent/imgui/imgui_tables.cpp rename to ioperator/imgui/imgui_tables.cpp diff --git a/battleyent/imgui/imgui_widgets.cpp b/ioperator/imgui/imgui_widgets.cpp similarity index 100% rename from battleyent/imgui/imgui_widgets.cpp rename to ioperator/imgui/imgui_widgets.cpp diff --git a/battleyent/imgui/imstb_rectpack.h b/ioperator/imgui/imstb_rectpack.h similarity index 100% rename from battleyent/imgui/imstb_rectpack.h rename to ioperator/imgui/imstb_rectpack.h diff --git a/battleyent/imgui/imstb_textedit.h b/ioperator/imgui/imstb_textedit.h similarity index 100% rename from battleyent/imgui/imstb_textedit.h rename to ioperator/imgui/imstb_textedit.h diff --git a/battleyent/imgui/imstb_truetype.h b/ioperator/imgui/imstb_truetype.h similarity index 100% rename from battleyent/imgui/imstb_truetype.h rename to ioperator/imgui/imstb_truetype.h diff --git a/battleyent/kiero/kiero.cpp b/ioperator/kiero/kiero.cpp similarity index 100% rename from battleyent/kiero/kiero.cpp rename to ioperator/kiero/kiero.cpp diff --git a/battleyent/kiero/kiero.h b/ioperator/kiero/kiero.h similarity index 100% rename from battleyent/kiero/kiero.h rename to ioperator/kiero/kiero.h diff --git a/battleyent/minhook/include/MinHook.h b/ioperator/minhook/include/MinHook.h similarity index 100% rename from battleyent/minhook/include/MinHook.h rename to ioperator/minhook/include/MinHook.h diff --git a/battleyent/minhook/lib/libMinHook.x64.lib b/ioperator/minhook/lib/libMinHook.x64.lib similarity index 100% rename from battleyent/minhook/lib/libMinHook.x64.lib rename to ioperator/minhook/lib/libMinHook.x64.lib diff --git a/battleyent/minhook/lib/libMinHook.x86.lib b/ioperator/minhook/lib/libMinHook.x86.lib similarity index 100% rename from battleyent/minhook/lib/libMinHook.x86.lib rename to ioperator/minhook/lib/libMinHook.x86.lib diff --git a/battleyent/offsets.h b/ioperator/offsets.h similarity index 100% rename from battleyent/offsets.h rename to ioperator/offsets.h diff --git a/battleyent/pch.cpp b/ioperator/pch.cpp similarity index 100% rename from battleyent/pch.cpp rename to ioperator/pch.cpp diff --git a/battleyent/pch.h b/ioperator/pch.h similarity index 100% rename from battleyent/pch.h rename to ioperator/pch.h diff --git a/operator/operator.cpp b/operator/operator.cpp index e900b9d..6ac99a0 100644 --- a/operator/operator.cpp +++ b/operator/operator.cpp @@ -4,7 +4,87 @@ #include #include #include +#include +#include +#include +#include +#include +#pragma comment(lib, "shlwapi.lib") +typedef struct _UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING, * PUNICODE_STRING; + +typedef struct _RTL_USER_PROCESS_PARAMETERS { + BYTE Reserved1[16]; + PVOID Reserved2[10]; + UNICODE_STRING ImagePathName; + UNICODE_STRING CommandLine; +} RTL_USER_PROCESS_PARAMETERS, * PRTL_USER_PROCESS_PARAMETERS; + +typedef struct _PEB { + BYTE Reserved1[2]; + BYTE BeingDebugged; + BYTE Reserved2[1]; + PVOID Reserved3[2]; + PVOID Ldr; + PRTL_USER_PROCESS_PARAMETERS ProcessParameters; +} PEB, * PPEB; + +typedef struct _PROCESS_BASIC_INFORMATION { + PVOID Reserved1; + PPEB PebBaseAddress; + PVOID Reserved2[2]; + ULONG_PTR UniqueProcessId; + PVOID Reserved3; +} PROCESS_BASIC_INFORMATION; + +// ProcessBasicInformation = 0 +#ifndef ProcessBasicInformation +#define ProcessBasicInformation 0 +#endif + + +std::wstring GetCommandLine(DWORD pid) +{ + std::wstring result; + HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ, FALSE, pid); + if (!hProcess) return result; + + // Load ntdll + auto ntdll = GetModuleHandleA("ntdll.dll"); + auto NtQueryInformationProcess = (LONG(WINAPI*)(HANDLE, int, PVOID, ULONG, PULONG))GetProcAddress(ntdll, "NtQueryInformationProcess"); + + if (!NtQueryInformationProcess) { + CloseHandle(hProcess); + return result; + } + + PROCESS_BASIC_INFORMATION pbi{}; + ULONG len; + if (NtQueryInformationProcess(hProcess, 0, &pbi, sizeof(pbi), &len) == 0) + { + PEB peb{}; + RTL_USER_PROCESS_PARAMETERS upp{}; + if (ReadProcessMemory(hProcess, pbi.PebBaseAddress, &peb, sizeof(peb), nullptr)) + { + if (ReadProcessMemory(hProcess, peb.ProcessParameters, &upp, sizeof(upp), nullptr)) + { + wchar_t* buffer = new wchar_t[8192]; + if (ReadProcessMemory(hProcess, upp.CommandLine.Buffer, buffer, upp.CommandLine.Length, nullptr)) + { + result = std::wstring(buffer, upp.CommandLine.Length / sizeof(wchar_t)); + } + delete[] buffer; + } + } + } + + CloseHandle(hProcess); + return result; +} std::string GetExeDirectory() { wchar_t path[MAX_PATH] = { 0 }; @@ -142,9 +222,9 @@ void verifyServiceDeletion(const std::wstring& svcName) SERVICE_STATUS status{}; if (ControlService(hExisting, SERVICE_CONTROL_STOP, &status)) { - DWORD start = GetTickCount(); + long long start = GetTickCount64(); std::cout << "Waiting for BEService to stop"; - while (status.dwCurrentState != SERVICE_STOPPED && GetTickCount() - start < 10000) { + while (status.dwCurrentState != SERVICE_STOPPED && GetTickCount64() - start < 10000) { Sleep(500); std::cout << "."; if (!QueryServiceStatus(hExisting, &status)) break; @@ -165,6 +245,207 @@ void verifyServiceDeletion(const std::wstring& svcName) } } +BOOL InjectDLL(DWORD processId, const char* dllPath) +{ + HANDLE hProcess = OpenProcess( + PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD | + PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, + FALSE, processId); + + if (!hProcess) { + std::cout << "[-] OpenProcess failed: " << GetLastError() << std::endl; + return FALSE; + } + + SIZE_T pathLen = strlen(dllPath) + 1; + LPVOID remoteMem = VirtualAllocEx(hProcess, nullptr, pathLen, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + if (!remoteMem) { + std::cout << "[-] VirtualAllocEx failed: " << GetLastError() << std::endl; + CloseHandle(hProcess); + return FALSE; + } + + if (!WriteProcessMemory(hProcess, remoteMem, dllPath, pathLen, nullptr)) { + std::cout << "[-] WriteProcessMemory failed: " << GetLastError() << std::endl; + VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE); + CloseHandle(hProcess); + return FALSE; + } + + HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); + if (!hKernel32) { + VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE); + CloseHandle(hProcess); + return FALSE; + } + + LPTHREAD_START_ROUTINE pLoadLibrary = (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "LoadLibraryA"); + + HANDLE hThread = CreateRemoteThread(hProcess, nullptr, 0, pLoadLibrary, remoteMem, 0, nullptr); + if (!hThread) { + std::cout << "[-] CreateRemoteThread failed: " << GetLastError() << std::endl; + VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE); + CloseHandle(hProcess); + return FALSE; + } + + WaitForSingleObject(hThread, 10000); + + DWORD exitCode = 0; + GetExitCodeThread(hThread, &exitCode); + + CloseHandle(hThread); + VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE); + CloseHandle(hProcess); + + if (exitCode != 0) { + std::cout << "[+] Injected successfully! (hModule = 0x" + << std::hex << exitCode << std::dec << ")\n"; + return TRUE; + } + + std::cout << "[-] LoadLibraryA returned NULL in target process\n"; + return FALSE; +} + +BOOL StealAndKillBE(std::wstring& outCmdLine, DWORD& outPid) +{ + HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnap == INVALID_HANDLE_VALUE) return false; + + PROCESSENTRY32 pe{ .dwSize = sizeof(pe) }; + bool found = false; + + if (!Process32First(hSnap, &pe)) + goto not_found; + + do { + if (_wcsicmp(pe.szExeFile, L"EscapeFromTarkov_BE.exe") != 0) + continue; + std::cout << std::endl; + found = true; + outPid = pe.th32ProcessID; + std::wcout << L"[+] Found BE process (PID: " << outPid << L") - Stealing command line...\n"; + + // 1. STEAL COMMAND LINE FIRST + outCmdLine = GetCommandLine(outPid); + if (outCmdLine.empty()) { + std::wcout << L"[-] Failed to read command line from PID " << outPid << L"\n"; + continue; // try next instance + } + + std::wcout << L"[+] Command line stolen successfully!\n"; + + // 2. NOW KILL IT + HANDLE hProc = OpenProcess(PROCESS_TERMINATE, FALSE, outPid); + if (hProc) { + TerminateProcess(hProc, 0); + CloseHandle(hProc); + std::cout << "[+] BE process terminated.\n"; + } + + // Don't break — kill ALL BE instances (in case of multiple) + } while (Process32Next(hSnap, &pe)); +not_found: + CloseHandle(hSnap); + return found && !outCmdLine.empty(); +} + +BOOL Battleyent() +{ + std::wstring stolenCmdLine; + DWORD bePid = 0; + + // ── 1. Wait for BE and steal command line ─────────────────────── + std::cout << "[.] Waiting for EscapeFromTarkov_BE.exe to appear"; + while (!StealAndKillBE(stolenCmdLine, bePid)) + { + std::cout << "."; + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + + // ── 2. Replace BE executable with clean one ─────────────────── + std::wstring cleanCmdLine = std::regex_replace( + stolenCmdLine, + std::wregex(L"EscapeFromTarkov_BE\\.exe", std::regex_constants::icase), + L"EscapeFromTarkov.exe"); + + // ── 3. Extract real executable path (remove quotes if any) ───── + std::wsmatch match; + std::wstring exeFullPath; + + if (std::regex_search(cleanCmdLine, match, std::wregex(L"\"([^\"]+)\""))) + { + exeFullPath = match[1].str(); + cleanCmdLine = std::regex_replace(cleanCmdLine, + std::wregex(L"\"[^\"]+\""), + exeFullPath, + std::regex_constants::format_first_only); + } + else if (cleanCmdLine.find(L' ') != std::wstring::npos) + { + exeFullPath = cleanCmdLine.substr(0, cleanCmdLine.find(L' ')); + } + else + { + exeFullPath = cleanCmdLine; + } + + // ── 4. Build correct working directory ─────────────────────── + const std::wstring gameWorkingDir = exeFullPath.substr(0, exeFullPath.find_last_of(L"\\/")); + + std::wcout << L"[+] Game path : " << exeFullPath << L'\n'; + std::wcout << L"[+] Working directory: " << gameWorkingDir << L'\n'; + std::wcout << L"[+] Final cmdline : " << cleanCmdLine << L'\n'; + + // ── 5. Launch the clean game (suspended) ───────────────────── + STARTUPINFOW si = { sizeof(si) }; + PROCESS_INFORMATION pi = { }; + + const BOOL created = CreateProcessW( + nullptr, + cleanCmdLine.data(), + nullptr, nullptr, + FALSE, + CREATE_SUSPENDED, // start suspended -> safe injection + nullptr, + gameWorkingDir.c_str(), // avoid consistency crashes + &si, + &pi + ); + + if (!created) + { + std::cerr << "[-] CreateProcessW failed: " << GetLastError() << std::endl; + return FALSE; + } + + std::cout << "[+] EscapeFromTarkov.exe launched (PID: " << pi.dwProcessId << ")\n"; + + // ── 6. Resume main thread ───── + ResumeThread(pi.hThread); + + // ── 7. Inject our DLL ─────────────────────────────────────── + const std::string dllPath = GetExeDirectory() + "\\iOperator.dll"; + + if (!InjectDLL(pi.dwProcessId, dllPath.c_str())) + { + std::cout << "[-] Injection failed!\n"; + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + return FALSE; + } + + // ── 8. Success ─────────────────────────────────────────────── + std::cout << "[+] iOperator.dll injected successfully!\n"; + std::cout << "[+] Bootstrap done. Enjoy your raids!\n"; + + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + + Sleep(3000); + return TRUE; +} int main() { @@ -229,16 +510,11 @@ int main() CloseServiceHandle(hNew); CloseServiceHandle(scm); - std::cout << std::endl; - std::cout << "Spinning up Battleyen't.\n"; - char* path = _strdup(GetExeDirectory().c_str()); - size_t path_buf_size = strlen(path) + strlen("battleyent.exe") + 1; - path = (char*)realloc(path, path_buf_size); - if (strcat_s(path, path_buf_size, "battleyent.exe") == 0) { - system(path); - } - free(path); + + std::cout << "Spinning up. Launch EFT from launcher.\n"; + + while (!Battleyent()); std::cout << "Waiting for the game to start"; while (!isProcessRunning("EscapeFromTarkov.exe")) diff --git a/operator/operator.vcxproj b/operator/operator.vcxproj index 59de797..e662b1f 100644 --- a/operator/operator.vcxproj +++ b/operator/operator.vcxproj @@ -42,7 +42,7 @@ Application true - v145 + v143 Unicode @@ -105,6 +105,7 @@ _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp20 + stdclatest Console diff --git a/service/service.vcxproj b/service/service.vcxproj index 892b64c..952a16f 100644 --- a/service/service.vcxproj +++ b/service/service.vcxproj @@ -43,7 +43,7 @@ Application true - v145 + v143 Unicode @@ -106,6 +106,7 @@ _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp20 + stdclatest Console