Code:
#include <windows.h>
#include <tlhelp32.h>
#include <iostream>
#include <vector>
#include <string>
#include <thread>
#include <chrono>
#include <winternl.h>
// --- Manual import for NtQueryInformationThread ---
typedef NTSTATUS (NTAPI *pNtQueryInformationThread)(
HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG
);
// --- Config ---
const std::string CABAL_PATH = "D:\\Game\\CABAL Online (SEA)\\Bin\\x64\\CabalMain.exe";
const std::string CABAL_PARAM = "husky";
const std::vector<std::string> TARGET_PROCESSES = {"xcoronahost.xem", "xxd-0.xem"};
const std::string TARGET_MODULE = "xcorona_x64.xem";
const uintptr_t TARGET_OFFSET = 0x18d3c; // Offset for thread start
// --- Helper: Launch CabalMain.exe with husky parameter ---
bool LaunchCabal(PROCESS_INFORMATION& pi) {
STARTUPINFOA si = { sizeof(si) };
std::string cmd = "\"" + CABAL_PATH + "\" " + CABAL_PARAM;
if (!CreateProcessA(
NULL, &cmd[0], NULL, NULL, FALSE,
0, NULL, NULL, &si, &pi
)) {
std::cerr << "Failed to launch CabalMain.exe\n";
return false;
}
return true;
}
// --- Helper: Get module base address in remote process ---
uintptr_t GetRemoteModuleBase(DWORD pid, const std::string& moduleName) {
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (hSnap == INVALID_HANDLE_VALUE) return 0;
MODULEENTRY32 me = { sizeof(me) };
uintptr_t base = 0;
if (Module32First(hSnap, &me)) {
do {
if (_stricmp(me.szModule, moduleName.c_str()) == 0) {
base = (uintptr_t)me.modBaseAddr;
break;
}
} while (Module32Next(hSnap, &me));
}
CloseHandle(hSnap);
return base;
}
// --- Helper: Get thread start address ---
uintptr_t GetThreadStartAddress(HANDLE hThread) {
static pNtQueryInformationThread NtQueryInformationThread =
(pNtQueryInformationThread)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryInformationThread");
if (!NtQueryInformationThread) return 0;
uintptr_t startAddr = 0;
NTSTATUS status = NtQueryInformationThread(
hThread, (THREADINFOCLASS)9, // ThreadQuerySetWin32StartAddress
&startAddr, sizeof(startAddr), NULL
);
if (status != 0) return 0;
return startAddr;
}
// --- Helper: Find all TIDs in process whose start address is module_base + offset ---
std::vector<DWORD> FindTargetTIDs(DWORD pid, uintptr_t offset) {
std::vector<DWORD> tids;
uintptr_t base = GetRemoteModuleBase(pid, TARGET_MODULE);
if (!base) return tids;
uintptr_t targetStart = base + offset;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hSnap == INVALID_HANDLE_VALUE) return tids;
THREADENTRY32 te = { sizeof(te) };
if (Thread32First(hSnap, &te)) {
do {
if (te.th32OwnerProcessID == pid) {
HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION | THREAD_TERMINATE, FALSE, te.th32ThreadID);
if (hThread) {
uintptr_t startAddr = GetThreadStartAddress(hThread);
if (startAddr == targetStart) {
tids.push_back(te.th32ThreadID);
}
CloseHandle(hThread);
}
}
} while (Thread32Next(hSnap, &te));
}
CloseHandle(hSnap);
return tids;
}
// --- Helper: Suspend/Resume process ---
bool SuspendProcess(DWORD pid) {
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hSnap == INVALID_HANDLE_VALUE) return false;
THREADENTRY32 te = { sizeof(te) };
bool ok = false;
if (Thread32First(hSnap, &te)) {
do {
if (te.th32OwnerProcessID == pid) {
HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID);
if (hThread) {
SuspendThread(hThread);
CloseHandle(hThread);
ok = true;
}
}
} while (Thread32Next(hSnap, &te));
}
CloseHandle(hSnap);
return ok;
}
bool ResumeProcess(DWORD pid) {
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hSnap == INVALID_HANDLE_VALUE) return false;
THREADENTRY32 te = { sizeof(te) };
bool ok = false;
if (Thread32First(hSnap, &te)) {
do {
if (te.th32OwnerProcessID == pid) {
HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID);
if (hThread) {
ResumeThread(hThread);
CloseHandle(hThread);
ok = true;
}
}
} while (Thread32Next(hSnap, &te));
}
CloseHandle(hSnap);
return ok;
}
// --- Helper: Terminate thread by TID ---
bool TerminateThreadById(DWORD tid) {
HANDLE hThread = OpenThread(THREAD_TERMINATE, FALSE, tid);
if (!hThread) return false;
BOOL result = TerminateThread(hThread, 0);
CloseHandle(hThread);
return result;
}
// --- Helper: Terminate process by name ---
bool TerminateProcessByName(const std::string& name) {
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap == INVALID_HANDLE_VALUE) return false;
PROCESSENTRY32 pe = { sizeof(pe) };
bool ok = false;
if (Process32First(hSnap, &pe)) {
do {
if (_stricmp(pe.szExeFile, name.c_str()) == 0) {
HANDLE hProc = OpenProcess(PROCESS_TERMINATE, FALSE, pe.th32ProcessID);
if (hProc) {
TerminateProcess(hProc, 0);
CloseHandle(hProc);
ok = true;
}
}
} while (Process32Next(hSnap, &pe));
}
CloseHandle(hSnap);
return ok;
}
// --- Helper: Get module handle in remote process by name ---
HMODULE GetRemoteModuleHandle(DWORD pid, const std::string& moduleName) {
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (hSnap == INVALID_HANDLE_VALUE) return NULL;
MODULEENTRY32 me = { sizeof(me) };
HMODULE hMod = NULL;
if (Module32First(hSnap, &me)) {
do {
if (_stricmp(me.szModule, moduleName.c_str()) == 0) {
hMod = me.hModule;
break;
}
} while (Module32Next(hSnap, &me));
}
CloseHandle(hSnap);
return hMod;
}
// --- Helper: Unload module from remote process ---
bool UnloadModule(DWORD pid, const std::string& moduleName) {
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (!hProcess) {
std::cerr << "OpenProcess failed\n";
return false;
}
HMODULE hMod = GetRemoteModuleHandle(pid, moduleName);
if (!hMod) {
std::cerr << "Module not found in process\n";
CloseHandle(hProcess);
return false;
}
LPTHREAD_START_ROUTINE pFreeLibrary = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandleA("kernel32.dll"), "FreeLibrary");
if (!pFreeLibrary) {
std::cerr << "GetProcAddress(FreeLibrary) failed\n";
CloseHandle(hProcess);
return false;
}
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, pFreeLibrary, hMod, 0, NULL);
if (!hThread) {
std::cerr << "CreateRemoteThread failed\n";
CloseHandle(hProcess);
return false;
}
WaitForSingleObject(hThread, 5000);
CloseHandle(hThread);
CloseHandle(hProcess);
return true;
}
// --- Helper: Verification (stub) ---
bool VerifyAll() {
// Implement verification logic as needed.
return true;
}
int main() {
while (true) {
std::cout << "Launching CabalMain.exe...\n";
PROCESS_INFORMATION pi;
if (!LaunchCabal(pi)) return 1;
// Wait 5 seconds before suspending and checking threads
std::cout << "Waiting 5 seconds for CabalMain.exe to initialize...\n";
std::this_thread::sleep_for(std::chrono::seconds(5));
// Check for the threads to terminate by start address
std::vector<DWORD> tids = FindTargetTIDs(pi.dwProcessId, TARGET_OFFSET);
if (tids.empty()) {
std::cerr << "Target threads not found, terminating process and retrying...\n";
TerminateProcess(pi.hProcess, 0);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
continue;
}
std::cout << "Suspending CabalMain.exe...\n";
SuspendProcess(pi.dwProcessId);
std::cout << "Terminating target threads...\n";
for (DWORD tid : tids) {
if (!TerminateThreadById(tid)) {
std::cerr << "Failed to terminate thread " << tid << "\n";
}
}
std::cout << "Resuming CabalMain.exe...\n";
ResumeProcess(pi.dwProcessId);
std::cout << "Terminating target processes...\n";
for (const auto& proc : TARGET_PROCESSES) {
TerminateProcessByName(proc);
}
std::cout << "Unloading module...\n";
if (!UnloadModule(pi.dwProcessId, TARGET_MODULE)) {
std::cerr << "Failed to unload module: " << TARGET_MODULE << "\n";
}
std::cout << "Verifying steps...\n";
if (VerifyAll()) {
std::cout << "\nSUCCESS: All steps completed.\n";
break;
} else {
std::cerr << "Verification failed, retrying...\n";
TerminateProcess(pi.hProcess, 0);
}
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
std::this_thread::sleep_for(std::chrono::seconds(2));
}
std::cout << "Press Enter to exit.\n";
std::cin.get();
return 0;
}
Quote:
Path
D:\Game\CABAL Online (SEA)\Bin\x64\CabalMain.exe
Thread to terminate in CabalMain.exe
xcorona_x64.xem+0x18d3c <-terminate thread from CabalMain.exe
xcorona_x64.xem+0x18d3c <-terminate thread from CabalMain.exe
PROCESS to terminate
xcoronahost.xem
xxd-0.xem
MODULE Base address Description to unload
xcorona_x64.xem, 0x7ffbee370000, XIGNCODE3 SYSTEM
Memory
0x7ffbee370000 D:\Game\CABAL Online (SEA)\XIGNCODE\xcorona_x64.xem
0x7ffbee371000 D:\Game\CABAL Online (SEA)\XIGNCODE\xcorona_x64.xem
0x7ffbee39a000 D:\Game\CABAL Online (SEA)\XIGNCODE\xcorona_x64.xem
0x7ffbee3a7000 D:\Game\CABAL Online (SEA)\XIGNCODE\xcorona_x64.xem
0x7ffbee3a9000 D:\Game\CABAL Online (SEA)\XIGNCODE\xcorona_x64.xem
0x7ffbee99d000 D:\Game\CABAL Online (SEA)\XIGNCODE\xcorona_x64.xem
Handels
xcoronahost.xem
using husky parameter
launch CabalMain.exe
wait until The two threads i gave loads
then once it load
suspend the CabalMain.exe process first
then while CabalMain.exe is in suspended state
Terminate the two Thread i provided completely from CabalMain.exe
xcorona_x64.xem+0x18d3c
xcorona_x64.xem+0x18d3c
after terminating the two threads from CabalMain.exe
resume the Process of CabalMain.exe
then terminate these two process running loop
xcoronahost.xem
xxd-0.xem
once its all completely terminated
unload the MODULE in CabalMain.exe
xcorona_x64.xem
then verify if all the steps is complete if not
terminate then loop
if sucess
dont close the terminal console and give a message success
but when i do it manually it works, here i did it manually
xigncode not running anymore and cabal is ok... enlighten me please hahahah






