added files.

This commit is contained in:
nitrogenoliquido committed 2026-10-14 22:15:53 -05:00
commit e908ab2355
353 files changed
+130515

No files matched your search

+22
View File
@@ -0,0 +1,22 @@
add_executable(Slinky
src/Main.cpp
src/Injector.cpp
src/ProcessUtil.cpp
src/ConsoleUI.cpp
Slinky.rc
)
target_include_directories(Slinky PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
)
target_compile_definitions(Slinky PRIVATE
_CRT_SECURE_NO_WARNINGS
WIN32_LEAN_AND_MEAN
)
set_target_properties(Slinky PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
OUTPUT_NAME "Slinky"
)
+5
View File
@@ -0,0 +1,5 @@
#include "include/Resource.h"
#ifdef EMBED_BUNDLED_DLL
IDR_BUNDLED_DLL RCDATA "SlinkyNative.dll"
#endif
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#include <windows.h>
#include <string>
#include <atomic>
namespace Slinky {
class ConsoleUI {
public:
static void Initialize();
static void Shutdown();
static void PrintBanner();
static void StartAnimation();
static void StopAnimation();
static void SetStatusText(const char* text);
static void PrintError(const char* action, DWORD errorCode);
private:
static DWORD WINAPI AnimationThread(LPVOID lpParam);
static CRITICAL_SECTION s_CriticalSection;
static char s_StatusText[512];
static std::atomic<bool> s_Running;
static HANDLE s_hAnimationThread;
static DWORD s_OriginalConsoleMode;
static HANDLE s_hConsole;
};
} // namespace Slinky
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#include <windows.h>
#include <string>
namespace Slinky {
class Injector {
public:
static bool ExtractBundledDll(std::wstring& outDllPath, std::wstring& outLogPath);
static bool InjectDll(DWORD pid, const std::wstring& dllPath);
static bool MonitorStartup(DWORD pid, const std::wstring& logPath);
};
} // namespace Slinky
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include <windows.h>
#include <string>
#include <vector>
namespace Slinky {
struct TargetWindow {
HWND hWnd = nullptr;
DWORD pid = 0;
std::wstring title;
};
class ProcessUtil {
public:
static std::vector<DWORD> GetJavaProcessIds();
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);
};
} // namespace Slinky
+3
View File
@@ -0,0 +1,3 @@
#pragma once
#define IDR_BUNDLED_DLL 200
+144
View File
@@ -0,0 +1,144 @@
#include "ConsoleUI.hpp"
#include <cstdio>
#include <cstring>
namespace Slinky {
CRITICAL_SECTION ConsoleUI::s_CriticalSection;
char ConsoleUI::s_StatusText[512] = { 0 };
std::atomic<bool> ConsoleUI::s_Running(false);
HANDLE ConsoleUI::s_hAnimationThread = nullptr;
DWORD ConsoleUI::s_OriginalConsoleMode = 0;
HANDLE ConsoleUI::s_hConsole = INVALID_HANDLE_VALUE;
void ConsoleUI::PrintBanner() {
const char* bannerLines[] = {
" _____ __ _ __",
" / ___// /__ (_)___/ /",
" \\__ \\/ //_// / __ / ",
" ___/ / ,< / / /_/ / ",
"/____/_/|_|/_/\\__,_/ ",
" _____ __ __ _ ",
" / ___/____ / /_ __/ /_(_)___ ____ _____",
" \\__ \\/ __ \\/ / / / / __/ / __ \\/ __ \\/ ___/",
" ___/ / /_/ / / /_/ / /_/ / /_/ / / / (__ ) ",
"/____/\\____/_/\\__,_/\\__/_/\\____/_/ /_/____/ "
};
for (size_t lineIdx = 0; lineIdx < 10; ++lineIdx) {
const char* line = bannerLines[lineIdx];
size_t blockWidth = (lineIdx < 5) ? 24 : 45;
size_t len = strlen(line);
for (size_t i = 0; i < len; ++i) {
float ratio = (float)i / (float)(blockWidth - 1);
if (ratio > 1.0f) ratio = 1.0f;
int val = (int)(255 - ratio * 200.0f);
if (val < 45) val = 45;
printf("\x1b[38;2;%d;%d;%dm%c", val, val, val, line[i]);
}
printf("\x1b[0m\n");
}
printf("\n");
fflush(stdout);
}
void ConsoleUI::Initialize() {
InitializeCriticalSection(&s_CriticalSection);
s_hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
if (s_hConsole != INVALID_HANDLE_VALUE) {
GetConsoleMode(s_hConsole, &s_OriginalConsoleMode);
SetConsoleMode(s_hConsole, s_OriginalConsoleMode | 0x0004);
}
SetConsoleTitleW(L"Slinky");
strcpy_s(s_StatusText, "SCANNING");
PrintBanner();
}
void ConsoleUI::Shutdown() {
StopAnimation();
if (s_hConsole != INVALID_HANDLE_VALUE && s_OriginalConsoleMode != 0) {
SetConsoleMode(s_hConsole, s_OriginalConsoleMode);
}
DeleteCriticalSection(&s_CriticalSection);
}
void ConsoleUI::SetStatusText(const char* text) {
EnterCriticalSection(&s_CriticalSection);
strncpy_s(s_StatusText, text, _TRUNCATE);
LeaveCriticalSection(&s_CriticalSection);
}
void ConsoleUI::PrintError(const char* action, DWORD errorCode) {
wchar_t* msgBuf = nullptr;
FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR)&msgBuf, 0, nullptr);
char errorStr[512] = "unknown";
if (msgBuf) {
WideCharToMultiByte(CP_UTF8, 0, msgBuf, -1, errorStr, 512, nullptr, nullptr);
LocalFree(msgBuf);
size_t len = strlen(errorStr);
while (len > 0 && (errorStr[len - 1] == '\r' || errorStr[len - 1] == '\n')) {
errorStr[--len] = '\0';
}
}
EnterCriticalSection(&s_CriticalSection);
printf("\n[!] %s failed with error %lu: %s\n", action, errorCode, errorStr);
fflush(stdout);
LeaveCriticalSection(&s_CriticalSection);
}
void ConsoleUI::StartAnimation() {
if (s_Running) return;
s_Running = true;
s_hAnimationThread = CreateThread(nullptr, 0, AnimationThread, nullptr, 0, nullptr);
}
void ConsoleUI::StopAnimation() {
if (!s_Running) return;
s_Running = false;
if (s_hAnimationThread) {
WaitForSingleObject(s_hAnimationThread, 1000);
CloseHandle(s_hAnimationThread);
s_hAnimationThread = nullptr;
}
printf("\n");
fflush(stdout);
}
DWORD WINAPI ConsoleUI::AnimationThread(LPVOID lpParam) {
const char* spinner[] = { "-", "\\", "|", "/" };
int frame = 0;
while (s_Running) {
char currentStatus[512] = { 0 };
EnterCriticalSection(&s_CriticalSection);
strncpy_s(currentStatus, s_StatusText, _TRUNCATE);
LeaveCriticalSection(&s_CriticalSection);
printf("\r\x1b[2K [%s] %s", spinner[frame % 4], currentStatus);
fflush(stdout);
frame++;
Sleep(160);
}
char finalStatus[512] = { 0 };
EnterCriticalSection(&s_CriticalSection);
strncpy_s(finalStatus, s_StatusText, _TRUNCATE);
LeaveCriticalSection(&s_CriticalSection);
printf("\r\x1b[2K [+] %s\n", finalStatus);
fflush(stdout);
return 0;
}
} // namespace Slinky
+201
View File
@@ -0,0 +1,201 @@
#include "Injector.hpp"
#include "ProcessUtil.hpp"
#include "ConsoleUI.hpp"
#include "Resource.h"
#include <cstdio>
#include <vector>
namespace Slinky {
bool Injector::ExtractBundledDll(std::wstring& outDllPath, std::wstring& outLogPath) {
wchar_t tempPath[MAX_PATH] = { 0 };
if (!GetTempPathW(MAX_PATH, tempPath)) {
ConsoleUI::PrintError("Finding temp folder", GetLastError());
return false;
}
wchar_t slinkyTempDir[MAX_PATH] = { 0 };
swprintf_s(slinkyTempDir, L"%lsslinky-%lu", tempPath, GetCurrentProcessId());
if (!CreateDirectoryW(slinkyTempDir, nullptr) && GetLastError() != ERROR_ALREADY_EXISTS) {
ConsoleUI::PrintError("Creating temp folder", GetLastError());
return false;
}
outDllPath = std::wstring(slinkyTempDir) + L"\\SlinkyNative.dll";
outLogPath = std::wstring(slinkyTempDir) + L"\\slinky-native.log";
DeleteFileW(outLogPath.c_str());
HRSRC hRes = FindResourceW(nullptr, MAKEINTRESOURCEW(IDR_BUNDLED_DLL), (LPCWSTR)10);
if (hRes) {
DWORD resSize = SizeofResource(nullptr, hRes);
HGLOBAL hLoad = LoadResource(nullptr, hRes);
if (hLoad && resSize > 0) {
const void* pData = LockResource(hLoad);
if (pData) {
HANDLE hFile = CreateFileW(outDllPath.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (hFile != INVALID_HANDLE_VALUE) {
DWORD written = 0;
WriteFile(hFile, pData, resSize, &written, nullptr);
CloseHandle(hFile);
return true;
}
}
}
}
wchar_t exePath[MAX_PATH] = { 0 };
if (GetModuleFileNameW(nullptr, exePath, MAX_PATH) > 0) {
wchar_t* lastSlash = wcsrchr(exePath, L'\\');
if (lastSlash) {
*lastSlash = L'\0';
std::wstring localDll = std::wstring(exePath) + L"\\SlinkyNative.dll";
if (GetFileAttributesW(localDll.c_str()) != INVALID_FILE_ATTRIBUTES) {
if (CopyFileW(localDll.c_str(), outDllPath.c_str(), FALSE)) {
return true;
}
outDllPath = localDll;
outLogPath = std::wstring(exePath) + L"\\slinky-native.log";
DeleteFileW(outLogPath.c_str());
return true;
}
}
}
ConsoleUI::SetStatusText("Could not extract bundled DLL.");
ConsoleUI::PrintError("Reading bundled DLL", ERROR_FILE_NOT_FOUND);
return false;
}
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("Opening game process");
HANDLE hProcess = OpenProcess(
PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
FALSE, pid);
if (!hProcess) {
ConsoleUI::PrintError("OpenProcess", GetLastError());
return false;
}
ConsoleUI::SetStatusText("Allocating DLL path in game");
SIZE_T pathSizeBytes = (dllPath.length() + 1) * sizeof(wchar_t);
LPVOID pRemotePath = VirtualAllocEx(hProcess, nullptr, pathSizeBytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!pRemotePath) {
ConsoleUI::PrintError("Allocating DLL path in game", GetLastError());
CloseHandle(hProcess);
return false;
}
ConsoleUI::SetStatusText("Copying DLL path into game");
if (!WriteProcessMemory(hProcess, pRemotePath, dllPath.c_str(), pathSizeBytes, nullptr)) {
ConsoleUI::PrintError("Copying DLL path into game", GetLastError());
VirtualFreeEx(hProcess, pRemotePath, 0, MEM_RELEASE);
CloseHandle(hProcess);
return false;
}
ConsoleUI::SetStatusText("Finding Windows DLL loader");
HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll");
LPTHREAD_START_ROUTINE pLoadLibraryW = (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "LoadLibraryW");
if (!pLoadLibraryW) {
ConsoleUI::PrintError("Finding Windows DLL loader", GetLastError());
VirtualFreeEx(hProcess, pRemotePath, 0, MEM_RELEASE);
CloseHandle(hProcess);
return false;
}
ConsoleUI::SetStatusText("Starting DLL loader in game");
HANDLE hThread = CreateRemoteThread(hProcess, nullptr, 0, pLoadLibraryW, pRemotePath, 0, nullptr);
if (!hThread) {
ConsoleUI::PrintError("Starting DLL loader in game", GetLastError());
VirtualFreeEx(hProcess, pRemotePath, 0, MEM_RELEASE);
CloseHandle(hProcess);
return false;
}
ConsoleUI::SetStatusText("Reading DLL loader result");
DWORD waitRes = WaitForSingleObject(hThread, 30000);
if (waitRes != WAIT_OBJECT_0) {
ConsoleUI::SetStatusText("Game did not finish loading the DLL.");
CloseHandle(hThread);
VirtualFreeEx(hProcess, pRemotePath, 0, MEM_RELEASE);
CloseHandle(hProcess);
return false;
}
DWORD dwExitCode = 0;
GetExitCodeThread(hThread, &dwExitCode);
CloseHandle(hThread);
VirtualFreeEx(hProcess, pRemotePath, 0, MEM_RELEASE);
CloseHandle(hProcess);
if (!ProcessUtil::WaitForModuleLoad(pid, L"SlinkyNative.dll", 5000)) {
ConsoleUI::SetStatusText("DLL not in game after load attempt.");
return false;
}
ConsoleUI::SetStatusText("Injected successfully");
return true;
}
bool Injector::MonitorStartup(DWORD pid, const std::wstring& logPath) {
HANDLE hProcess = OpenProcess(SYNCHRONIZE, FALSE, pid);
ConsoleUI::SetStatusText("Still loading...");
DWORD startTime = GetTickCount();
const DWORD timeoutMs = 30000;
while (GetTickCount() - startTime < timeoutMs) {
if (hProcess && WaitForSingleObject(hProcess, 0) == WAIT_OBJECT_0) {
ConsoleUI::SetStatusText("Game process closed before startup finished.");
CloseHandle(hProcess);
return false;
}
FILE* fp = nullptr;
if (_wfopen_s(&fp, logPath.c_str(), L"r, ccs=UTF-8") == 0 && fp) {
wchar_t line[1024];
while (fgetws(line, 1024, fp)) {
if (wcsstr(line, L"FINAL STATUS: RUNNING")) {
ConsoleUI::SetStatusText("Press Right Shift in Minecraft.");
fclose(fp);
if (hProcess) CloseHandle(hProcess);
return true;
} else if (wcsstr(line, L"FINAL STATUS: RELOADED")) {
ConsoleUI::SetStatusText("Slinky reloaded. Press Right Shift.");
fclose(fp);
if (hProcess) CloseHandle(hProcess);
return true;
} else if (wcsstr(line, L"FINAL STATUS: ALREADY_RUNNING")) {
ConsoleUI::SetStatusText("Already running. Unload from menu first.");
fclose(fp);
if (hProcess) CloseHandle(hProcess);
return false;
} else if (wcsstr(line, L"FINAL STATUS: FAILED")) {
ConsoleUI::SetStatusText("Slinky could not start.");
fclose(fp);
if (hProcess) CloseHandle(hProcess);
return false;
}
}
fclose(fp);
}
Sleep(150);
}
if (hProcess) CloseHandle(hProcess);
ConsoleUI::SetStatusText("DLL loaded but Slinky never confirmed startup.");
return false;
}
} // namespace Slinky
+80
View File
@@ -0,0 +1,80 @@
#include <windows.h>
#include "ConsoleUI.hpp"
#include "Injector.hpp"
#include "ProcessUtil.hpp"
#include <cstdio>
#include <vector>
using namespace Slinky;
int main() {
ConsoleUI::Initialize();
ConsoleUI::StartAnimation();
ConsoleUI::SetStatusText("Finding bundled DLL");
std::wstring dllPath;
std::wstring logPath;
if (!Injector::ExtractBundledDll(dllPath, logPath)) {
Sleep(2500);
ConsoleUI::StopAnimation();
ConsoleUI::Shutdown();
return 1;
}
ConsoleUI::SetStatusText("SCANNING");
DWORD startWait = GetTickCount();
const DWORD timeoutWait = 180000;
std::vector<TargetWindow> windows;
int dotCount = 0;
while (GetTickCount() - startWait < timeoutWait) {
windows = ProcessUtil::FindMinecraftWindows();
if (!windows.empty()) {
break;
}
const char* dots[] = { "", ".", "..", "..." };
char waitMsg[64];
sprintf_s(waitMsg, "Waiting for Minecraft%s", dots[dotCount % 4]);
ConsoleUI::SetStatusText(waitMsg);
dotCount++;
Sleep(500);
}
if (windows.empty()) {
ConsoleUI::SetStatusText("Minecraft not found after 3 minutes.");
Sleep(3000);
ConsoleUI::StopAnimation();
ConsoleUI::Shutdown();
return 1;
}
TargetWindow target = windows[0];
char foundMsg[256];
char titleUtf8[256] = { 0 };
WideCharToMultiByte(CP_UTF8, 0, target.title.c_str(), -1, titleUtf8, 256, nullptr, nullptr);
sprintf_s(foundMsg, "Found Minecraft %s", titleUtf8);
ConsoleUI::SetStatusText(foundMsg);
Sleep(500);
ConsoleUI::SetStatusText("INJECTING ...");
if (!Injector::InjectDll(target.pid, dllPath)) {
Sleep(3000);
ConsoleUI::StopAnimation();
ConsoleUI::Shutdown();
return 1;
}
bool success = Injector::MonitorStartup(target.pid, logPath);
Sleep(3000);
ConsoleUI::StopAnimation();
ConsoleUI::Shutdown();
return success ? 0 : 1;
}
+100
View File
@@ -0,0 +1,100 @@
#include "ProcessUtil.hpp"
#include <tlhelp32.h>
#include <algorithm>
namespace Slinky {
std::vector<DWORD> ProcessUtil::GetJavaProcessIds() {
std::vector<DWORD> pids;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap == INVALID_HANDLE_VALUE) return pids;
PROCESSENTRY32W pe;
pe.dwSize = sizeof(pe);
if (Process32FirstW(hSnap, &pe)) {
do {
if (_wcsicmp(pe.szExeFile, L"javaw.exe") == 0 ||
_wcsicmp(pe.szExeFile, L"java.exe") == 0)
{
pids.push_back(pe.th32ProcessID);
}
} while (Process32NextW(hSnap, &pe));
}
CloseHandle(hSnap);
return pids;
}
struct EnumData {
std::vector<DWORD> javaPids;
std::vector<TargetWindow> windows;
};
static BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) {
if (!IsWindowVisible(hWnd)) return TRUE;
if (GetWindowTextLengthW(hWnd) == 0) return TRUE;
DWORD pid = 0;
GetWindowThreadProcessId(hWnd, &pid);
EnumData* data = (EnumData*)lParam;
if (std::find(data->javaPids.begin(), data->javaPids.end(), pid) == data->javaPids.end()) {
return TRUE;
}
wchar_t titleBuf[512] = { 0 };
if (GetWindowTextW(hWnd, titleBuf, 512) > 0) {
TargetWindow tw;
tw.hWnd = hWnd;
tw.pid = pid;
tw.title = titleBuf;
data->windows.push_back(tw);
}
return TRUE;
}
std::vector<TargetWindow> ProcessUtil::FindMinecraftWindows() {
EnumData data;
data.javaPids = GetJavaProcessIds();
if (data.javaPids.empty()) return {};
EnumWindows(EnumWindowsProc, (LPARAM)&data);
return data.windows;
}
bool ProcessUtil::IsModuleLoaded(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);
bool found = false;
if (Module32FirstW(hSnap, &me)) {
do {
if (_wcsicmp(me.szModule, moduleName) == 0 ||
wcsstr(me.szExePath, moduleName) != nullptr)
{
found = true;
break;
}
} while (Module32NextW(hSnap, &me));
}
CloseHandle(hSnap);
return found;
}
bool ProcessUtil::WaitForModuleLoad(DWORD pid, const wchar_t* moduleName, DWORD timeoutMs) {
DWORD elapsed = 0;
while (elapsed < timeoutMs) {
if (IsModuleLoaded(pid, moduleName)) return true;
Sleep(50);
elapsed += 50;
}
return false;
}
} // namespace Slinky