diff --git a/.gitignore b/.gitignore index 2237a27..29265af 100644 --- a/.gitignore +++ b/.gitignore @@ -339,4 +339,5 @@ ASALocalRun/ .localhistory/ # BeatPulse healthcheck temp database -healthchecksdb \ No newline at end of file +healthchecksdb +/PluginDevFolder/PlaygroundPlugin diff --git a/SMInjector/SMInjector.sln b/SMInjector/SMInjector.sln index 953989b..a160e7b 100644 --- a/SMInjector/SMInjector.sln +++ b/SMInjector/SMInjector.sln @@ -24,27 +24,58 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SMLuaReaderPlugin", "..\Plu {81368E09-9FA2-4F28-9915-22FE758BFD48} = {81368E09-9FA2-4F28-9915-22FE758BFD48} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PlaygroundPlugin", "..\PluginDevFolder\PlaygroundPlugin\PlaygroundPlugin.vcxproj", "{53AE29AD-5DEB-4557-A65E-6E68D2E5336A}" + ProjectSection(ProjectDependencies) = postProject + {81368E09-9FA2-4F28-9915-22FE758BFD48} = {81368E09-9FA2-4F28-9915-22FE758BFD48} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {E94AFAD6-2262-40E4-81D3-CD0130B98C0B}.Debug|x64.ActiveCfg = Debug|x64 + {E94AFAD6-2262-40E4-81D3-CD0130B98C0B}.Debug|x86.ActiveCfg = Debug|x64 {E94AFAD6-2262-40E4-81D3-CD0130B98C0B}.Release|x64.ActiveCfg = Release|x64 {E94AFAD6-2262-40E4-81D3-CD0130B98C0B}.Release|x64.Build.0 = Release|x64 + {E94AFAD6-2262-40E4-81D3-CD0130B98C0B}.Release|x86.ActiveCfg = Release|x64 {81368E09-9FA2-4F28-9915-22FE758BFD48}.Debug|x64.ActiveCfg = Debug|x64 + {81368E09-9FA2-4F28-9915-22FE758BFD48}.Debug|x86.ActiveCfg = Debug|Win32 + {81368E09-9FA2-4F28-9915-22FE758BFD48}.Debug|x86.Build.0 = Debug|Win32 {81368E09-9FA2-4F28-9915-22FE758BFD48}.Release|x64.ActiveCfg = Release|x64 {81368E09-9FA2-4F28-9915-22FE758BFD48}.Release|x64.Build.0 = Release|x64 + {81368E09-9FA2-4F28-9915-22FE758BFD48}.Release|x86.ActiveCfg = Release|Win32 + {81368E09-9FA2-4F28-9915-22FE758BFD48}.Release|x86.Build.0 = Release|Win32 {F09BBCFB-A1E3-43E0-8406-FBC8B72A09CA}.Debug|x64.ActiveCfg = Debug|x64 + {F09BBCFB-A1E3-43E0-8406-FBC8B72A09CA}.Debug|x86.ActiveCfg = Debug|Win32 + {F09BBCFB-A1E3-43E0-8406-FBC8B72A09CA}.Debug|x86.Build.0 = Debug|Win32 {F09BBCFB-A1E3-43E0-8406-FBC8B72A09CA}.Release|x64.ActiveCfg = Release|x64 {F09BBCFB-A1E3-43E0-8406-FBC8B72A09CA}.Release|x64.Build.0 = Release|x64 + {F09BBCFB-A1E3-43E0-8406-FBC8B72A09CA}.Release|x86.ActiveCfg = Release|Win32 + {F09BBCFB-A1E3-43E0-8406-FBC8B72A09CA}.Release|x86.Build.0 = Release|Win32 {16BDCA26-D20C-4AC4-8DB3-9C108719B752}.Debug|x64.ActiveCfg = Debug|x64 + {16BDCA26-D20C-4AC4-8DB3-9C108719B752}.Debug|x86.ActiveCfg = Debug|Win32 + {16BDCA26-D20C-4AC4-8DB3-9C108719B752}.Debug|x86.Build.0 = Debug|Win32 {16BDCA26-D20C-4AC4-8DB3-9C108719B752}.Release|x64.ActiveCfg = Release|x64 {16BDCA26-D20C-4AC4-8DB3-9C108719B752}.Release|x64.Build.0 = Release|x64 + {16BDCA26-D20C-4AC4-8DB3-9C108719B752}.Release|x86.ActiveCfg = Release|Win32 + {16BDCA26-D20C-4AC4-8DB3-9C108719B752}.Release|x86.Build.0 = Release|Win32 {13E88C11-DEB6-47D5-9382-4E5D484A58C2}.Debug|x64.ActiveCfg = Debug|x64 + {13E88C11-DEB6-47D5-9382-4E5D484A58C2}.Debug|x86.ActiveCfg = Debug|x64 {13E88C11-DEB6-47D5-9382-4E5D484A58C2}.Release|x64.ActiveCfg = Release|x64 {13E88C11-DEB6-47D5-9382-4E5D484A58C2}.Release|x64.Build.0 = Release|x64 + {13E88C11-DEB6-47D5-9382-4E5D484A58C2}.Release|x86.ActiveCfg = Release|x64 + {53AE29AD-5DEB-4557-A65E-6E68D2E5336A}.Debug|x64.ActiveCfg = Debug|x64 + {53AE29AD-5DEB-4557-A65E-6E68D2E5336A}.Debug|x64.Build.0 = Debug|x64 + {53AE29AD-5DEB-4557-A65E-6E68D2E5336A}.Debug|x86.ActiveCfg = Debug|Win32 + {53AE29AD-5DEB-4557-A65E-6E68D2E5336A}.Debug|x86.Build.0 = Debug|Win32 + {53AE29AD-5DEB-4557-A65E-6E68D2E5336A}.Release|x64.ActiveCfg = Release|x64 + {53AE29AD-5DEB-4557-A65E-6E68D2E5336A}.Release|x64.Build.0 = Release|x64 + {53AE29AD-5DEB-4557-A65E-6E68D2E5336A}.Release|x86.ActiveCfg = Release|Win32 + {53AE29AD-5DEB-4557-A65E-6E68D2E5336A}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -53,6 +84,7 @@ Global {F09BBCFB-A1E3-43E0-8406-FBC8B72A09CA} = {4EC6A5BC-FCE4-4FFE-AC55-7D83B6B7C8D7} {16BDCA26-D20C-4AC4-8DB3-9C108719B752} = {4EC6A5BC-FCE4-4FFE-AC55-7D83B6B7C8D7} {13E88C11-DEB6-47D5-9382-4E5D484A58C2} = {4EC6A5BC-FCE4-4FFE-AC55-7D83B6B7C8D7} + {53AE29AD-5DEB-4557-A65E-6E68D2E5336A} = {4EC6A5BC-FCE4-4FFE-AC55-7D83B6B7C8D7} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D7E2F6B1-96AC-4FB5-B8AA-FDB43C7F169E} diff --git a/SMInjector/src/find_steam.h b/SMInjector/src/find_steam.h index 9e67d82..ccb9fc1 100644 --- a/SMInjector/src/find_steam.h +++ b/SMInjector/src/find_steam.h @@ -13,35 +13,28 @@ namespace SteamFinder { using std::vector; using std::filesystem::directory_iterator; - LONG get_registry_string(HKEY hKey, const char* key_name, string& strValue) { - CHAR szBuffer[512] = { 0 }; + LONG get_registry_string(HKEY hKey, const wchar_t* key_name, std::wstring& strValue) { + wchar_t szBuffer[512] = { 0 }; DWORD dwBufferSize = sizeof(szBuffer); - ULONG nError = RegQueryValueExA(hKey, key_name, 0, NULL, (LPBYTE)szBuffer, &dwBufferSize); + ULONG nError = RegQueryValueExW(hKey, key_name, 0, NULL, (LPBYTE)szBuffer, &dwBufferSize); if(nError == ERROR_SUCCESS) strValue = szBuffer; return nError; } - string get_game_path() { + std::wstring get_game_path() { HKEY hKey; LONG lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\WOW6432Node\\Valve\\Steam", 0, KEY_READ, &hKey); - string install_path; - get_registry_string(hKey, "InstallPath", install_path); + std::wstring install_path; + get_registry_string(hKey, L"InstallPath", install_path); RegCloseKey(hKey); return install_path; } - /* - inline bool does_file_exist(const string& name) { - struct stat buffer; - return (stat(name.c_str(), &buffer) == 0); - } - */ - - vector get_steam_libraries(string install_path, string vdf_file) { - vector vec; + vector get_steam_libraries(std::wstring install_path, std::wstring vdf_file) { + vector vec; vec.reserve(10); - vec.push_back(install_path.append("\\steamapps\\common")); + vec.push_back(install_path.append(L"\\steamapps\\common")); if(vdf_file.empty()) { return vec; } @@ -50,7 +43,7 @@ namespace SteamFinder { std::string buffer(std::istreambuf_iterator{infile}, {}); if(!buffer.empty()) { - char temp[2048] = { 0 }; + wchar_t temp[2048] = { 0 }; int idx = 0; int len = 0; @@ -64,7 +57,7 @@ namespace SteamFinder { if(i > 16 && quote) { len++; if(len > 4 && ((len & 1) == 0)) { - vec.push_back(string(temp).append("\\steamapps\\common")); + vec.push_back(std::wstring(temp).append(L"\\steamapps\\common")); } temp[0] = 0; @@ -83,29 +76,26 @@ namespace SteamFinder { return vec; } - string find_game_from_libs(vector list, const char* game) { - std::wstring name(game, game + strlen(game)); + std::wstring find_game_from_libs(vector list, const wchar_t* game) { + std::wstring name(game); for(int i = 0; i < list.size(); i++) { for(const auto& file : directory_iterator(list[i])) { if(file.path().filename().compare(name) == 0) { - char szBuffer[512] = { 0 }; - size_t num; - wcstombs_s(&num, szBuffer, file.path().c_str(), 512); - return string(szBuffer); + return std::wstring(file.path()); } } } - return ""; + return L""; } - string FindGame(const char* game) { - string install_path = get_game_path(); - if(install_path.empty()) return ""; + std::wstring FindGame(const wchar_t* game) { + std::wstring install_path = get_game_path(); + if(install_path.empty()) return L""; - string vdf_test = string(install_path).append("\\steamapps\\libraryfolders.vdf"); - vector libs = get_steam_libraries(install_path, vdf_test); + std::wstring vdf_test = std::wstring(install_path).append(L"\\steamapps\\libraryfolders.vdf"); + vector libs = get_steam_libraries(install_path, vdf_test); return find_game_from_libs(libs, game); } } diff --git a/SMInjector/src/main.cpp b/SMInjector/src/main.cpp index 129c794..fa7393c 100644 --- a/SMInjector/src/main.cpp +++ b/SMInjector/src/main.cpp @@ -9,50 +9,50 @@ #include "find_steam.h" -bool Inject(HANDLE, const char*); +bool Inject(HANDLE, const wchar_t*); -inline bool does_file_exist(const char* name) { - struct stat buffer; - return (stat(name, &buffer) == 0); +inline bool does_file_exist(const wchar_t* name) { + struct _stat buffer; + return (_wstat(name, &buffer) == 0); } -std::string get_dir_path() { - CHAR buffer[MAX_PATH] = { 0 }; - GetModuleFileNameA(NULL, buffer, MAX_PATH); - std::string::size_type pos = std::string(buffer).find_last_of("\\/"); - return std::string(buffer).substr(0, pos); +std::wstring get_dir_path() { + wchar_t buffer[MAX_PATH] = { 0 }; + GetModuleFileNameW(NULL, buffer, MAX_PATH); + std::wstring::size_type pos = std::wstring(buffer).find_last_of(L"\\/"); + return std::wstring(buffer).substr(0, pos); } -std::string get_dll_path(const char* dll_name) { - CHAR buffer[MAX_PATH] = { 0 }; - GetModuleFileNameA(NULL, buffer, MAX_PATH); - std::string::size_type pos = std::string(buffer).find_last_of("\\/"); - return std::string(buffer).substr(0, pos).append("\\").append(dll_name); +std::wstring get_dll_path(const wchar_t* dll_name) { + wchar_t buffer[MAX_PATH] = { 0 }; + GetModuleFileNameW(NULL, buffer, MAX_PATH); + std::wstring::size_type pos = std::wstring(buffer).find_last_of(L"\\/"); + return std::wstring(buffer).substr(0, pos).append(L"\\").append(dll_name); } -BOOL startup(std::string in_exe, std::string in_dir, std::string in_cmd, HANDLE &hProcess, HANDLE &hThread) { - STARTUPINFOA si; +BOOL startup(std::wstring in_exe, std::wstring in_dir, std::wstring in_cmd, HANDLE &hProcess, HANDLE &hThread) { + STARTUPINFO si; PROCESS_INFORMATION pi; - CHAR exe[MAX_PATH + 1] = { 0 }; - CHAR dir[MAX_PATH + 1] = { 0 }; - CHAR cmd[4097] = { 0 }; + wchar_t exe[MAX_PATH + 1] = { 0 }; + wchar_t dir[MAX_PATH + 1] = { 0 }; + wchar_t cmd[4097] = { 0 }; ZeroMemory(cmd, 4097); - memcpy(exe, in_exe.c_str(), min(in_exe.size(), MAX_PATH + 1)); - memcpy(dir, in_dir.c_str(), min(in_dir.size(), MAX_PATH + 1)); - sprintf_s(cmd, 4097, "\"%s\" %s", exe, in_cmd.c_str()); + memcpy(exe, in_exe.c_str(), min(in_exe.size() * 2, MAX_PATH + 1)); + memcpy(dir, in_dir.c_str(), min(in_dir.size() * 2, MAX_PATH + 1)); + swprintf_s(cmd, 4097, L"\"%s\" %s", exe, in_cmd.c_str()); - // printf("EXE: [%s]\n", exe); - // printf("DIR: [%s]\n", dir); - // printf("CMD: [%s]\n", cmd); + //wprintf(L"EXE: [%s]\n", exe); + //wprintf(L"DIR: [%s]\n", dir); + //wprintf(L"CMD: [%s]\n", cmd); ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); si.wShowWindow = true; - if(!CreateProcessA( + if(!CreateProcessW( exe, cmd, NULL, NULL, @@ -78,11 +78,11 @@ BOOL startup(std::string in_exe, std::string in_dir, std::string in_cmd, HANDLE int main(int argc, char** argv) { printf("SMInjector: startup\n"); - std::string game_path = SteamFinder::FindGame("Scrap Mechanic"); - std::string dll_path = get_dll_path("SMLibrary.dll"); + std::wstring game_path = SteamFinder::FindGame(L"Scrap Mechanic"); + std::wstring dll_path = get_dll_path(L"SMLibrary.dll"); - printf("GAME: [%s]\n", game_path.c_str()); - printf("DLL : [%s]\n", dll_path.c_str()); + wprintf(L"GAME: [%s]\n", game_path.c_str()); + wprintf(L"DLL : [%s]\n", dll_path.c_str()); if(game_path.empty()) { printf("SMInjector: Failed to find the game \"ScrapMechanic\"\n"); @@ -91,9 +91,9 @@ int main(int argc, char** argv) { HANDLE hProcess; HANDLE hThread; - std::string exe_exe = std::string(game_path).append("\\Release\\ScrapMechanic.exe"); - std::string exe_dir = std::string(game_path).append("\\Release"); - if(startup(exe_exe, exe_dir, "-dev", hProcess, hThread)) { + std::wstring exe_exe = std::wstring(game_path).append(L"\\Release\\ScrapMechanic.exe"); + std::wstring exe_dir = std::wstring(game_path).append(L"\\Release"); + if(startup(exe_exe, exe_dir, L"-dev", hProcess, hThread)) { if(!Inject(hProcess, dll_path.c_str())) { printf("SMInjector: failed to inject dll file\n"); TerminateProcess(hProcess, 0); @@ -102,33 +102,28 @@ int main(int argc, char** argv) { } printf("\nSMInjector: Adding plugins.\n"); - for(const auto& file : std::filesystem::directory_iterator(get_dir_path().append("\\plugins"))) { - char dll_plugin[512] = { 0 }; - size_t num; - wcstombs_s(&num, dll_plugin, file.path().c_str(), 512); - - if(!Inject(hProcess, dll_plugin)) { + for(const auto& file : std::filesystem::directory_iterator(get_dir_path().append(L"\\plugins"))) { + if(!Inject(hProcess, file.path().c_str())) { wprintf(L" Failed to inject '%s'\n", file.path().filename().c_str()); return 0; } else { wprintf(L" Injected '%s'\n", file.path().filename().c_str()); } } - + Sleep(500); - ResumeThread(hThread); } return 0; } -bool Inject(HANDLE hProc, const char* path) { +bool Inject(HANDLE hProc, const wchar_t* path) { if(!does_file_exist(path)) { return false; } - const size_t path_length = strlen(path); + const size_t path_length = wcslen(path) * 2; LPVOID lpvoid = VirtualAllocEx(hProc, NULL, path_length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if(!lpvoid) { @@ -136,13 +131,12 @@ bool Inject(HANDLE hProc, const char* path) { } WriteProcessMemory(hProc, lpvoid, path, path_length, NULL); - HMODULE kernel32 = GetModuleHandleA("kernel32.dll"); if(!kernel32) { return false; } - LPVOID LoadLibAddr = (LPVOID)GetProcAddress(kernel32, "LoadLibraryA"); + LPVOID LoadLibAddr = (LPVOID)GetProcAddress(kernel32, "LoadLibraryW"); HANDLE threadID = CreateRemoteThread(hProc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddr, lpvoid, NULL, NULL); if(!threadID) { return false; diff --git a/SMLibrary/include/console.h b/SMLibrary/include/console.h index 48cac32..1c59933 100644 --- a/SMLibrary/include/console.h +++ b/SMLibrary/include/console.h @@ -6,6 +6,12 @@ #ifndef _SM_LIBRARY_BUILD_PLUGIN #include #include + +#ifdef _SM_OUTPUT_LOGS +#include +#include +#endif + #endif #include @@ -46,7 +52,11 @@ namespace Console { void log_open() { log_close(); +#ifdef _SM_OUTPUT_LOGS freopen_s(&console_handle, "CONOUT$", "w", stdout); +#else + freopen_s(&console_handle, "CONOUT$", "w", stdout); +#endif } _LIB_EXPORT diff --git a/SMLibrary/src/hooks.h b/SMLibrary/src/hooks.h index aa8336d..8dfcb60 100644 --- a/SMLibrary/src/hooks.h +++ b/SMLibrary/src/hooks.h @@ -12,6 +12,7 @@ Hook *hck_init_console; namespace Hooks { void hook_init_console(void* a, void* b) { + FreeConsole(); ((pinit_console)hck_init_console->Gate())(a, b); PostConsoleInjections(); return; diff --git a/SMLibrary/src/sm_lib.cpp b/SMLibrary/src/sm_lib.cpp index 62d9bf5..25650d0 100644 --- a/SMLibrary/src/sm_lib.cpp +++ b/SMLibrary/src/sm_lib.cpp @@ -4,6 +4,7 @@ #include #define _SM_PLUGIN_NAME SMLibrary +#define _SM_OUTPUT_LOGS #include "../include/sm_lib.h" #include "../include/hook.h" @@ -34,9 +35,9 @@ HookUtility *util; BOOL Startup(HMODULE hModule) { HMODULE sm_handle = GetModuleHandleA("ScrapMechanic.exe"); if(!sm_handle) return false; - + hck_init_console = new Hook(); - hck_init_console->Inject((void*)((longlong)sm_handle + offset_InitConsole), &Hooks::hook_init_console, 15); + hck_init_console->Inject((void*)((longlong)sm_handle + offset_InitConsole), &Hooks::hook_init_console, 0, 15); return true; }