diff --git a/GlosSIConfig/main.cpp b/GlosSIConfig/main.cpp index ccb8f5b..39a476c 100644 --- a/GlosSIConfig/main.cpp +++ b/GlosSIConfig/main.cpp @@ -96,6 +96,8 @@ int main(int argc, char* argv[]) SetWindowLong(hwnd, GWL_STYLE, style); // Enable blurbehind (not needed?) anyway gives nice background on win7 and 8 + // LOL.. just realizing < Win 10 is not supported by HidHide driver... + // let's see what users think... DWM_BLURBEHIND bb{}; bb.dwFlags = DWM_BB_ENABLE; bb.fEnable = true; diff --git a/GlosSITarget/DllInjector.h b/GlosSITarget/DllInjector.h new file mode 100644 index 0000000..aa7197b --- /dev/null +++ b/GlosSITarget/DllInjector.h @@ -0,0 +1,110 @@ +#pragma once + +#include +#include +#include + +namespace DllInjector { + +inline bool TakeDebugPrivilege() +{ + HANDLE process = GetCurrentProcess(), token; + TOKEN_PRIVILEGES priv; + LUID luid = {NULL}; + + if (!OpenProcessToken(process, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) { + CloseHandle(process); + spdlog::error("Failed to open process token"); + return false; + } + LookupPrivilegeValue(0, SE_DEBUG_NAME, &luid); + + priv.PrivilegeCount = 1; + priv.Privileges[0].Luid = luid; + priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + if (!AdjustTokenPrivileges(token, false, &priv, sizeof(priv), NULL, NULL)) { + spdlog::error("Failed to take debug privilege token"); + } + + CloseHandle(token); + CloseHandle(process); + return true; +} + +inline bool Inject(DWORD pid, const std::wstring& lib_path) +{ + HANDLE process = NULL, alloc_address = NULL, remote_thread = NULL; + LPTHREAD_START_ROUTINE thread_routine = NULL; + + size_t path_size = (lib_path.length() + 1) * sizeof(wchar_t); + + process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, false, pid); + + if (!process) { + spdlog::error("Failed to open process"); + return false; + } + + alloc_address = VirtualAllocEx(process, NULL, path_size, MEM_COMMIT, PAGE_READWRITE); + + if (!VirtualAllocEx(process, NULL, path_size, MEM_COMMIT, PAGE_READWRITE)) { + spdlog::error("Failed to allocate memory in target process"); + CloseHandle(process); + return false; + } + + if (!WriteProcessMemory(process, (LPVOID)alloc_address, lib_path.c_str(), path_size, NULL)) { + spdlog::error("Failed to write memory in target process"); + VirtualFreeEx(process, alloc_address, path_size, MEM_DECOMMIT); + CloseHandle(process); + return false; + } + + thread_routine = reinterpret_cast(GetProcAddress(GetModuleHandle(L"Kernel32"), "LoadLibraryW")); + if (!thread_routine) { + spdlog::error("Failed to get address of LoadLibraryW"); + VirtualFreeEx(process, alloc_address, path_size, MEM_DECOMMIT); + CloseHandle(process); + return false; + } + + remote_thread = CreateRemoteThread(process, NULL, 0, thread_routine, alloc_address, 0, NULL); + + if (!remote_thread) { + spdlog::error("Failed to create remote thread"); + VirtualFreeEx(process, alloc_address, path_size, MEM_DECOMMIT); + CloseHandle(process); + return false; + } + + WaitForSingleObject(remote_thread, INFINITE); + + CloseHandle(remote_thread); + VirtualFreeEx(process, alloc_address, path_size, MEM_DECOMMIT); + CloseHandle(process); + spdlog::debug("Successfully injected"); + return true; +} + +inline bool findModule(DWORD pid, std::wstring& lib_path, HMODULE& hMod) +{ + MODULEENTRY32W entry = {sizeof(entry)}; + HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid); + + if (Module32FirstW(snapshot, &entry) == TRUE) { + while (Module32NextW(snapshot, &entry) == TRUE) { + std::wstring ModuleName(entry.szModule); + std::wstring ExePath(entry.szExePath); + if (ModuleName == lib_path || ExePath == lib_path) { + hMod = (HMODULE)entry.modBaseAddr; + CloseHandle(snapshot); + return true; + } + } + } + CloseHandle(snapshot); + spdlog::error(L"Failed to find module \"{}\"", lib_path); + return false; +} + +}; // namespace DllInjector diff --git a/GlosSITarget/GlosSITarget.vcxproj b/GlosSITarget/GlosSITarget.vcxproj index 5a72ee9..9811703 100644 --- a/GlosSITarget/GlosSITarget.vcxproj +++ b/GlosSITarget/GlosSITarget.vcxproj @@ -187,6 +187,7 @@ + @@ -199,6 +200,7 @@ + diff --git a/GlosSITarget/GlosSITarget.vcxproj.filters b/GlosSITarget/GlosSITarget.vcxproj.filters index a3bfd4d..3be7961 100644 --- a/GlosSITarget/GlosSITarget.vcxproj.filters +++ b/GlosSITarget/GlosSITarget.vcxproj.filters @@ -125,6 +125,12 @@ Header Files + + Header Files + + + Header Files + diff --git a/GlosSITarget/HidHide.cpp b/GlosSITarget/HidHide.cpp index 925635a..c079d2d 100644 --- a/GlosSITarget/HidHide.cpp +++ b/GlosSITarget/HidHide.cpp @@ -272,6 +272,8 @@ void HidHide::enableOverlayElement() closeCtrlDevice(); overlay_elem_clock_.restart(); } + ImGui::SetNextWindowSizeConstraints({300, 250}, {1000, 1000}); + ImGui::SetNextWindowPos({600, 100}, ImGuiCond_FirstUseEver); ImGui::Begin("Hidden Devices"); ImGui::BeginChild("Inner", {0.f, ImGui::GetItemRectSize().y - 64}, true); std::ranges::for_each(avail_devices_, [this](const auto& device) { diff --git a/GlosSITarget/Overlay.cpp b/GlosSITarget/Overlay.cpp index 33fe78d..2e2a161 100644 --- a/GlosSITarget/Overlay.cpp +++ b/GlosSITarget/Overlay.cpp @@ -84,7 +84,7 @@ Overlay::Overlay( colors[ImGuiCol_FrameBgActive] = ImVec4(0.09f, 0.12f, 0.14f, 1.00f); colors[ImGuiCol_TitleBg] = ImVec4(0.18f, 0.21f, 0.24f, 0.94f); colors[ImGuiCol_TitleBgActive] = ImVec4(0.26f, 0.29f, 0.34f, 0.93f); - colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f); + colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.16f, 0.19f, 0.22f, 0.81f); colors[ImGuiCol_MenuBarBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f); colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.39f); colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f); @@ -151,8 +151,9 @@ void Overlay::update() if (enabled_ || force_enable_) { window_.clear(sf::Color(0, 0, 0, 128)); // make window slightly dim screen with overlay - - std::ranges::for_each(OVERLAY_ELEMS_, [](const auto& fn) { fn(); }); + std::ranges::for_each(OVERLAY_ELEMS_, [this](const auto& fn) { + fn(); + }); // ImGui::ShowDemoWindow(); @@ -199,6 +200,7 @@ void Overlay::showLogs() const } if (logs.empty()) return; + ImGui::SetNextWindowSizeConstraints({150, 150}, {1000, window_.getSize().y - 250.f}); if (!enabled_) { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, {32.f, 32.f}); ImGui::Begin("Log", nullptr, @@ -222,6 +224,7 @@ void Overlay::showLogs() const ImGui::Text(msg.payload.data()); } }); + ImGui::SetScrollY(ImGui::GetScrollMaxY()); ImGui::End(); if (!enabled_) { ImGui::PopStyleVar(); diff --git a/GlosSITarget/Resource.rc b/GlosSITarget/Resource.rc index 8c57e30..bd7f32d 100644 --- a/GlosSITarget/Resource.rc +++ b/GlosSITarget/Resource.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,0,0,5419086 - PRODUCTVERSION 0,0,0,5419086 + FILEVERSION 0,0,0,0041050 + PRODUCTVERSION 0,0,0,0041050 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -69,12 +69,12 @@ BEGIN BEGIN VALUE "CompanyName", "Peter Repukat - FlatspotSoftware" VALUE "FileDescription", "GlosSI - SteamTarget" - VALUE "FileVersion", "0.0.0.5419d86" + VALUE "FileVersion", "0.0.0.cb41e5f" VALUE "InternalName", "GlosSITarget" VALUE "LegalCopyright", "Copyright (C) 2021 Peter Repukat - FlatspotSoftware" VALUE "OriginalFilename", "GlosSITarget.exe" VALUE "ProductName", "GlosSI" - VALUE "ProductVersion", "0.0.0.5419d86" + VALUE "ProductVersion", "0.0.0.cb41e5f" END END BLOCK "VarFileInfo" @@ -316,6 +316,150 @@ END + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/GlosSITarget/SteamTarget.cpp b/GlosSITarget/SteamTarget.cpp index 123c34e..bc97a46 100644 --- a/GlosSITarget/SteamTarget.cpp +++ b/GlosSITarget/SteamTarget.cpp @@ -25,6 +25,11 @@ limitations under the License. #include #include +#ifdef _WIN32 +#include "UWPOverlayEnabler.h" +#endif + + SteamTarget::SteamTarget(int argc, char* argv[]) : window_( [this] { run_ = false; }, @@ -41,6 +46,9 @@ SteamTarget::SteamTarget(int argc, char* argv[]) }) { target_window_handle_ = window_.getSystemHandle(); +#ifdef _WIN32 + UWPOverlayEnabler::AddUwpOverlayOvWidget(); +#endif } int SteamTarget::run() diff --git a/GlosSITarget/TargetWindow.cpp b/GlosSITarget/TargetWindow.cpp index 67aeeef..eb88f16 100644 --- a/GlosSITarget/TargetWindow.cpp +++ b/GlosSITarget/TargetWindow.cpp @@ -48,6 +48,7 @@ TargetWindow::TargetWindow( Overlay::AddOverlayElem([this]() { bool windowed_copy = windowed_; + ImGui::SetNextWindowPos({650, 450}, ImGuiCond_FirstUseEver); ImGui::Begin("Window mode"); if (ImGui::Checkbox("Window mode", &windowed_copy)) { toggle_window_mode_after_frame_ = true; diff --git a/GlosSITarget/UWPOverlayEnabler.h b/GlosSITarget/UWPOverlayEnabler.h new file mode 100644 index 0000000..c227946 --- /dev/null +++ b/GlosSITarget/UWPOverlayEnabler.h @@ -0,0 +1,83 @@ +#pragma once + +#include +#include + +#include "DllInjector.h" +#include "Overlay.h" + +namespace UWPOverlayEnabler { + +namespace internal { + +inline std::filesystem::path EnablerPath() +{ + wchar_t buff[MAX_PATH]; + GetModuleFileName(GetModuleHandle(NULL), buff, MAX_PATH); + const std::wstring path(buff); + return path.substr(0, 1 + path.find_last_of(L'\\')) + L"UWPOverlayEnablerDLL.dll"; +} + +inline DWORD ExplorerPid() +{ + PROCESSENTRY32 entry; + entry.dwSize = sizeof(PROCESSENTRY32); + HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); + if (Process32First(snapshot, &entry) == TRUE) { + while (Process32Next(snapshot, &entry) == TRUE) { + if (std::wstring(entry.szExeFile).find(L"explorer.exe") != std::string::npos) { + return entry.th32ProcessID; + } + } + } + CloseHandle(snapshot); + return 0; +} + +} + +inline void AddUwpOverlayOvWidget() +{ + Overlay::AddOverlayElem([]() { + ImGui::SetNextWindowPos({950, 100}, ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSizeConstraints({170, 225}, {1000, 1000}); + ImGui::SetNextWindowCollapsed(true, ImGuiCond_FirstUseEver); + ImGui::Begin("UWP-Overlay"); + ImGui::Text("To enable the overlay on top of \"fullscreen\" UWP-Apps,"); + ImGui::Text("a .dll has to be injected into explorer.exe"); + ImGui::Spacing(); + ImGui::Spacing(); + ImGui::Text("This method also uses undocumented windows functions"); + ImGui::Text("and is highly experimental"); + ImGui::Spacing(); + ImGui::Spacing(); + ImGui::Text("This might cause issues!!!"); + ImGui::Spacing(); + if (ImGui::CollapsingHeader("I am sure!")) { + if (ImGui::Button(/* just */ "DO IT!")) { // insert meme gif here >.< + const auto enabler_path = internal::EnablerPath(); + if (std::filesystem::exists(enabler_path)) { + const auto explorer_pid = internal::ExplorerPid(); + if (explorer_pid != 0) { + if (DllInjector::TakeDebugPrivilege()) { + // No need to eject, as the dll is self-ejecting. + if (DllInjector::Inject(explorer_pid, enabler_path.wstring())) { + spdlog::info("Successfully injected UWPOverlay enabler into explorer.exe"); + // Nesting level over 9000 + } + } + } + else { + spdlog::error("explorer not found"); // needs loglevel WTF + } + } + else { + spdlog::error("UWPOverlayEnablerDLL not found"); + } + } + } + ImGui::End(); + }); +} + +} \ No newline at end of file diff --git a/GlosSITarget/main.cpp b/GlosSITarget/main.cpp index 906e168..6fe9468 100644 --- a/GlosSITarget/main.cpp +++ b/GlosSITarget/main.cpp @@ -62,7 +62,7 @@ int main(int argc, char* argv[]) const auto overlay_sink = std::make_shared(); #ifdef _DEBUG - overlay_sink->set_level(spdlog::level::debug); // TODO: make configurable + overlay_sink->set_level(spdlog::level::debug); #else overlay_sink->set_level(spdlog::level::info); #endif