DLL tarafında a0 sunucudan gelen paketi parseleyip sadece 512 byte 'ını yolluyoruz ki paket 515 byte gelir op code a0 00 02 olarak kuracağımız emulatör a0 00 02 yi kabul etmez o yüzden kodda traşladım ,
emulatör
iki kodda da 127.0.0.1 olarak ayarladım ben testlerimi ana makinada yaptığım için böyle siz x3 serveri ip sini verdiğiniz gibi açacaksınız normal oyunu farklı makinada açacaksınız emule ettiğim x3 ana makinada x3 olmadan açılan cliente bilgi gönderecek. kolay gelsin ,
knight online priv koxp, satılır dm xd
client x3 yok direk açılıyor :
C++:
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <iostream>
#include <cstdint>
#include "hook.h"
#include "memory.h"
#include "pointer.h"
#include "userRun.h"
#include "3d.h"
#include "inv.h"
#include "otopointer.h"
#include <thread>
#include "pipe.h"
#include "otoLogin.h"
#include "OTPGenerator.h"
#include <sstream>
#include <string>
#include <vector>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <optional>
#include <map>
#include <fstream>
#include <chrono>
#include <ctime>
#include "global.h"
#include "mobselect.h"
#include "logic.h"
#include "Functions.h"
#include "SendSkill.h"
#include <set>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
std::vector<BYTE> g_A0_Buffer;
std::chrono::steady_clock::time_point g_LastPacketTime;
std::mutex g_BufferMutex;
bool g_TimerActive = false;
void YazHataLogu(const std::string& mesaj) {
std::ofstream dosya("C:\\hata.txt", std::ios::app);
if (dosya.is_open()) {
time_t simdi = time(0);
char* dt = ctime(&simdi);
if (dt) dt[strlen(dt) - 1] = '\0';
dosya << "[" << dt << "] " << mesaj << std::endl;
dosya.close();
}
}
std::string PaketToHexString(BYTE* pData, int nSize) {
std::stringstream ss;
for (int i = 0; i < nSize; i++) {
ss << std::hex << std::uppercase << std::setw(2) << std::setfill('0') << (int)pData[i] << " ";
}
return ss.str();
}
//HOOK SEND
typedef int(__thiscall* CAPISocketSend)(DWORD* socket, BYTE* pData, int nSize);
CAPISocketSend oCAPISocketSend = nullptr;
BYTE g_lastPacket[256];
int g_lastPacketSize = 0;
bool g_gameStart = false;
bool g_otp = false;
BYTE g_Login[1024]; //tampon
int g_CapturedF3Size = 0;
bool g_LoginOK = false;
bool g_bulcanQuest = false;
int __fastcall HookedSendPacketMethod(DWORD* socket, void* Unknown, BYTE* pData, int nSize)
{
if (pData && nSize > 0 && pData[0] == 0xA0)
{
std::string hexStr = PaketToHexString(pData, nSize);
YazHataLogu("[LEGAL SEND] Size=" + std::to_string(nSize) + " | Data: " + hexStr);
printf("[LEGAL SEND] Size=%d | Data: ", nSize);
for (int i = 0; i < nSize; i++)
{
printf("%02X ", pData[i]);
}
printf("\n");
}
if (pData && nSize > 300 )
{
std::string hexStr = PaketToHexString(pData, nSize);
YazHataLogu("[LEGAL SEND] Size=" + std::to_string(nSize) + " | Data: " + hexStr);
printf("[LEGAL SEND] Size=%d | Data: ", nSize);
for (int i = 0; i < nSize; i++)
{
printf("%02X ", pData[i]);
}
printf("\n");
}
return oCAPISocketSend(socket, pData, nSize);
}
const uintptr_t HookSize = 5;
bool IsSendPacketHooked = false;
void HookSendPacketMethod() {
BYTE* src = reinterpret_cast<BYTE*>(KO_SND_FNC);
if (!src) {
return;
}
oCAPISocketSend = reinterpret_cast<CAPISocketSend>(
TrampHook32(reinterpret_cast<BYTE*>(KO_SND_FNC),
reinterpret_cast<BYTE*>(HookedSendPacketMethod),
HookSize));
if (!oCAPISocketSend) {
return;
}
IsSendPacketHooked = true;
}
//end of send hook
//X3 BYPASS
//RECV HOOK
DWORD KO_PTR_GameProcMain_orginalProcessPacketFuncAdr = 0x0;
DWORD KO_PTR_GameProcIntro_orginalProcessPacketFuncAdr = 0x0;
bool IsRecvPacketHooked = false;
typedef BYTE(__fastcall* tProcessPacket)(DWORD* pointer, void* Unknown, DWORD pDataPack, int& iOffset);
inline bool disableDeathAnimation = true;
std::atomic<bool> needSolve(false);
DWORD lastCaptchaRequestTime = 0;
// HOOK RECV PAKET
void SendToGameServer(BYTE* pBuf, int len) {
DWORD pktPtr = *(DWORD*)KO_PTR_PKT;
if (pktPtr == 0) return;
__asm {
MOV ECX, pktPtr // Oyunun Socket Nesnesi (this)
PUSH len // Boyut
PUSH pBuf // Veri
MOV EAX, KO_SND_FNC
CALL EAX // Oyunun orijinal Send fonksiyonu
}
}
BYTE originalBytes[5];
void HexLog(const char* label, BYTE* data, int size) {
printf("%s [%d bytes]: ", label, size);
for (int i = 0; i < size; i++) {
printf("%02X ", data[i]);
}
printf("\n");
}
void LogToConsole(const char* format, ...) {
char buffer[1024];
va_list args;
va_start(args, format);
vsprintf_s(buffer, format, args);
printf("%s\n", buffer);
OutputDebugStringA(buffer);
va_end(args);
}
// Global veya static kalsın
static SOCKET g_MasterSock = INVALID_SOCKET;
bool EnsureConnection() {
if (g_MasterSock != INVALID_SOCKET) return true;
WSADATA wsa; WSAStartup(MAKEWORD(2, 2), &wsa);
g_MasterSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (g_MasterSock == INVALID_SOCKET) return false;
int timeout = 5000;
setsockopt(g_MasterSock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8888);
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
if (connect(g_MasterSock, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
g_MasterSock = INVALID_SOCKET;
return false;
}
// HANDSHAKE GÖNDER
unsigned char hs[2] = { 0x31, 0x80 };
send(g_MasterSock, (char*)hs, 2, 0);
// CEVAP BEKLE
char dummy[10];
int r = recv(g_MasterSock, dummy, sizeof(dummy), 0);
if (r <= 0) {
YazHataLogu("[ERROR] Handshake cevabi gelmedi, soket kapatiliyor.");
closesocket(g_MasterSock);
g_MasterSock = INVALID_SOCKET;
return false;
}
YazHataLogu("[OK] Handshake basarili.");
return true;
}
std::mutex g_EmuLock;
int GetHBFromMaster(BYTE* pData, int pSize, BYTE* pOutBuffer, int& outSize) {
if (g_MasterSock == INVALID_SOCKET) {
WSADATA wsa; WSAStartup(MAKEWORD(2, 2), &wsa);
g_MasterSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
u_long mode = 1;
ioctlsocket(g_MasterSock, FIONBIO, &mode);
sockaddr_in addr = { AF_INET, htons(8888) };
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
connect(g_MasterSock, (sockaddr*)&addr, sizeof(addr));
}
// 2. Paketi hazırla
BYTE sBuf[1024];
sBuf[0] = (pSize >> 24) & 0xFF; sBuf[1] = (pSize >> 16) & 0xFF;
sBuf[2] = (pSize >> 8) & 0xFF; sBuf[3] = pSize & 0xFF;
memcpy(&sBuf[4], pData, pSize);
send(g_MasterSock, (char*)sBuf, pSize + 4, 0);
return 2;
}
void X3_WorkerThread(BYTE* data, int len) {
BYTE outBuf[515];
int outSize = 0;
int result = GetHBFromMaster(data, len, outBuf, outSize);
if (result == 1 && outSize > 0) {
YazHataLogu("[SUCCESS] Emu imzayi uretti, SUNUCUYA BASILIYOR.");
SendToGameServer(outBuf, outSize);
}
else {
YazHataLogu("[INFO] Emu su an cevap uretmedi (Paket yutuldu).");
}
}
std::string ToHexString(BYTE* data, int size) {
std::stringstream ss;
ss << std::hex << std::setfill('0');
for (int i = 0; i < size; ++i) {
ss << std::setw(2) << static_cast<int>(data[i]) << " ";
}
return ss.str();
}
BYTE __fastcall HookedProcessPacket(DWORD* pointer, void* Unknown, DWORD pDataPack, int& iOffset) {
BYTE* pData = *(BYTE**)(pDataPack + 0x8);
int pSize = *(int*)(pDataPack + 0x4);
if (pData != nullptr && pSize >= 515 && pData[0] == 0xA0) {
std::thread([=]() {
BYTE temp[515];
memcpy(temp, pData, 515);
X3_WorkerThread(temp, 515);
}).detach();
}
DWORD jumpBack = KO_PTR_GameProcMain_orginalProcessPacketFuncAdr + 5;
__asm {
mov ecx, pointer
mov edx, Unknown
push iOffset
push pDataPack
jmp jumpBack
}
}
//end of recv
void HookProcessPacket() {
if (IsRecvPacketHooked) return;
DWORD checkInstance = *(DWORD*)0x10F6094;
if (checkInstance == 0) {
std::cout << "[WAIT] Oyun henuz hazir degil, bekleniyor..." << std::endl;
return;
}
DWORD targetFunc = 0x00847170;
KO_PTR_GameProcMain_orginalProcessPacketFuncAdr = targetFunc;
DWORD newValue = (DWORD)&HookedProcessPacket;
BYTE jmp[5] = { 0xE9, 0x00, 0x00, 0x00, 0x00 };
DWORD relativeAddr = newValue - (targetFunc + 5);
memcpy(&jmp[1], &relativeAddr, 4);
DWORD oldProtect;
if (VirtualProtect((LPVOID)targetFunc, 5, PAGE_EXECUTE_READWRITE, &oldProtect)) {
memcpy(originalBytes, (LPVOID)targetFunc, 5);
// Hooku yerleştir
memcpy((LPVOID)targetFunc, jmp, 5);
VirtualProtect((LPVOID)targetFunc, 5, oldProtect, &oldProtect);
IsRecvPacketHooked = true;
std::cout << "[SUCCESS] Hook Aktif: 0x" << std::hex << targetFunc << std::endl;
}
}
emulatör
C++:
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
typedef int(__stdcall* _XignCode_probe_t)(void* pContext, BYTE* pInput, BYTE* pOutput, unsigned int* pOutSz, unsigned int reserved);
void* g_X3Context = nullptr;
_XignCode_probe_t _XignCode_Feed = nullptr;
_XignCode_probe_t _XignCode_Prepare = nullptr;
_XignCode_probe_t _XignCode_Pull = nullptr;
int main() {
printf("--- X3 EMU: FINAL FIXED VERSION ---\n");
HMODULE x3Mod = LoadLibraryA("C:\\NTTGame\\KnightOnlineEn\\XIGNCODE\\x3.xem");
auto dispatch = (int(__stdcall*)(void**, int))GetProcAddress(x3Mod, (LPCSTR)1);
dispatch(&g_X3Context, 1);
((bool(__stdcall*)(const wchar_t*, const wchar_t*, int))g_X3Context)(L"gA1cjrxctNry", L"C:\\NTTGame\\KnightOnlineEn\\XIGNCODE", 0);
void* p;
dispatch(&p, 5); _XignCode_Feed = (_XignCode_probe_t)p;
dispatch(&p, 4); _XignCode_Prepare = (_XignCode_probe_t)p;
dispatch(&p, 2); _XignCode_Pull = (_XignCode_probe_t)p;
dispatch(&p, 3); ((bool(__stdcall*)())p)();
WSADATA wsa; WSAStartup(MAKEWORD(2, 2), &wsa);
SOCKET listenSock = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in addr = { AF_INET, htons(8888), INADDR_ANY };
bind(listenSock, (sockaddr*)&addr, sizeof(addr));
listen(listenSock, 5);
printf("[OK] Emu hazir. Bekleniyor...\n");
__declspec(align(16)) BYTE alignedIn[8192];
__declspec(align(16)) BYTE dummyOut[8192];
while (true) {
SOCKET gameSock = accept(listenSock, NULL, NULL);
if (gameSock == INVALID_SOCKET) continue;
printf("[CONN] Baglanti geldi.\n");
while (true) {
unsigned char buffer[16384];
int bytes = recv(gameSock, (char*)buffer, sizeof(buffer), 0);
if (bytes <= 0) break;
if (bytes == 2 && buffer[0] == 0x31) continue;
for (int i = 0; i + 519 <= bytes; i += 519) {
memcpy(alignedIn, &buffer[i + 4], 515);
unsigned int outSz = 4096;
_XignCode_Feed(g_X3Context, alignedIn, dummyOut, &outSz, 0);
outSz = 4096;
_XignCode_Prepare(g_X3Context, alignedIn, dummyOut, &outSz, 0);
BYTE pullBuf[1024];
unsigned int pullSz = 1024;
int res = _XignCode_Pull(g_X3Context, alignedIn, pullBuf, &pullSz, 0);
if (res == 0 && pullBuf[0] != 0) {
printf("[SUCCESS] IMZA URETILDI!\n");
}
else {
printf("[INFO] Beslendi. (Res: %d)\n", res);
}
}
}
}
return 0;
}
iki kodda da 127.0.0.1 olarak ayarladım ben testlerimi ana makinada yaptığım için böyle siz x3 serveri ip sini verdiğiniz gibi açacaksınız normal oyunu farklı makinada açacaksınız emule ettiğim x3 ana makinada x3 olmadan açılan cliente bilgi gönderecek. kolay gelsin ,
knight online priv koxp, satılır dm xd
client x3 yok direk açılıyor :
Linkleri görebilmek için kayıt olmanız gerekmektedir
Son düzenleme: