Created
July 19, 2024 18:38
-
-
Save notmarek/c14b100cc412711c89bb61812b9e30ad to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define WIN32_LEAN_AND_MEAN | |
#include <Windows.h> | |
#include <cstdint> | |
#include <filesystem> | |
#include <format> | |
#include "MinHook.h" | |
#define ORIG(fn) static_cast<decltype(&(fn))>(o_##fn) | |
HANDLE _out; | |
#pragma comment(lib, "ntdll.lib") | |
uintptr_t scan(const char *module, const char *pattern) { | |
static auto pattern_to_byte = [](const char *pattern) { | |
auto bytes = std::vector<int>{}; | |
const auto start = const_cast<char *>(pattern); | |
const auto end = const_cast<char *>(pattern) + strlen(pattern); | |
for (auto current = start; current < end; ++current) { | |
if (*current == '?') { | |
++current; | |
if (*current == '?') | |
++current; | |
bytes.push_back(-1); | |
} else { | |
bytes.push_back(strtoul(current, ¤t, 16)); | |
} | |
} | |
return bytes; | |
}; | |
const auto mod = GetModuleHandleA(module); | |
if (!mod) | |
return 0; | |
const auto dos_header = reinterpret_cast<PIMAGE_DOS_HEADER>(mod); | |
const auto nt_headers = reinterpret_cast<PIMAGE_NT_HEADERS>(reinterpret_cast<std::uint8_t *>(mod) + | |
dos_header->e_lfanew); | |
const auto size_of_image = nt_headers->OptionalHeader.SizeOfImage; | |
const auto pattern_bytes = pattern_to_byte(pattern); | |
auto scan_bytes = reinterpret_cast<std::uint8_t *>(mod); | |
const auto s = pattern_bytes.size(); | |
const auto d = pattern_bytes.data(); | |
for (auto i = 0ul; i < size_of_image - s; ++i) { | |
bool found = true; | |
for (auto j = 0ul; j < s; ++j) { | |
if (scan_bytes[i + j] != d[j] && d[j] != -1) { | |
found = false; | |
break; | |
} | |
} | |
if (found) { | |
return reinterpret_cast<uintptr_t>(&scan_bytes[i]); | |
} | |
} | |
return 0; | |
} | |
CONSOLE_SCREEN_BUFFER_INFOEX info; | |
bool Printf(const char *name, const char *fmt, va_list va) { | |
if (!_out) | |
return false; | |
SetConsoleTextAttribute(_out, 0x00df); | |
WriteConsoleA(_out, "[", 1, nullptr, nullptr); | |
WriteConsoleA(_out, name, strlen(name), nullptr, nullptr); | |
WriteConsoleA(_out, "]", 1, nullptr, nullptr); | |
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0); | |
SetConsoleTextAttribute(_out, 15); | |
WriteConsoleA(_out, " ", 1, nullptr, nullptr); | |
char buf[8192]; | |
const size_t size = vsprintf_s(buf, 8192, fmt, va); | |
return !!WriteConsoleA(_out, &buf, static_cast<DWORD>(strlen(buf)), nullptr, nullptr); | |
} | |
bool LOG(const char *fmt, ...) { | |
va_list va; | |
va_start(va, fmt); | |
const bool result = Printf("CrackPipe:Info", fmt, va); | |
va_end(va); | |
return result; | |
} | |
PVOID o_inject; | |
int64_t *inject(HANDLE target, const char *path) { | |
char filename[260]; | |
HMODULE hm = nullptr; | |
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | | |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, | |
reinterpret_cast<LPCSTR>(&inject), &hm); // Find self | |
GetModuleFileNameA(hm, filename, 260); | |
LOG("Injecting along with Minty.\n"); | |
ORIG(inject)(target, path); | |
Sleep(200); | |
return ORIG(inject)(target, filename); | |
} | |
class someKindaString { | |
public: | |
char data[16]; | |
size_t length; | |
size_t extra; | |
void operator=(const std::string& obj) | |
{ | |
memcpy(*(char **) this->data, obj.c_str(), obj.length() + 1); | |
this->length = obj.length(); | |
} | |
char *c_str() { | |
if ((extra ^ 0x0F) == 0) { | |
return (char *) data; | |
} | |
return *reinterpret_cast<char **>(data); | |
} | |
}; | |
struct subscriptions { | |
someKindaString name; | |
someKindaString expiry; | |
}; | |
struct channelMessage { | |
someKindaString author; | |
someKindaString message; | |
someKindaString timestamp; | |
}; | |
struct appdata { | |
someKindaString numUsers; | |
someKindaString numOnlineUsers; | |
someKindaString numKeys; | |
someKindaString appdataversion; | |
someKindaString customerPanelLink; | |
}; | |
struct response { | |
std::vector<channelMessage> channelData; | |
uint8_t success; | |
someKindaString message; | |
}; | |
struct user { | |
someKindaString username; | |
someKindaString ip; | |
someKindaString hwid; | |
someKindaString createdate; | |
someKindaString lastlogin; | |
std::vector<subscriptions> subs; | |
}; | |
struct api { | |
someKindaString name; | |
someKindaString ownerid; | |
someKindaString secret; | |
someKindaString version; | |
someKindaString url; | |
user user; | |
appdata appdata; | |
response response; | |
someKindaString sessionId; | |
someKindaString sessionSecret; | |
}; | |
PVOID o_check_license; | |
int64_t check_license() { | |
LOG("Skipping license check and returning 69.\n"); | |
return 69; | |
} | |
PVOID o_keyauth_get; | |
char** keyauth_get(char** out, void** post_data, void** url) | |
{ | |
LOG("POST data: %s\n", static_cast<char*>(*post_data)); | |
LOG("URL: %s\n", static_cast<char*>(*url)); | |
const auto result = ORIG(keyauth_get)(out, post_data, url); | |
LOG("Response: %s\n", *result); | |
return result; | |
} | |
PVOID o_ka_init; | |
void ka_init(api* arg1) { | |
api* api = reinterpret_cast<struct api*>((uint64_t)arg1 + 0x8d0); | |
LOG("Name: %s, Owner: %s, Secret: %s, Version: %s, URL: %p\n", api->name.c_str(), api->ownerid.c_str(), api->secret.c_str(), | |
api->version.c_str(), api->url.c_str()); | |
if (api->url.c_str() != nullptr) { | |
#ifdef LOCAL | |
const std::string new_url("http://127.0.0.1/api/1.2/"); | |
#else | |
const std::string new_url("https://crackpipe.notmarek.com/api/1.2/"); | |
#endif | |
api->url = new_url; | |
} | |
ORIG(ka_init)(arg1); | |
} | |
PVOID o_ka_constructor; | |
int64_t *ka_constructor(api *arg1, someKindaString name, someKindaString ownerid, someKindaString secret, | |
someKindaString version, someKindaString url) { | |
LOG("Name: %s, Owner: %s, Secret: %s, Version: %s, URL: %s\n", name.c_str(), ownerid.c_str(), secret.c_str(), | |
version.c_str(), url.c_str()); | |
#ifdef LOCAL | |
const std::string new_url("http://127.0.0.1/api/1.2/"); | |
#else | |
const std::string new_url("https://crackpipe.notmarek.com/api/1.2/"); | |
#endif | |
url = new_url; | |
auto result = ORIG(ka_constructor)(arg1, name, ownerid, secret, version, url); | |
return result; | |
} | |
#define KACTR "41 54 41 56 41 57 48 83 EC ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 44 24 ? 49 8B F1" | |
#define SCAN_WHILE_LIMIT_OR_FOUND(module, pat) \ | |
void *found = (void *) scan(module, pat); \ | |
while (found == nullptr && i < LIMIT) { \ | |
found = (void *) scan(module, pat); \ | |
Sleep(500); \ | |
i++; \ | |
} | |
#define HOOK_IF_FOUND(module, name, pat, func) \ | |
if (GetModuleHandleA(module) != nullptr) { \ | |
LOG("Scanning for %s inside %s\n", name, module); \ | |
SCAN_WHILE_LIMIT_OR_FOUND(module, pat) \ | |
if (found != nullptr) { \ | |
LOG("Found %s @ %p\n", name, found); \ | |
MH_STATUS result = MH_CreateHook((LPVOID) found, (void *) func, (LPVOID *) &o_##func); \ | |
LOG("MinHook result: %s\n", MH_StatusToString(result)); \ | |
MH_EnableHook((LPVOID) found); \ | |
} \ | |
i = 0; \ | |
} | |
void start() { | |
#define LIMIT 3 | |
int i = 0; | |
AllocConsole(); | |
MH_Initialize(); | |
_out = GetStdHandle(STD_OUTPUT_HANDLE); | |
HOOK_IF_FOUND(nullptr, "Inject", "40 53 55 56 57 41 56 48 83 EC ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 44 24 ? 48 8B E9", inject) | |
info.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX); | |
GetConsoleScreenBufferInfoEx(_out, &info); | |
info.ColorTable[0xd] = RGB(255, 0, 105); | |
SetConsoleScreenBufferInfoEx(_out, &info); | |
const auto ntdll = GetModuleHandle(L"ntdll.dll"); | |
uint8_t callcode = ((uint8_t *) GetProcAddress(ntdll, "NtQuerySection"))[4] - 1; | |
uint8_t restore[] = {0x4C, 0x8B, 0xD1, 0xB8, callcode}; | |
volatile auto ntProtectVirtualMemory = (uint8_t *) GetProcAddress(ntdll, "NtProtectVirtualMemory"); | |
while (true) { | |
if (ntProtectVirtualMemory[0] != 0x4C) { | |
DWORD oldProtect; | |
VirtualProtect((LPVOID) ntProtectVirtualMemory, sizeof(restore), PAGE_EXECUTE_READWRITE, &oldProtect); | |
memcpy(ntProtectVirtualMemory, restore, sizeof(restore)); | |
VirtualProtect((LPVOID) ntProtectVirtualMemory, sizeof(restore), oldProtect, nullptr); | |
break; | |
} | |
} | |
#define DEBUG | |
#ifdef DEBUG | |
HOOK_IF_FOUND("MintyZZZ.dll", "Keyauth Init", "48 89 5C 24 ?? 55 48 8D AC 24 F0 FE FF FF", ka_init); // for dumping secrets | |
HOOK_IF_FOUND("MintyZZZ.dll", "Keyauth get", "48 89 5C 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 8D 6C 24 E0", keyauth_get) | |
#else | |
HOOK_IF_FOUND("MintyZZZ.dll", "ZZZ check license", "41 50 49 B8 87 75 82 25 D2 6D 26 72", check_license) | |
else HOOK_IF_FOUND("Revamp.dll", "KeyAuth constructor", KACTR, ka_constructor) | |
else HOOK_IF_FOUND("MintyWW.dll", "KeyAuth constructor", KACTR, ka_constructor) | |
#endif | |
else LOG("Damn nigga no auth found."); | |
} | |
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { | |
if (fdwReason == DLL_PROCESS_ATTACH) { | |
const auto thread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE) start, nullptr, 0, nullptr); | |
DisableThreadLibraryCalls(hinstDLL); | |
if (thread) { | |
CloseHandle(thread); | |
} | |
} | |
return true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment