From 5a942993dd12ae7d85b1633a58b0dc23f85832c2 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Fri, 14 Jun 2013 08:53:17 -0300 Subject: Hercules WPE Free Official Packet Obfuscation Support http://hercules.ws/board/topic/1105-hercules-wpe-free-june-14th-patch/ Signed-off-by: shennetsind --- src/map/battle.c | 5 ++-- src/map/battle.h | 1 + src/map/clif.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++----- src/map/clif.h | 4 +++ src/map/packets.h | 8 ++++++ 5 files changed, 86 insertions(+), 9 deletions(-) (limited to 'src') 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 -- cgit v1.2.3-70-g09d2