fox
This commit is contained in:
1 parent
82004f6b5e
commit
e0347fe1cb
8 files changed
+97
-13
No files matched your search
@@ -10,6 +10,7 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
|||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
add_compile_options(/W3 /utf-8 /MP)
|
add_compile_options(/W3 /utf-8 /MP)
|
||||||
|
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(Slinky)
|
add_subdirectory(Slinky)
|
||||||
|
|||||||
@@ -8,6 +8,10 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://discord.gg/AEwatvnvSf">https://discord.gg/AEwatvnvSf</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="assets/jak.jpg" alt="jak" height="150" />
|
<img src="assets/jak.jpg" alt="jak" height="150" />
|
||||||
<img src="assets/hack.jpg" alt="hack" height="150" />
|
<img src="assets/hack.jpg" alt="hack" height="150" />
|
||||||
@@ -17,6 +21,12 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="assets/proof.png" alt="proof" width="500" />
|
||||||
|
</p>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## How to build
|
## How to build
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ public:
|
|||||||
static std::vector<TargetWindow> FindMinecraftWindows();
|
static std::vector<TargetWindow> FindMinecraftWindows();
|
||||||
static bool IsModuleLoaded(DWORD pid, const wchar_t* moduleName);
|
static bool IsModuleLoaded(DWORD pid, const wchar_t* moduleName);
|
||||||
static bool WaitForModuleLoad(DWORD pid, const wchar_t* moduleName, DWORD timeoutMs);
|
static bool WaitForModuleLoad(DWORD pid, const wchar_t* moduleName, DWORD timeoutMs);
|
||||||
|
static bool UnloadModule(DWORD pid, const wchar_t* moduleName);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Slinky
|
} // namespace Slinky
|
||||||
+11
-2
@@ -70,8 +70,12 @@ bool Injector::ExtractBundledDll(std::wstring& outDllPath, std::wstring& outLogP
|
|||||||
|
|
||||||
bool Injector::InjectDll(DWORD pid, const std::wstring& dllPath) {
|
bool Injector::InjectDll(DWORD pid, const std::wstring& dllPath) {
|
||||||
if (ProcessUtil::IsModuleLoaded(pid, L"SlinkyNative.dll")) {
|
if (ProcessUtil::IsModuleLoaded(pid, L"SlinkyNative.dll")) {
|
||||||
ConsoleUI::SetStatusText("DLL already loaded.");
|
ConsoleUI::SetStatusText("Unloading previous instance...");
|
||||||
return true;
|
if (!ProcessUtil::UnloadModule(pid, L"SlinkyNative.dll")) {
|
||||||
|
ConsoleUI::SetStatusText("Could not unload previous instance.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Sleep(300);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConsoleUI::SetStatusText("Opening game process");
|
ConsoleUI::SetStatusText("Opening game process");
|
||||||
@@ -138,6 +142,11 @@ bool Injector::InjectDll(DWORD pid, const std::wstring& dllPath) {
|
|||||||
VirtualFreeEx(hProcess, pRemotePath, 0, MEM_RELEASE);
|
VirtualFreeEx(hProcess, pRemotePath, 0, MEM_RELEASE);
|
||||||
CloseHandle(hProcess);
|
CloseHandle(hProcess);
|
||||||
|
|
||||||
|
if (dwExitCode == 0) {
|
||||||
|
ConsoleUI::SetStatusText("LoadLibraryW failed in game process.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ProcessUtil::WaitForModuleLoad(pid, L"SlinkyNative.dll", 5000)) {
|
if (!ProcessUtil::WaitForModuleLoad(pid, L"SlinkyNative.dll", 5000)) {
|
||||||
ConsoleUI::SetStatusText("DLL not in game after load attempt.");
|
ConsoleUI::SetStatusText("DLL not in game after load attempt.");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -97,4 +97,55 @@ bool ProcessUtil::WaitForModuleLoad(DWORD pid, const wchar_t* moduleName, DWORD
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ProcessUtil::UnloadModule(DWORD pid, const wchar_t* moduleName) {
|
||||||
|
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);
|
||||||
|
if (hSnap == INVALID_HANDLE_VALUE) return false;
|
||||||
|
|
||||||
|
MODULEENTRY32W me;
|
||||||
|
me.dwSize = sizeof(me);
|
||||||
|
|
||||||
|
HMODULE hTargetModule = nullptr;
|
||||||
|
if (Module32FirstW(hSnap, &me)) {
|
||||||
|
do {
|
||||||
|
if (_wcsicmp(me.szModule, moduleName) == 0 ||
|
||||||
|
wcsstr(me.szExePath, moduleName) != nullptr)
|
||||||
|
{
|
||||||
|
hTargetModule = me.hModule;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (Module32NextW(hSnap, &me));
|
||||||
|
}
|
||||||
|
CloseHandle(hSnap);
|
||||||
|
|
||||||
|
if (!hTargetModule) return true;
|
||||||
|
|
||||||
|
HANDLE hProcess = OpenProcess(
|
||||||
|
PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION,
|
||||||
|
FALSE, pid);
|
||||||
|
if (!hProcess) return false;
|
||||||
|
|
||||||
|
HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll");
|
||||||
|
LPTHREAD_START_ROUTINE pFreeLibrary = (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "FreeLibrary");
|
||||||
|
if (!pFreeLibrary) {
|
||||||
|
CloseHandle(hProcess);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE hThread = CreateRemoteThread(hProcess, nullptr, 0, pFreeLibrary, (LPVOID)hTargetModule, 0, nullptr);
|
||||||
|
if (hThread) {
|
||||||
|
WaitForSingleObject(hThread, 5000);
|
||||||
|
CloseHandle(hThread);
|
||||||
|
}
|
||||||
|
CloseHandle(hProcess);
|
||||||
|
|
||||||
|
DWORD elapsed = 0;
|
||||||
|
while (elapsed < 3000) {
|
||||||
|
if (!IsModuleLoaded(pid, moduleName)) return true;
|
||||||
|
Sleep(50);
|
||||||
|
elapsed += 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !IsModuleLoaded(pid, moduleName);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Slinky
|
} // namespace Slinky
|
||||||
@@ -6,11 +6,7 @@
|
|||||||
|
|
||||||
static HMODULE g_hModule = nullptr;
|
static HMODULE g_hModule = nullptr;
|
||||||
|
|
||||||
DWORD WINAPI SlinkyNativeWorkerThread(LPVOID lpParam) {
|
static DWORD RunWorker(HMODULE hModule) {
|
||||||
HMODULE hModule = (HMODULE)lpParam;
|
|
||||||
|
|
||||||
SlinkyNative::Logger::Initialize(hModule);
|
|
||||||
|
|
||||||
if (!SlinkyNative::JvmManager::Initialize()) {
|
if (!SlinkyNative::JvmManager::Initialize()) {
|
||||||
SlinkyNative::Logger::Log(L"FINAL STATUS: FAILED");
|
SlinkyNative::Logger::Log(L"FINAL STATUS: FAILED");
|
||||||
return 1;
|
return 1;
|
||||||
@@ -27,6 +23,22 @@ DWORD WINAPI SlinkyNativeWorkerThread(LPVOID lpParam) {
|
|||||||
return (status == SlinkyNative::InjectionStatus::Success || status == SlinkyNative::InjectionStatus::AlreadyRunning) ? 0 : 1;
|
return (status == SlinkyNative::InjectionStatus::Success || status == SlinkyNative::InjectionStatus::AlreadyRunning) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DWORD WINAPI SlinkyNativeWorkerThread(LPVOID lpParam) {
|
||||||
|
HMODULE hModule = (HMODULE)lpParam;
|
||||||
|
SlinkyNative::Logger::Initialize(hModule);
|
||||||
|
|
||||||
|
DWORD ret = 1;
|
||||||
|
__try {
|
||||||
|
ret = RunWorker(hModule);
|
||||||
|
}
|
||||||
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||||||
|
SlinkyNative::Logger::Log(L"SlinkyNativeWorkerThread crashed with exception 0x%08X", GetExceptionCode());
|
||||||
|
SlinkyNative::Logger::Log(L"FINAL STATUS: FAILED");
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) {
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) {
|
||||||
switch (fdwReason) {
|
switch (fdwReason) {
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
|
|||||||
@@ -355,11 +355,7 @@ bool PayloadLoader::DefinePayloadClasses(JNIEnv* env, jobject classLoader, const
|
|||||||
env->ReleaseStringUTFChars(nameStr, nameChars);
|
env->ReleaseStringUTFChars(nameStr, nameChars);
|
||||||
|
|
||||||
if (entryName.rfind("dev/slinky/", 0) == 0 && entryName.size() > 6 && entryName.substr(entryName.size() - 6) == ".class") {
|
if (entryName.rfind("dev/slinky/", 0) == 0 && entryName.size() > 6 && entryName.substr(entryName.size() - 6) == ".class") {
|
||||||
// Convert "dev/slinky/Foo.class" -> "dev.slinky.Foo"
|
std::string internalName = entryName.substr(0, entryName.size() - 6);
|
||||||
std::string className = entryName.substr(0, entryName.size() - 6);
|
|
||||||
for (char& c : className) {
|
|
||||||
if (c == '/') c = '.';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read bytes
|
// Read bytes
|
||||||
jobject inputStream = env->CallObjectMethod(jarObj, jarGetInputStream, entry);
|
jobject inputStream = env->CallObjectMethod(jarObj, jarGetInputStream, entry);
|
||||||
@@ -375,7 +371,11 @@ bool PayloadLoader::DefinePayloadClasses(JNIEnv* env, jobject classLoader, const
|
|||||||
jsize byteLen = env->GetArrayLength(classBytesArr);
|
jsize byteLen = env->GetArrayLength(classBytesArr);
|
||||||
jbyte* rawBytes = env->GetByteArrayElements(classBytesArr, nullptr);
|
jbyte* rawBytes = env->GetByteArrayElements(classBytesArr, nullptr);
|
||||||
if (rawBytes) {
|
if (rawBytes) {
|
||||||
jclass definedClass = env->DefineClass(nullptr, classLoader, rawBytes, byteLen);
|
jclass definedClass = env->DefineClass(internalName.c_str(), classLoader, rawBytes, byteLen);
|
||||||
|
if (!definedClass) {
|
||||||
|
env->ExceptionClear();
|
||||||
|
definedClass = env->DefineClass(nullptr, classLoader, rawBytes, byteLen);
|
||||||
|
}
|
||||||
if (definedClass) {
|
if (definedClass) {
|
||||||
definedCount++;
|
definedCount++;
|
||||||
env->DeleteLocalRef(definedClass);
|
env->DeleteLocalRef(definedClass);
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 806 KiB |
Reference in new issue
Block a user