Skip to content

Instantly share code, notes, and snippets.

@notmarek
Created July 19, 2024 18:38
Show Gist options
  • Save notmarek/c14b100cc412711c89bb61812b9e30ad to your computer and use it in GitHub Desktop.
Save notmarek/c14b100cc412711c89bb61812b9e30ad to your computer and use it in GitHub Desktop.
#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, &current, 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