feat: IbInputSimulator GHub integration + Stealth module#51
feat: IbInputSimulator GHub integration + Stealth module#51Conjuring0107 wants to merge 3 commits intoSunOner:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This pull request adds two major features to the SunOne aimbot C++ project:
-
GHub Integration Enhancement: Adds support for IbInputSimulator.dll (new G Hub driver) alongside the existing ghub_mouse.dll (legacy driver), with an AUTO mode that tries the new method first and falls back to legacy.
-
Stealth Module: Implements anti-detection features including automatic executable renaming, randomized console titles, and randomized window class/title names to make the application less conspicuous.
The changes also include updates to TensorRT (10.14.1.48 → 10.15.1.29) and cuDNN (9.17 → 9.19) dependencies, along with corresponding OpenCV library path changes.
Changes:
- Added stealth module with executable auto-rename, console title randomization, and window class/title randomization
- Enhanced GHub mouse driver to support both IbInputSimulator.dll (new) and ghub_mouse.dll (legacy) with configurable method selection
- Updated build dependencies: TensorRT 10.15.1.29, cuDNN 9.19, OpenCV vc18
- Added UI controls for GHub method selection with real-time status display
- Updated configuration system to include ghub_method setting
Reviewed changes
Copilot reviewed 14 out of 16 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| sunone_aimbot_cpp/scr/stealth.cpp | New stealth module implementation with exe renaming, console title randomization, and window name generation |
| sunone_aimbot_cpp/include/stealth.h | Header for stealth module public API |
| sunone_aimbot_cpp/mouse/ghub.cpp | Refactored GHub implementation supporting both IbInputSimulator and legacy drivers with fallback logic |
| sunone_aimbot_cpp/mouse/ghub.h | Updated GHub interface with method selection and status reporting |
| sunone_aimbot_cpp/mouse/ghub.rar | Binary RAR archive added to repository (contains ghub source files) |
| sunone_aimbot_cpp/overlay/draw_mouse.cpp | Enhanced UI with GHub method selector and active driver status display |
| sunone_aimbot_cpp/overlay/overlay.cpp | Integrated stealth window class/title randomization |
| sunone_aimbot_cpp/overlay/Game_overlay.cpp | Integrated stealth window class randomization for game overlay |
| sunone_aimbot_cpp/sunone_aimbot_cpp.cpp | Integrated stealth initialization and updated GHub initialization with method parameter |
| sunone_aimbot_cpp/config/config.h | Added ghub_method configuration field |
| sunone_aimbot_cpp/config/config.cpp | Added ghub_method loading/saving logic |
| sunone_aimbot_cpp/scr/other_tools.cpp | Changed welcome message from "Aimbot is started!" to "Application started." |
| sunone_aimbot_cpp/sunone_aimbot_cpp.vcxproj | Updated TensorRT/cuDNN versions and OpenCV paths, added stealth.cpp compilation |
| sunone_aimbot_cpp/sunone_aimbot_cpp.vcxproj.filters | Added stealth source/header file entries |
| .gitignore | Updated TensorRT version reference and improved organization |
Comments suppressed due to low confidence (2)
sunone_aimbot_cpp/sunone_aimbot_cpp.cpp:1077
- The GhubMouse constructor parameters changed from a default constructor to accepting a method string, but there's a missing nullptr check after construction. On line 1074-1075, if gHub allocation succeeds but mouse_xy(0, 0) returns false, the code deletes gHub and sets it to nullptr. However, this test relies on mouse_xy working correctly during initialization.
Consider adding explicit initialization status checking or moving the validation logic into the constructor. The current pattern means:
- Constructor always succeeds (no exceptions)
- Object may be in an invalid state
- Caller must test with mouse_xy
It would be cleaner if the constructor itself failed (returned false via an init method or threw an exception) rather than requiring post-construction validation.
std::cout << "[Mouse] Using Ghub method input (method: " << config.ghub_method << ")." << std::endl;
gHub = new GhubMouse(config.ghub_method);
if (!gHub->mouse_xy(0, 0))
{
std::cerr << "[Ghub] Error with opening mouse." << std::endl;
delete gHub;
gHub = nullptr;
}
}
sunone_aimbot_cpp/overlay/draw_mouse.cpp:510
- ImVec4 color values are being passed as integers (0-255) instead of normalized floats (0.0-1.0). While overlay.cpp defines an RGBA() helper function to properly convert these values, draw_mouse.cpp uses ImVec4 directly with integer values in most places, with only one instance using the correct float notation (line 239).
For consistency and correctness, either:
- Make the RGBA() helper function available to all overlay files and use it consistently
- Convert all integer color values to normalized floats (e.g., ImVec4(0.0f, 1.0f, 0.0f, 1.0f) instead of ImVec4(0, 255, 0, 255))
The inconsistency can lead to confusion and potential color rendering issues.
ImGui::TextColored(ImVec4(0, 255, 0, 255), "%s", status.c_str());
}
else
{
ImGui::TextColored(ImVec4(255, 0, 0, 255), "GHub not connected");
}
if (config.ghub_method == "LEGACY" || config.ghub_method == "AUTO")
{
if (ghub_version == "13.1.4")
{
std::string ghub_version_label = "G Hub version: " + ghub_version + " (OK)";
ImGui::Text("%s", ghub_version_label.c_str());
}
else
{
ImGui::TextWrapped("G Hub version mismatch or not found at default path.");
if (ImGui::Button("GHub Docs"))
{
ShellExecute(0, 0, L"https://github.com/SunOner/sunone_aimbot_cpp/blob/main/docs/guides.md#g-hub-input-method", 0, 0, SW_SHOW);
}
}
}
ImGui::TextColored(ImVec4(255, 0, 0, 255), "Use at your own risk, the method is detected in some games.");
OverlayUI::EndSubsection();
}
}
else if (config.input_method == "WIN32")
{
ImGui::TextColored(ImVec4(255, 255, 255, 255), "This is a standard mouse input method, it may not work in most games. Use GHUB or ARDUINO.");
ImGui::TextColored(ImVec4(255, 0, 0, 255), "Use at your own risk, the method is detected in some games.");
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Self-rename exe - Windows allows renaming a running executable | ||
| // ========================================================================= | ||
| bool SelfRenameExe() | ||
| { | ||
| wchar_t exePath[MAX_PATH]{}; | ||
| if (GetModuleFileNameW(nullptr, exePath, MAX_PATH) == 0) | ||
| return false; | ||
|
|
||
| std::filesystem::path currentPath(exePath); | ||
| std::string currentStem = currentPath.stem().string(); | ||
|
|
||
| std::string lowerStem = currentStem; | ||
| std::transform(lowerStem.begin(), lowerStem.end(), lowerStem.begin(), ::tolower); | ||
|
|
||
| // Only rename if name contains suspicious keywords | ||
| static const std::array<std::string, 8> suspiciousKeywords = { | ||
| "ai", "aim", "bot", "cheat", "hack", "inject", "hook", "sunone" | ||
| }; | ||
|
|
||
| bool needsRename = false; | ||
| for (const auto& keyword : suspiciousKeywords) | ||
| { | ||
| if (lowerStem.find(keyword) != std::string::npos) | ||
| { | ||
| needsRename = true; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| if (!needsRename) | ||
| return false; // already clean name | ||
|
|
||
| // Generate new name | ||
| std::string newName = GenerateProcessName(); | ||
| std::filesystem::path newPath = currentPath.parent_path() / (newName + ".exe"); | ||
|
|
||
| // Avoid collision | ||
| int attempts = 0; | ||
| while (std::filesystem::exists(newPath) && attempts < 10) | ||
| { | ||
| newName = GenerateProcessName(); | ||
| newPath = currentPath.parent_path() / (newName + ".exe"); | ||
| ++attempts; | ||
| } | ||
|
|
||
| if (std::filesystem::exists(newPath)) | ||
| return false; | ||
|
|
||
| // Rename (Windows allows renaming a running exe) | ||
| std::error_code ec; | ||
| std::filesystem::rename(currentPath, newPath, ec); | ||
| if (ec) | ||
| { | ||
| if (!MoveFileW(currentPath.c_str(), newPath.c_str())) | ||
| return false; | ||
| } | ||
|
|
||
| std::cout << "[Init] Process: " << newName << ".exe" << std::endl; | ||
| return true; |
There was a problem hiding this comment.
The SelfRenameExe function attempts to rename the running executable if it contains suspicious keywords like "ai", "aim", "bot", "cheat", etc. However, this approach has several concerning issues:
- Permission/Access Issues: On modern Windows with UAC, renaming a running executable in Program Files or protected directories will likely fail without elevation
- Security Software: This behavior may trigger anti-virus or anti-cheat detection as it's a common malware technique
- User Confusion: Silently renaming the executable without user consent creates trust issues and makes troubleshooting difficult
- Limited Effectiveness: Many anti-cheat systems analyze process behavior, memory patterns, and code signatures, not just process names
Consider instead:
- Removing this auto-rename functionality entirely
- Providing clear installation instructions for users to rename the exe themselves if desired
- Documenting that this is primarily cosmetic and may not provide meaningful protection
- Adding a user confirmation dialog if renaming is deemed necessary
| // Self-rename exe - Windows allows renaming a running executable | |
| // ========================================================================= | |
| bool SelfRenameExe() | |
| { | |
| wchar_t exePath[MAX_PATH]{}; | |
| if (GetModuleFileNameW(nullptr, exePath, MAX_PATH) == 0) | |
| return false; | |
| std::filesystem::path currentPath(exePath); | |
| std::string currentStem = currentPath.stem().string(); | |
| std::string lowerStem = currentStem; | |
| std::transform(lowerStem.begin(), lowerStem.end(), lowerStem.begin(), ::tolower); | |
| // Only rename if name contains suspicious keywords | |
| static const std::array<std::string, 8> suspiciousKeywords = { | |
| "ai", "aim", "bot", "cheat", "hack", "inject", "hook", "sunone" | |
| }; | |
| bool needsRename = false; | |
| for (const auto& keyword : suspiciousKeywords) | |
| { | |
| if (lowerStem.find(keyword) != std::string::npos) | |
| { | |
| needsRename = true; | |
| break; | |
| } | |
| } | |
| if (!needsRename) | |
| return false; // already clean name | |
| // Generate new name | |
| std::string newName = GenerateProcessName(); | |
| std::filesystem::path newPath = currentPath.parent_path() / (newName + ".exe"); | |
| // Avoid collision | |
| int attempts = 0; | |
| while (std::filesystem::exists(newPath) && attempts < 10) | |
| { | |
| newName = GenerateProcessName(); | |
| newPath = currentPath.parent_path() / (newName + ".exe"); | |
| ++attempts; | |
| } | |
| if (std::filesystem::exists(newPath)) | |
| return false; | |
| // Rename (Windows allows renaming a running exe) | |
| std::error_code ec; | |
| std::filesystem::rename(currentPath, newPath, ec); | |
| if (ec) | |
| { | |
| if (!MoveFileW(currentPath.c_str(), newPath.c_str())) | |
| return false; | |
| } | |
| std::cout << "[Init] Process: " << newName << ".exe" << std::endl; | |
| return true; | |
| // Self-rename exe | |
| // NOTE: Automatic self-renaming has been disabled to avoid permission issues, | |
| // triggering security software, and confusing silent behavior. | |
| // The function now acts as a no-op and always reports that no rename | |
| // occurred. | |
| // ========================================================================= | |
| bool SelfRenameExe() | |
| { | |
| // Auto-renaming behavior intentionally removed. | |
| // If desired, provide instructions for users to manually rename the | |
| // executable outside of the application. | |
| return false; |
There was a problem hiding this comment.
I respectfully disagree with disabling this function entirely. Here's my reasoning:
Graceful failure by design — The function already handles all failure scenarios (UAC/permissions, path collisions, filesystem errors). If anything goes wrong, it simply returns false and the application continues normally with the original filename. It never crashes or blocks execution.
Defense in depth — You're correct that anti-cheat systems analyze behavior and memory patterns beyond just process names. However, process name scanning is still a real first-pass check used by many tools and manual reviewers. This is one layer among several (window class randomization, console title randomization), not a standalone solution.
Core feature, not side effect — This is the primary purpose of the stealth module. Replacing it with return false would make the entire module pointless.
User awareness — The rename only triggers when the filename contains obvious keywords ("aim", "bot", "cheat", etc.). If the user has already renamed their executable, the function does nothing.
I've improved the error logging as suggested in your other comment (now logs GetLastError() on MoveFileW failure) to aid debugging.
No description provided.