Proteção contra Ring Bug e algumas correções para 97d
Proteção contra Ring Bug (Reviver após morte com drop de ring):
Ring.h:
Código:
#pragma once
namespace Network
{
struct PMSG_ITEMTHROW
{
PBMSG_HEAD h;
unsigned char X;
unsigned char Y;
unsigned char Pos;
};
struct PMSG_INVENTORYITEMMOVE
{
PBMSG_HEAD h;
unsigned char Flag;
unsigned char Num;
unsigned char Info[4];
unsigned char FlagEx;
unsigned char Target;
};
class Ring
{
public:
static int Drop(PMSG_ITEMTHROW* lpMsg, DWORD dwIndex, int szDrop);
static void Move(PMSG_INVENTORYITEMMOVE* lpMsg, DWORD dwIndex);
};
}
Ring.cpp:
Código:
#include "Ring.h"
namespace Network
{
int Ring::Drop(PMSG_ITEMTHROW* lpMsg, DWORD dwIndex, int szDrop)
{
if(Object[dwIndex].Type == 1 && Object[dwIndex].Live == 0)
{
lpMsg->Pos = 80;
}
return ServerItemDrop(lpMsg, dwIndex, szDrop);
}
void Ring::Move(PMSG_INVENTORYITEMMOVE* lpMsg, DWORD dwIndex)
{
if(Object[dwIndex].Type == 1 && Object[dwIndex].Live == 0)
{
BYTE szItem[4];
ServerItemMoveResult(dwIndex, (-1), 0, szItem);
return;
}
ServerItemMove(lpMsg, dwIndex);
}
}
Hook:
Código:
Hook((DWORD)&Network::Ring::Drop, 0x4010FF);
Hook((DWORD)&Network::Ring::Move, 0x40272F);
Defines:
Código:
#define ServerItemDrop ((int(*)(Network::PMSG_ITEMTHROW*, DWORD, int)) 0x4191B0)
#define ServerItemMove ((void(*)(Network::PMSG_INVENTORYITEMMOVE*, DWORD)) 0x41A6F0)
#define ServerItemMoveResult ((void(*)(DWORD, BYTE, BYTE, LPBYTE)) 0x41A670)
Correção ShadowBug (Server-side):
Shadow.h:
Código:
#pragma once
namespace Network
{
class Shadow
{
public:
static int Bless(OBJECTSTRUCT* lpObj, int szSource, int szTarget);
static int Soul(OBJECTSTRUCT* lpObj, int szSource, int szTarget);
static int Life(OBJECTSTRUCT* lpObj, int szSource, int szTarget);
};
}
Shadow.cpp:
Código:
#include "Shadow.h"
namespace Network
{
int Shadow::Bless(OBJECTSTRUCT* lpObj, int szSource, int szTarget)
{
if(lpObj->pInventory[szTarget].m_Type >= ITEMGET(12, 7))
{
return 0;
}
return ServerItemBlessUp(lpObj, szSource, szTarget);
}
int Shadow::Soul(OBJECTSTRUCT* lpObj, int szSource, int szTarget)
{
if(lpObj->pInventory[szTarget].m_Type >= ITEMGET(12, 7))
{
return 0;
}
return ServerItemSoulUp(lpObj, szSource, szTarget);
}
int Shadow::Life(OBJECTSTRUCT* lpObj, int szSource, int szTarget)
{
if(lpObj->pInventory[szTarget].m_Type >= ITEMGET(12, 7))
{
return 0;
}
return ServerItemLifeUp(lpObj, szSource, szTarget);
}
}
Hook:
Código:
Hook((DWORD)&Network::Shadow::Bless, 0x4016E0);
Hook((DWORD)&Network::Shadow::Soul, 0x4015A0);
Hook((DWORD)&Network::Shadow::Life, 0x401FAF);
Defines:
Código:
#define ServerItemBlessUp ((int(*)(Network::OBJECTSTRUCT*, int, int)) 0x479A60)
#define ServerItemSoulUp ((int(*)(Network::OBJECTSTRUCT*, int, int)) 0x479E50)
#define ServerItemLifeUp ((int(*)(Network::OBJECTSTRUCT*, int, int)) 0x47A490)
Outras correções:
Pk Bug:
Código:
*(BYTE*)(0x45508A) = 0x90;
*(BYTE*)(0x45508B) = 0x90;
*(BYTE*)(0x45508C) = 0x90;
*(BYTE*)(0x45508D) = 0x90;
*(BYTE*)(0x45508E) = 0x90;
*(BYTE*)(0x4550AF) = 0x90;
*(BYTE*)(0x4550B0) = 0x90;
*(BYTE*)(0x4550B1) = 0x90;
*(BYTE*)(0x4550B2) = 0x90;
*(BYTE*)(0x4550B3) = 0x90;
*(BYTE*)(0x4642A4) = 0x9C;
*(BYTE*)(0x4642B0) = 0x9C;
*(BYTE*)(0x4643C0) = 0x9C;
*(BYTE*)(0x4643CC) = 0x9C;
Potion Bug:
Código:
*(BYTE*)(0x4119FE) = 0x90;
*(BYTE*)(0x4119FF) = 0x90;
*(BYTE*)(0x411A00) = 0x90;
*(BYTE*)(0x411A01) = 0x90;
*(BYTE*)(0x411A02) = 0x90;
*(BYTE*)(0x411A03) = 0x90;
*(BYTE*)(0x411A04) = 0x90;
*(BYTE*)(0x411A05) = 0x90;
*(BYTE*)(0x411A06) = 0x90;
*(BYTE*)(0x411A07) = 0x90;
*(BYTE*)(0x45BD58) = 0x90;
*(BYTE*)(0x45BD59) = 0x90;
*(BYTE*)(0x45BD5A) = 0x90;
*(BYTE*)(0x45BD5B) = 0x90;
*(BYTE*)(0x45BD5C) = 0x90;
*(BYTE*)(0x45BD5D) = 0x90;
*(BYTE*)(0x45BE0E) = 0x90;
*(BYTE*)(0x45BE0F) = 0x90;
*(BYTE*)(0x45BE10) = 0x90;
*(BYTE*)(0x45BE11) = 0x90;
*(BYTE*)(0x45BE12) = 0x90;
*(BYTE*)(0x45BE13) = 0x90;
*(BYTE*)(0x45BE14) = 0x90;
Checagem de Personal ID:
Código:
*(BYTE*)(0x417781) = 0xEB;
*(BYTE*)(0x420D2A) = 0x90;
*(BYTE*)(0x420D2B) = 0x90;
*(BYTE*)(0x420DEB) = 0x90;
*(BYTE*)(0x420DEC) = 0x90;
Party Zen Bug:
Código:
BYTE btParty[57] = {0x8B, 0x4D, 0x0C, 0x33, 0xC0, 0x8A, 0x41, 0x64, 0x83, 0xF8, 0x02, 0x74, 0x05, 0x83, 0xF8, 0x03, 0x75, 0x20, 0x8B,
0x91, 0xB4, 0x00, 0x00, 0x00, 0x89, 0x55, 0xF8, 0xDB, 0x45, 0xF8, 0xD8, 0x0D, 0xC8, 0x18, 0x6E, 0x00, 0xE8, 0x1C,
0x55, 0x0B, 0x00, 0x8B, 0x4D, 0x0C, 0x89, 0x81, 0xB4, 0x00, 0x00, 0x00, 0x5F, 0x5E, 0x5B, 0x8B, 0xE5, 0x5D, 0xC3};
memcpy((int*)0x4E3437, btParty, sizeof(btParty));
Autoridade do nick Webzen:
Código:
*(BYTE*)(0x45D33A) = 0x01;
*(BYTE*)(0x45D37B) = 0x01;
*(BYTE*)(0x45D3E3) = 0x01;
WebZen Mu GameServer already running:
Código:
*(BYTE*)(0x48F766) = 0xEB;
Stand-by DataServer:
Código:
*(BYTE*)(0x462C07) = 0x90;
*(BYTE*)(0x462C08) = 0x90;
*(BYTE*)(0x462C09) = 0x90;
*(BYTE*)(0x462C0A) = 0x90;
*(BYTE*)(0x462C0B) = 0x90;
Socket Serial:
Código:
*(BYTE*)(0x414239) = 0xEB;
DestroyGIocp:
Código:
*(BYTE*)(0x40165E) = 0xC3;
*(BYTE*)(0x40165F) = 0x90;
*(BYTE*)(0x401660) = 0x90;
*(BYTE*)(0x401661) = 0x90;
*(BYTE*)(0x401652) = 0x90;
Invalid Socket:
Código:
*(BYTE*)(0x440EF8) = 0x90;
*(BYTE*)(0x440EF9) = 0x90;
*(BYTE*)(0x440F23) = 0xEB;
Protocol Error:
Código:
*(BYTE*)(0x426EA1 + btTemp) = 0x90;
Hack Reporting (Client Hack Detected...):
Código:
*(BYTE*)(0x41529B) = 0x90;
*(BYTE*)(0x41529C) = 0x90;
*(BYTE*)(0x4152B6) = 0xE9;
*(BYTE*)(0x4152B7) = 0xC2;
*(BYTE*)(0x4152B8) = 0x00;
*(BYTE*)(0x4152B9) = 0x00;
*(BYTE*)(0x4152BA) = 0x00;
*(BYTE*)(0x4152BB) = 0x90;
error-L2 : Index(%d) %x %x %x:
Código:
*(BYTE*)(0x44029B) = 0x90;
*(BYTE*)(0x44029C) = 0x90;
*(BYTE*)(0x44029D) = 0x90;
*(BYTE*)(0x44029E) = 0x90;
*(BYTE*)(0x44029F) = 0x90;
*(BYTE*)(0x4402A0) = 0x90;
Também gostaria de ressaltar num bug muito comum, que possui a mesma funcionalidade do Ring Bug que os usuários usam para reviver durante 3 ~ 5 segundos e matar seus adversários, que são por trade. Ex: um jogador morre estando no trade e cancela o pedido, automaticamente ele revive e mata seu adversário (se o servidor for fácil/mediano).
Uma possível solução para isso, seria verificar se o personagem está vivo antes de cancelar o pedido, ex:
Código:
void Trade::Response(PMSG_TRADE_RESPONSE* lpMsg, DWORD dwIndex)
{
if(Object[dwIndex].Live != 1)
{
return;
}
ServerResponseTrade(lpMsg, dwIndex);
}
Logicamente, o usuário seria impedido de prosseguir com o processo de cancelamento e evitaria reviver. (o mesmo não foi testado, é apenas uma ideia pra quem deseja acabar com isso.)
Créditos:
Network. ;)