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)
|
||||
add_compile_options(/W3 /utf-8 /MP)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
endif()
|
||||
|
||||
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">
|
||||
<img src="assets/jak.jpg" alt="jak" 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
|
||||
|
||||
### Prerequisites
|
||||
|
||||
@@ -18,6 +18,7 @@ public:
|
||||
static std::vector<TargetWindow> FindMinecraftWindows();
|
||||
static bool IsModuleLoaded(DWORD pid, const wchar_t* moduleName);
|
||||
static bool WaitForModuleLoad(DWORD pid, const wchar_t* moduleName, DWORD timeoutMs);
|
||||
static bool UnloadModule(DWORD pid, const wchar_t* moduleName);
|
||||
};
|
||||
|
||||
} // 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) {
|
||||
if (ProcessUtil::IsModuleLoaded(pid, L"SlinkyNative.dll")) {
|
||||
ConsoleUI::SetStatusText("DLL already loaded.");
|
||||
return true;
|
||||
ConsoleUI::SetStatusText("Unloading previous instance...");
|
||||
if (!ProcessUtil::UnloadModule(pid, L"SlinkyNative.dll")) {
|
||||
ConsoleUI::SetStatusText("Could not unload previous instance.");
|
||||
return false;
|
||||
}
|
||||
Sleep(300);
|
||||
}
|
||||
|
||||
ConsoleUI::SetStatusText("Opening game process");
|
||||
@@ -138,6 +142,11 @@ bool Injector::InjectDll(DWORD pid, const std::wstring& dllPath) {
|
||||
VirtualFreeEx(hProcess, pRemotePath, 0, MEM_RELEASE);
|
||||
CloseHandle(hProcess);
|
||||
|
||||
if (dwExitCode == 0) {
|
||||
ConsoleUI::SetStatusText("LoadLibraryW failed in game process.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ProcessUtil::WaitForModuleLoad(pid, L"SlinkyNative.dll", 5000)) {
|
||||
ConsoleUI::SetStatusText("DLL not in game after load attempt.");
|
||||
return false;
|
||||
|
||||
@@ -97,4 +97,55 @@ bool ProcessUtil::WaitForModuleLoad(DWORD pid, const wchar_t* moduleName, DWORD
|
||||
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
|
||||
@@ -6,11 +6,7 @@
|
||||
|
||||
static HMODULE g_hModule = nullptr;
|
||||
|
||||
DWORD WINAPI SlinkyNativeWorkerThread(LPVOID lpParam) {
|
||||
HMODULE hModule = (HMODULE)lpParam;
|
||||
|
||||
SlinkyNative::Logger::Initialize(hModule);
|
||||
|
||||
static DWORD RunWorker(HMODULE hModule) {
|
||||
if (!SlinkyNative::JvmManager::Initialize()) {
|
||||
SlinkyNative::Logger::Log(L"FINAL STATUS: FAILED");
|
||||
return 1;
|
||||
@@ -27,6 +23,22 @@ DWORD WINAPI SlinkyNativeWorkerThread(LPVOID lpParam) {
|
||||
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) {
|
||||
switch (fdwReason) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
|
||||
@@ -355,11 +355,7 @@ bool PayloadLoader::DefinePayloadClasses(JNIEnv* env, jobject classLoader, const
|
||||
env->ReleaseStringUTFChars(nameStr, nameChars);
|
||||
|
||||
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 className = entryName.substr(0, entryName.size() - 6);
|
||||
for (char& c : className) {
|
||||
if (c == '/') c = '.';
|
||||
}
|
||||
std::string internalName = entryName.substr(0, entryName.size() - 6);
|
||||
|
||||
// Read bytes
|
||||
jobject inputStream = env->CallObjectMethod(jarObj, jarGetInputStream, entry);
|
||||
@@ -375,7 +371,11 @@ bool PayloadLoader::DefinePayloadClasses(JNIEnv* env, jobject classLoader, const
|
||||
jsize byteLen = env->GetArrayLength(classBytesArr);
|
||||
jbyte* rawBytes = env->GetByteArrayElements(classBytesArr, nullptr);
|
||||
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) {
|
||||
definedCount++;
|
||||
env->DeleteLocalRef(definedClass);
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 806 KiB |
Reference in new issue
Block a user