summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--conf/battle/client.conf6
-rw-r--r--conf/battle/party.conf2
-rw-r--r--src/map/battle.c5
-rw-r--r--src/map/battle.h1
-rw-r--r--src/map/clif.c77
-rw-r--r--src/map/clif.h4
-rw-r--r--src/map/packets.h8
7 files changed, 93 insertions, 10 deletions
diff --git a/conf/battle/client.conf b/conf/battle/client.conf
index e638ed0a0..93ad536ee 100644
--- a/conf/battle/client.conf
+++ b/conf/battle/client.conf
@@ -9,6 +9,12 @@
// assume unit types (1: Pc, 2: Mob, 4: Pet, 8: Homun, 16: Mercenary)
//--------------------------------------------------------------
+// Whether to enable the official packet obfuscation support (good vs WPE)
+// 0: disabled
+// 1: optional (not recommended) -- identifies whether it is required
+// 2: enabled (recommended)
+packet_obfuscation: 1
+
// Minimum delay between whisper/global/party/guild messages (in ms)
// Messages that break this threshold are silently omitted.
min_chat_delay: 0
diff --git a/conf/battle/party.conf b/conf/battle/party.conf
index e57bc4fc9..7339b2e3c 100644
--- a/conf/battle/party.conf
+++ b/conf/battle/party.conf
@@ -15,7 +15,7 @@ party_update_interval: 1000
// Method used to update party-mate hp-bars:
// 0: Aegis - bar is updated every time HP changes (bandwidth intensive)
-// 1: Hercules - bar is updated with the party map dots (up to 1 second delay)
+// 1: Athena - bar is updated with the party map dots (up to 1 second delay)
party_hp_mode: 0
// When 'Party Share' item sharing is enabled in a party,
diff --git a/src/map/battle.c b/src/map/battle.c
index 9fa4224f5..1fa35116e 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -6368,7 +6368,7 @@ static const struct _battle_data {
{ "cashshop_show_points", &battle_config.cashshop_show_points, 0, 0, 1, },
{ "mail_show_status", &battle_config.mail_show_status, 0, 0, 2, },
{ "client_limit_unit_lv", &battle_config.client_limit_unit_lv, 0, 0, BL_ALL, },
-// BattleGround Settings
+ // BattleGround Settings
{ "bg_update_interval", &battle_config.bg_update_interval, 1000, 100, INT_MAX, },
{ "bg_flee_penalty", &battle_config.bg_flee_penalty, 20, 0, INT_MAX, },
/**
@@ -6393,6 +6393,7 @@ static const struct _battle_data {
{ "max_walk_path", &battle_config.max_walk_path, 17, 1, MAX_WALKPATH, },
{ "item_enabled_npc", &battle_config.item_enabled_npc, 1, 0, 1, },
{ "gm_ignore_warpable_area", &battle_config.gm_ignore_warpable_area, 0, 2, 100, },
+ { "packet_obfuscation", &battle_config.packet_obfuscation, 1, 0, 3, },
};
#ifndef STATS_OPT_OUT
/**
@@ -6617,7 +6618,7 @@ void battle_adjust_conf(void) {
#ifndef CELL_NOSTACK
if (battle_config.cell_stack_limit != 1)
- ShowWarning("Battle setting 'cell_stack_limit' takes no effect as this server was compiled without Cell Stack Limit support.\n");
+ ShowWarning("Battle setting 'cell_stack_limit' takes no effect as this server was compiled without Cell Stack Limit support (CELL_NOSTACK).\n");
#endif
}
diff --git a/src/map/battle.h b/src/map/battle.h
index 02d21ed69..7d41a02c5 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -449,6 +449,7 @@ struct Battle_Config {
int item_restricted_consumption_type;
int max_walk_path;
int item_enabled_npc;
+ int packet_obfuscation;
int gm_ignore_warpable_area;
diff --git a/src/map/clif.c b/src/map/clif.c
index 2f8ecd6a4..2feb6f4bf 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -632,6 +632,7 @@ void clif_authfail_fd(int fd, int type)
WFIFOB(fd,2) = type;
WFIFOSET(fd,packet_len(0x81));
set_eof(fd);
+
}
@@ -9288,6 +9289,7 @@ void clif_parse_WantToConnection(int fd, struct map_session_data* sd) {
WFIFOB(fd,2) = 3; // Rejected by server
WFIFOSET(fd,packet_len(0x6a));
set_eof(fd);
+
return;
}
@@ -9301,6 +9303,8 @@ void clif_parse_WantToConnection(int fd, struct map_session_data* sd) {
CREATE(sd, TBL_PC, 1);
sd->fd = fd;
+ sd->cryptKey = (( clif->cryptKey[0] * clif->cryptKey[1] ) + clif->cryptKey[2]) & 0xFFFFFFFF;
+
session[fd]->session_data = sd;
pc->setnewpc(sd, account_id, char_id, login_id1, client_tick, sex, fd);
@@ -9819,6 +9823,7 @@ void clif_parse_QuitGame(int fd, struct map_session_data *sd)
(!battle_config.prevent_logout || DIFF_TICK(iTimer->gettick(), sd->canlog_tick) > battle_config.prevent_logout) )
{
set_eof(fd);
+
clif->disconnect_ack(sd, 0);
} else {
clif->disconnect_ack(sd, 1);
@@ -17436,6 +17441,47 @@ void clif_scriptclear(struct map_session_data *sd, int npcid) {
clif->send(&p,sizeof(p), &sd->bl, SELF);
}
+unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) {
+ if( sd ) {
+ sd->cryptKey = (( sd->cryptKey * clif->cryptKey[1] ) + clif->cryptKey[2]) & 0xFFFFFFFF;
+ return (cmd ^ ((sd->cryptKey >> 16) & 0x7FFF));
+ }
+ return (cmd ^ (((( clif->cryptKey[0] * clif->cryptKey[1] ) + clif->cryptKey[2]) >> 16) & 0x7FFF));
+}
+unsigned short clif_parse_cmd_normal ( int fd, struct map_session_data *sd ) {
+ unsigned short cmd = RFIFOW(fd,0);
+ // filter out invalid / unsupported packets
+ if (cmd > MAX_PACKET_DB || packet_db[cmd].len == 0)
+ return 0;
+
+ return cmd;
+}
+unsigned short clif_parse_cmd_optional ( int fd, struct map_session_data *sd ) {
+ unsigned short cmd = RFIFOW(fd,0);
+
+ // filter out invalid / unsupported packets
+ if (cmd > MAX_PACKET_DB || packet_db[cmd].len == 0) {
+ cmd = clif->decrypt_cmd( cmd, sd );
+ if( cmd > MAX_PACKET_DB || packet_db[cmd].len == 0 )
+ return 0;
+ RFIFOW(fd, 0) = cmd;
+ }
+
+ return cmd;
+}
+unsigned short clif_parse_cmd_decrypt ( int fd, struct map_session_data *sd ) {
+ unsigned short cmd = RFIFOW(fd,0);
+
+ cmd = clif->decrypt_cmd( cmd, sd );
+
+ // filter out invalid / unsupported packets
+ if (cmd > MAX_PACKET_DB || packet_db[cmd].len == 0 )
+ return 0;
+
+ RFIFOW(fd, 0) = cmd;
+
+ return cmd;
+}
/*==========================================
* Main client packet processing function
@@ -17479,20 +17525,18 @@ int clif_parse(int fd) {
if (RFIFOREST(fd) < 2)
return 0;
- cmd = RFIFOW(fd,0);
-
- // filter out invalid / unsupported packets
- if (cmd > MAX_PACKET_DB || packet_db[cmd].len == 0) {
- ShowWarning("clif_parse: Received unsupported packet (packet 0x%04x, %d bytes received), disconnecting session #%d.\n", cmd, RFIFOREST(fd), fd);
+ if( !( cmd = clif->parse_cmd(fd,sd) ) ) {
+ ShowWarning("clif_parse: Received unsupported packet (packet 0x%04x, %d bytes received), disconnecting session #%d.\n", RFIFOW(fd,0), RFIFOREST(fd), fd);
#ifdef DUMP_INVALID_PACKET
ShowDump(RFIFOP(fd,0), RFIFOREST(fd));
#endif
set_eof(fd);
return 0;
}
+
// determine real packet length
- packet_len = packet_db[cmd].len;
- if (packet_len == -1) { // variable-length packet
+ if ( ( packet_len = packet_db[cmd].len ) == -1) { // variable-length packet
+
if (RFIFOREST(fd) < 4)
return 0;
@@ -17503,9 +17547,11 @@ int clif_parse(int fd) {
ShowDump(RFIFOP(fd,0), RFIFOREST(fd));
#endif
set_eof(fd);
+
return 0;
}
}
+
if ((int)RFIFOREST(fd) < packet_len)
return 0; // not enough data received to form the packet
@@ -17598,14 +17644,29 @@ void packetdb_loaddb(void) {
memset(packet_db,0,sizeof(packet_db));
#define packet(id, size, ...) packetdb_addpacket(id, size, ##__VA_ARGS__, 0xFFFF)
+ #define packetKeys(a,b,c) { clif->cryptKey[0] = a; clif->cryptKey[1] = b; clif->cryptKey[2] = c; }
#include "packets.h" /* load structure data */
#undef packet
+ #undef packetKeys
}
void clif_bc_ready(void) {
if( battle_config.display_status_timers )
clif->status_change = clif_status_change;
else
clif->status_change = clif_status_change_notick;
+
+ switch( battle_config.packet_obfuscation ) {
+ case 0:
+ clif->parse_cmd = clif_parse_cmd_normal;
+ break;
+ default:
+ case 1:
+ clif->parse_cmd = clif_parse_cmd_optional;
+ break;
+ case 2:
+ clif->parse_cmd = clif_parse_cmd_decrypt;
+ break;
+ }
}
/*==========================================
*
@@ -17689,6 +17750,8 @@ void clif_defaults(void) {
clif->send = clif_send;
clif->send_sub = clif_send_sub;
clif->parse = clif_parse;
+ clif->parse_cmd = clif_parse_cmd_optional;
+ clif->decrypt_cmd = clif_decrypt_cmd;
/* auth */
clif->authok = clif_authok;
clif->authrefuse = clif_authrefuse;
diff --git a/src/map/clif.h b/src/map/clif.h
index b447687ea..6e1fa81d3 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -462,6 +462,8 @@ struct clif_interface {
struct hCSData **data[CASHSHOP_TAB_MAX];
unsigned int item_count[CASHSHOP_TAB_MAX];
} cs;
+ /* */
+ unsigned int cryptKey[3];
/* core */
int (*init) (void);
void (*final) (void);
@@ -472,6 +474,8 @@ struct clif_interface {
int (*send) (const void* buf, int len, struct block_list* bl, enum send_target type);
int (*send_sub) (struct block_list *bl, va_list ap);
int (*parse) (int fd);
+ unsigned short (*parse_cmd) ( int fd, struct map_session_data *sd );
+ unsigned short (*decrypt_cmd) ( int cmd, struct map_session_data *sd );
/* auth */
void (*authok) (struct map_session_data *sd);
void (*authrefuse) (int fd, uint8 error_code);
diff --git a/src/map/packets.h b/src/map/packets.h
index bcce36040..43b36e033 100644
--- a/src/map/packets.h
+++ b/src/map/packets.h
@@ -10,6 +10,10 @@
#define packet(a,b,...)
#endif
+#ifndef packetKeys
+ #define packetKeys(a,b,c)
+#endif
+
/*
* packet syntax
* - packet(packet_id,length)
@@ -2017,6 +2021,8 @@ packet(0x020d,-1);
packet(0x08E5,41,clif->pPartyBookingRegisterReq,2,4);
packet(0x08d2,10);
packet(0x0916,26,clif->pGuildInvite2,2);
+ packetKeys(0x1540e48,0x13041224,0x31247924);
+
#endif
//2012-06-18aRagexeRE
@@ -2052,6 +2058,7 @@ packet(0x020d,-1);
//2012-07-16aRagExe (special thanks to Yommy!)
#if PACKETVER >= 20120716
packet(0x0364,8,clif->pMoveFromKafra,2,4);
+ packetKeys(0x76052205, 0x22052205, 0x22052205);
#endif
//2013-03-20Ragexe (Judas + Yommy)
@@ -2086,6 +2093,7 @@ packet(0x020d,-1);
packet(0x086F,26,clif->pFriendsListAdd,2);
packet(0x093F,5,clif->pHomMenu,2,4);
packet(0x0947,36,clif->pStoragePassword,0);
+ packetKeys(0x3F094C49, 0x55F86C1E, 0x58AA359A);
// Shuffle End
// New Packets