From 88c489d39323df897d287e4739588cc244038584 Mon Sep 17 00:00:00 2001 From: Arkshine Date: Mon, 26 May 2014 18:02:30 +0200 Subject: [PATCH 01/14] Cstrike: Move AMXX API in a new file. --- dlls/cstrike/cstrike/AMBuilder | 1 + dlls/cstrike/cstrike/Makefile | 2 +- dlls/cstrike/cstrike/amxx_api.cpp | 57 +++++++++++++++++++++ dlls/cstrike/cstrike/cstrike.cpp | 57 +-------------------- dlls/cstrike/cstrike/msvc10/cstrike.vcxproj | 1 + 5 files changed, 62 insertions(+), 56 deletions(-) create mode 100644 dlls/cstrike/cstrike/amxx_api.cpp diff --git a/dlls/cstrike/cstrike/AMBuilder b/dlls/cstrike/cstrike/AMBuilder index dbb36069..b96e0207 100644 --- a/dlls/cstrike/cstrike/AMBuilder +++ b/dlls/cstrike/cstrike/AMBuilder @@ -5,6 +5,7 @@ binary = AMXX.MetaModule(builder, 'cstrike') binary.sources = [ 'sdk/amxxmodule.cpp', + 'amxx_api.cpp', 'CstrikePlayer.cpp', 'cstrike.cpp', 'CstrikeHacks.cpp', diff --git a/dlls/cstrike/cstrike/Makefile b/dlls/cstrike/cstrike/Makefile index 7edf61fd..c3c22401 100755 --- a/dlls/cstrike/cstrike/Makefile +++ b/dlls/cstrike/cstrike/Makefile @@ -14,7 +14,7 @@ MM_ROOT = ../../../../metamod/metamod PROJECT = cstrike -OBJECTS = sdk/amxxmodule.cpp CstrikePlayer.cpp cstrike.cpp CstrikeHacks.cpp +OBJECTS = sdk/amxxmodule.cpp amxx_api.cpp CstrikePlayer.cpp cstrike.cpp CstrikeHacks.cpp ############################################## ### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### diff --git a/dlls/cstrike/cstrike/amxx_api.cpp b/dlls/cstrike/cstrike/amxx_api.cpp new file mode 100644 index 00000000..2b8c27eb --- /dev/null +++ b/dlls/cstrike/cstrike/amxx_api.cpp @@ -0,0 +1,57 @@ +/* AMX Mod X + * Counter-Strike Module + * + * by the AMX Mod X Development Team + * + * This file is part of AMX Mod X. + * + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + */ +#include "amxxmodule.h" +#include "cstrike.h" + +extern AMX_NATIVE_INFO cstrikeNatives[]; + +int AmxxCheckGame(const char *game) +{ + if (strcasecmp(game, "cstrike") == 0 || + strcasecmp(game, "czero") == 0) + { + return AMXX_GAME_OK; + } + return AMXX_GAME_BAD; +} + +void OnAmxxAttach() +{ + MF_AddNatives(cstrikeNatives); + InitializeHacks(); +} + +void OnAmxxDetach() +{ + ShutdownHacks(); +} \ No newline at end of file diff --git a/dlls/cstrike/cstrike/cstrike.cpp b/dlls/cstrike/cstrike/cstrike.cpp index 4e9b41ac..dc90838f 100755 --- a/dlls/cstrike/cstrike/cstrike.cpp +++ b/dlls/cstrike/cstrike/cstrike.cpp @@ -1,38 +1,5 @@ #include "cstrike.h" -/* AMX Mod X - * Counter-Strike Module - * - * by the AMX Mod X Development Team - * - * This file is part of AMX Mod X. - * - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * In addition, as a special exception, the author gives permission to - * link the code of this program with the Half-Life Game Engine ("HL - * Engine") and Modified Game Libraries ("MODs") developed by Valve, - * L.L.C ("Valve"). You must obey the GNU General Public License in all - * respects for all of the code used other than the HL Engine and MODs - * from Valve. If you modify this file, you may extend this exception - * to your version of the file, but you are not obligated to do so. If - * you do not wish to do so, delete this exception statement from your - * version. - */ - CCstrikePlayer g_players[33]; int g_zooming[33] = {0}; bool g_precachedknife = false; @@ -1777,7 +1744,7 @@ static cell AMX_NATIVE_CALL not_on_64(AMX* amx, cell* params) #endif -AMX_NATIVE_INFO cstrike_Exports[] = { +AMX_NATIVE_INFO cstrikeNatives[] = { {"cs_set_user_money", cs_set_user_money}, {"cs_get_user_money", cs_get_user_money}, {"cs_get_user_deaths", cs_get_user_deaths}, @@ -1918,24 +1885,4 @@ void PlayerPreThink(edict_t *pPlayer) } RETURN_META(MRES_IGNORED); -} - -int AmxxCheckGame(const char *game) -{ - if (strcasecmp(game, "cstrike") == 0 || - strcasecmp(game, "czero") == 0) - { - return AMXX_GAME_OK; - } - return AMXX_GAME_BAD; -} -void OnAmxxAttach() -{ - MF_AddNatives(cstrike_Exports); - InitializeHacks(); -} - -void OnAmxxDetach() -{ - ShutdownHacks(); -} +} \ No newline at end of file diff --git a/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj b/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj index 23494392..5904a14e 100644 --- a/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj +++ b/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj @@ -135,6 +135,7 @@ + From f08e22db954523943aabd2ad247b8aa0f05bee87 Mon Sep 17 00:00:00 2001 From: Arkshine Date: Mon, 26 May 2014 18:42:51 +0200 Subject: [PATCH 02/14] Cstrike: Rename cstrike.cpp to CstrikeNatives.cpp --- dlls/cstrike/cstrike/AMBuilder | 2 +- dlls/cstrike/cstrike/CstrikeHacks.cpp | 2 +- .../{cstrike.cpp => CstrikeNatives.cpp} | 38 +++++++++++++++++-- .../cstrike/{cstrike.h => CstrikeNatives.h} | 0 dlls/cstrike/cstrike/Makefile | 2 +- dlls/cstrike/cstrike/amxx_api.cpp | 2 +- dlls/cstrike/cstrike/msvc10/cstrike.vcxproj | 4 +- .../cstrike/msvc10/cstrike.vcxproj.filters | 15 +++++--- 8 files changed, 50 insertions(+), 15 deletions(-) rename dlls/cstrike/cstrike/{cstrike.cpp => CstrikeNatives.cpp} (97%) mode change 100755 => 100644 rename dlls/cstrike/cstrike/{cstrike.h => CstrikeNatives.h} (100%) mode change 100755 => 100644 diff --git a/dlls/cstrike/cstrike/AMBuilder b/dlls/cstrike/cstrike/AMBuilder index b96e0207..904ab6d6 100644 --- a/dlls/cstrike/cstrike/AMBuilder +++ b/dlls/cstrike/cstrike/AMBuilder @@ -7,7 +7,7 @@ binary.sources = [ 'sdk/amxxmodule.cpp', 'amxx_api.cpp', 'CstrikePlayer.cpp', - 'cstrike.cpp', + 'CstrikeNatives.cpp', 'CstrikeHacks.cpp', ] diff --git a/dlls/cstrike/cstrike/CstrikeHacks.cpp b/dlls/cstrike/cstrike/CstrikeHacks.cpp index 97278dc7..11119b43 100644 --- a/dlls/cstrike/cstrike/CstrikeHacks.cpp +++ b/dlls/cstrike/cstrike/CstrikeHacks.cpp @@ -1,6 +1,6 @@ #include #include -#include "cstrike.h" +#include "CstrikeNatives.h" #if defined(__linux__) || defined(__APPLE__) #include diff --git a/dlls/cstrike/cstrike/cstrike.cpp b/dlls/cstrike/cstrike/CstrikeNatives.cpp old mode 100755 new mode 100644 similarity index 97% rename from dlls/cstrike/cstrike/cstrike.cpp rename to dlls/cstrike/cstrike/CstrikeNatives.cpp index dc90838f..ef106976 --- a/dlls/cstrike/cstrike/cstrike.cpp +++ b/dlls/cstrike/cstrike/CstrikeNatives.cpp @@ -1,4 +1,36 @@ -#include "cstrike.h" +/* AMX Mod X + * Counter-Strike Module + * + * by the AMX Mod X Development Team + * + * This file is part of AMX Mod X. + * + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + */ +#include "CstrikeNatives.h" CCstrikePlayer g_players[33]; int g_zooming[33] = {0}; @@ -1306,8 +1338,8 @@ static cell AMX_NATIVE_CALL cs_user_spawn(AMX *amx, cell *params) MDLL_Think(pPlayer); const char *auth = GETPLAYERAUTHID(pPlayer); - if (((pPlayer->v.flags & FL_FAKECLIENT) == FL_FAKECLIENT || (auth && (strcmp(auth, "BOT") == 0))) && pPlayer->v.deadflag == DEAD_RESPAWNABLE) { - MDLL_Spawn(pPlayer); + if (((pPlayer->v.flags & FL_FAKECLIENT) == FL_FAKECLIENT || (auth && (strcmp(auth, "BOT") == 0))) && pPlayer->v.deadflag == DEAD_RESPAWNABLE) { + MDLL_Spawn(pPlayer); } // pPlayer->v.iuser1 = 0; diff --git a/dlls/cstrike/cstrike/cstrike.h b/dlls/cstrike/cstrike/CstrikeNatives.h old mode 100755 new mode 100644 similarity index 100% rename from dlls/cstrike/cstrike/cstrike.h rename to dlls/cstrike/cstrike/CstrikeNatives.h diff --git a/dlls/cstrike/cstrike/Makefile b/dlls/cstrike/cstrike/Makefile index c3c22401..61140da5 100755 --- a/dlls/cstrike/cstrike/Makefile +++ b/dlls/cstrike/cstrike/Makefile @@ -14,7 +14,7 @@ MM_ROOT = ../../../../metamod/metamod PROJECT = cstrike -OBJECTS = sdk/amxxmodule.cpp amxx_api.cpp CstrikePlayer.cpp cstrike.cpp CstrikeHacks.cpp +OBJECTS = sdk/amxxmodule.cpp amxx_api.cpp CstrikePlayer.cpp CstrikeNatives.cpp CstrikeHacks.cpp ############################################## ### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### diff --git a/dlls/cstrike/cstrike/amxx_api.cpp b/dlls/cstrike/cstrike/amxx_api.cpp index 2b8c27eb..3a4f0c68 100644 --- a/dlls/cstrike/cstrike/amxx_api.cpp +++ b/dlls/cstrike/cstrike/amxx_api.cpp @@ -31,7 +31,7 @@ * version. */ #include "amxxmodule.h" -#include "cstrike.h" +#include "CstrikeNatives.h" extern AMX_NATIVE_INFO cstrikeNatives[]; diff --git a/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj b/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj index 5904a14e..7232ab8a 100644 --- a/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj +++ b/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj @@ -136,13 +136,13 @@ - + - + diff --git a/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj.filters b/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj.filters index 1cea77cc..b3e7ccc3 100644 --- a/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj.filters +++ b/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj.filters @@ -20,9 +20,6 @@ - - Source Files - Source Files @@ -32,11 +29,14 @@ Module SDK\SDK Base + + Source Files + + + Source Files + - - Header Files - Header Files @@ -49,6 +49,9 @@ Module SDK\SDK Base + + Header Files + From 62cf10f0c354d5aff2badd1cee827d5bd47a0032 Mon Sep 17 00:00:00 2001 From: Arkshine Date: Mon, 26 May 2014 21:19:18 +0200 Subject: [PATCH 03/14] Cstrike: Move game datas in its own file. --- dlls/cstrike/cstrike/CstrikeDatas.h | 257 ++++++++++++++++++ dlls/cstrike/cstrike/CstrikeHacks.cpp | 2 +- dlls/cstrike/cstrike/CstrikeNatives.cpp | 1 + dlls/cstrike/cstrike/CstrikeNatives.h | 253 ----------------- dlls/cstrike/cstrike/msvc10/cstrike.vcxproj | 1 + .../cstrike/msvc10/cstrike.vcxproj.filters | 3 + 6 files changed, 263 insertions(+), 254 deletions(-) create mode 100644 dlls/cstrike/cstrike/CstrikeDatas.h diff --git a/dlls/cstrike/cstrike/CstrikeDatas.h b/dlls/cstrike/cstrike/CstrikeDatas.h new file mode 100644 index 00000000..b237b34e --- /dev/null +++ b/dlls/cstrike/cstrike/CstrikeDatas.h @@ -0,0 +1,257 @@ +#ifndef CSTRIKE_DATA_H +#define CSTRIKE_DATA_H + +#include "amxxmodule.h" + +#if defined(__linux__) || defined (__APPLE__) + #define EXTRAOFFSET 5 // offsets 5 higher in Linux builds + #define EXTRAOFFSET_WEAPONS 4 // weapon offsets are obviously only 4 steps higher on Linux! + #define ACTUAL_EXTRA_OFFSET 20 // actual, byte-addressable offset +#else + #define EXTRAOFFSET 0 // no change in Windows builds + #define EXTRAOFFSET_WEAPONS 0 + #define ACTUAL_EXTRA_OFFSET 0 +#endif + +/* + Offset history: + 041029: + Confirmed (pretty much) ALL offsets for 32 bit Windows, 32 bit Linux and amd64 (yes that's all of them). + Found out that weapon offsets are only +4 higher on Linux. + Also backpack ammo offsets were all obviously 5 steps too high since unknown time... + +*/ +// "player" entities +#if !defined __amd64__ + // 32 bit offsets here + #define OFFSET_ARMORTYPE 112 + EXTRAOFFSET + #define OFFSET_TEAM 114 + EXTRAOFFSET + #define OFFSET_CSMONEY 115 + EXTRAOFFSET + #define OFFSET_PRIMARYWEAPON 116 + EXTRAOFFSET + #define OFFSET_LASTACTIVITY 124 + EXTRAOFFSET + #define OFFSET_INTERNALMODEL 126 + EXTRAOFFSET + #define OFFSET_NVGOGGLES 129 + EXTRAOFFSET + #define OFFSET_DEFUSE_PLANT 193 + EXTRAOFFSET + #define OFFSET_VIP 209 + EXTRAOFFSET + #define OFFSET_TK 216 + EXTRAOFFSET // 040926 + #define OFFSET_HOSTAGEKILLS 217 + EXTRAOFFSET + #define OFFSET_MAPZONE 235 + EXTRAOFFSET + #define OFFSET_ISDRIVING 350 + EXTRAOFFSET // 040926 + #define OFFSET_STATIONARY 362 + EXTRAOFFSET // 040927 (363 works also!) + #define OFFSET_ZOOMTYPE 363 + EXTRAOFFSET + + #define OFFSET_AWM_AMMO 377 + EXTRAOFFSET // 041029: All of these *_AMMO:s were changed -5 + #define OFFSET_SCOUT_AMMO 378 + EXTRAOFFSET + #define OFFSET_PARA_AMMO 379 + EXTRAOFFSET + #define OFFSET_FAMAS_AMMO 380 + EXTRAOFFSET + #define OFFSET_M3_AMMO 381 + EXTRAOFFSET + #define OFFSET_USP_AMMO 382 + EXTRAOFFSET + #define OFFSET_FIVESEVEN_AMMO 383 + EXTRAOFFSET + #define OFFSET_DEAGLE_AMMO 384 + EXTRAOFFSET + #define OFFSET_P228_AMMO 385 + EXTRAOFFSET + #define OFFSET_GLOCK_AMMO 386 + EXTRAOFFSET + #define OFFSET_FLASH_AMMO 387 + EXTRAOFFSET + #define OFFSET_HE_AMMO 388 + EXTRAOFFSET + #define OFFSET_SMOKE_AMMO 389 + EXTRAOFFSET + #define OFFSET_C4_AMMO 390 + EXTRAOFFSET + + #define OFFSET_CSDEATHS 444 + EXTRAOFFSET // 040926 + #define OFFSET_SHIELD 510 + EXTRAOFFSET + // "weapon_*" entities + #define OFFSET_WEAPONTYPE 43 + EXTRAOFFSET_WEAPONS + #define OFFSET_CLIPAMMO 51 + EXTRAOFFSET_WEAPONS + #define OFFSET_SILENCER_FIREMODE 74 + EXTRAOFFSET_WEAPONS + // "hostage_entity" entities + #define OFFSET_HOSTAGEFOLLOW 86 + EXTRAOFFSET + #define OFFSET_HOSTAGE_NEXTUSE 100 + EXTRAOFFSET + #define OFFSET_HOSTAGE_LASTUSE 483 + EXTRAOFFSET + #define OFFSET_HOSTAGEID 487 + EXTRAOFFSET + // "armoury_entity" + #define OFFSET_ARMOURY_TYPE 34 + EXTRAOFFSET_WEAPONS + // C4 offsets + #define OFFSET_C4_EXPLODE_TIME 100 + EXTRAOFFSET + #define OFFSET_C4_DEFUSING 0x181 + ACTUAL_EXTRA_OFFSET +#else + // Amd64 offsets here + #define OFFSET_ARMORTYPE 137 + EXTRAOFFSET + #define OFFSET_TEAM 139 + EXTRAOFFSET // +25 + #define OFFSET_CSMONEY 140 + EXTRAOFFSET // +25 + #define OFFSET_PRIMARYWEAPON 141 + EXTRAOFFSET // +25 + #define OFFSET_INTERNALMODEL 152 + EXTRAOFFSET // +26 + #define OFFSET_NVGOGGLES 155 + EXTRAOFFSET // +26 + #define OFFSET_DEFUSE_PLANT 219 + EXTRAOFFSET // +26 + #define OFFSET_VIP 242 + EXTRAOFFSET // +27 + #define OFFSET_TK 249 + EXTRAOFFSET // +33 040927 + #define OFFSET_MAPZONE 268 + EXTRAOFFSET // +27 + #define OFFSET_ISDRIVING 386 + EXTRAOFFSET // 040927 + #define OFFSET_STATIONARY 400 + EXTRAOFFSET // 040927 (401 works also) + #define OFFSET_ZOOMTYPE 402 + EXTRAOFFSET + + #define OFFSET_AWM_AMMO 426 + EXTRAOFFSET // +44 + #define OFFSET_SCOUT_AMMO 427 + EXTRAOFFSET // +44 + #define OFFSET_PARA_AMMO 428 + EXTRAOFFSET // +44 + #define OFFSET_FAMAS_AMMO 429 + EXTRAOFFSET // +44 + #define OFFSET_M3_AMMO 430 + EXTRAOFFSET // +44 + #define OFFSET_USP_AMMO 431 + EXTRAOFFSET // +44 + #define OFFSET_FIVESEVEN_AMMO 432 + EXTRAOFFSET // +44 + #define OFFSET_DEAGLE_AMMO 433 + EXTRAOFFSET // +44 + #define OFFSET_P228_AMMO 434 + EXTRAOFFSET // +44 + #define OFFSET_GLOCK_AMMO 435 + EXTRAOFFSET // +44 + #define OFFSET_FLASH_AMMO 436 + EXTRAOFFSET // +44 + #define OFFSET_HE_AMMO 437 + EXTRAOFFSET // +44 + #define OFFSET_SMOKE_AMMO 438 + EXTRAOFFSET // +44 + #define OFFSET_C4_AMMO 439 + EXTRAOFFSET // +44 + + #define OFFSET_CSDEATHS 493 + EXTRAOFFSET // +49 + #define OFFSET_SHIELD 559 + EXTRAOFFSET + // "weapon_*" entities + #define OFFSET_WEAPONTYPE 57 + EXTRAOFFSET // +14 + #define OFFSET_CLIPAMMO 65 + EXTRAOFFSET // +14 + #define OFFSET_SILENCER_FIREMODE 88 + EXTRAOFFSET // +14 + // "hostage_entity" entities + #define OFFSET_HOSTAGEFOLLOW 51 + EXTRAOFFSET // +21, long=51, int=107! (must use the long* offset because pointers on amd64 are stored the size of longs, 8 bytes, instead of the usual int 4 bytes.) + #define OFFSET_HOSTAGEID 516 + EXTRAOFFSET // +29 +#endif + +#if defined __linux__ +#define CS_DETOURCOPYBYTES_CLIENTCOMMAND 6 +#elif defined __APPLE__ +#define CS_DETOURCOPYBYTES_CLIENTCOMMAND 5 +#else +#define CS_DETOURCOPYBYTES_CLIENTCOMMAND 6 +#define CS_CLICMD_OFFS_USEBOTARGS 2 +#define CS_CLICMD_OFFS_BOTARGS 22 +#endif + + +// Ids of weapons in CS +#define CSW_P228 1 +//#define CSW_SHIELD 2 +#define CSW_SCOUT 3 +#define CSW_HEGRENADE 4 +#define CSW_XM1014 5 +#define CSW_C4 6 +#define CSW_MAC10 7 +#define CSW_AUG 8 +#define CSW_SMOKEGRENADE 9 +#define CSW_ELITE 10 +#define CSW_FIVESEVEN 11 +#define CSW_UMP45 12 +#define CSW_SG550 13 +#define CSW_GALI 14 +#define CSW_FAMAS 15 +#define CSW_USP 16 +#define CSW_GLOCK18 17 +#define CSW_AWP 18 +#define CSW_MP5NAVY 19 +#define CSW_M249 20 +#define CSW_M3 21 +#define CSW_M4A1 22 +#define CSW_TMP 23 +#define CSW_G3SG1 24 +#define CSW_FLASHBANG 25 +#define CSW_DEAGLE 26 +#define CSW_SG552 27 +#define CSW_AK47 28 +//#define CSW_KNIFE 29 +#define CSW_P90 30 +#define CSW_VEST 31 // Brand new invention! +#define CSW_VESTHELM 32 // Brand new invention! + +// These are used with armoury_entity:s. +#define CSA_MP5NAVY 0 +#define CSA_TMP 1 +#define CSA_P90 2 +#define CSA_MAC10 3 +#define CSA_AK47 4 +#define CSA_SG552 5 +#define CSA_M4A1 6 +#define CSA_AUG 7 +#define CSA_SCOUT 8 +#define CSA_G3SG1 9 +#define CSA_AWP 10 +#define CSA_M3 11 +#define CSA_XM1014 12 +#define CSA_M249 13 +#define CSA_FLASHBANG 14 +#define CSA_HEGRENADE 15 +#define CSA_VEST 16 +#define CSA_VESTHELM 17 +#define CSA_SMOKEGRENADE 18 + +#define M4A1_SILENCED (1<<2) +#define M4A1_ATTACHSILENCEANIM 6 +#define M4A1_DETACHSILENCEANIM 13 +#define USP_SILENCED (1<<0) +#define USP_ATTACHSILENCEANIM 7 +#define USP_DETACHSILENCEANIM 15 + +#define GLOCK_SEMIAUTOMATIC 0 +#define GLOCK_BURSTMODE 2 +#define FAMAS_AUTOMATIC 0 +#define FAMAS_BURSTMODE 16 + +#define PLAYER_IS_VIP (1<<8) + +#define PLAYER_IN_BUYZONE (1<<0) + +#define TEAM_UNASSIGNED 0 +#define TEAM_T 1 +#define TEAM_CT 2 +#define TEAM_SPECTATOR 3 + +#define CAN_PLANT_BOMB (1<<8) // 256 +#define HAS_DEFUSE_KIT (1<<16) // 65536 + +#define DEFUSER_COLOUR_R 0 +#define DEFUSER_COLOUR_G 160 +#define DEFUSER_COLOUR_B 0 + +#define HAS_NVGOGGLES (1<<0) + +#define SCOREATTRIB_NOTHING 0 +#define SCOREATTRIB_DEAD 1 +#define SCOREATTRIB_BOMB 2 // t only +#define SCOREATTRIB_VIP 4 // ct only + +#define AMD64_STATIONARY_NO 2 +#define AMD64_STATIONARY_YES 3 + +#define CS_ARMOR_NONE 0 +#define CS_ARMOR_KEVLAR 1 +#define CS_ARMOR_ASSAULTSUIT 2 + +#define CS_FIRST_ZOOM 0x28 +#define CS_SECOND_AWP_ZOOM 0xA +#define CS_SECOND_NONAWP_ZOOM 0xF +#define CS_AUGSG552_ZOOM 0x37 +#define CS_NO_ZOOM 0x5A + +#define HAS_SHIELD (1<<24) //16777216 + + +enum CS_Internal_Models { + CS_DONTCHANGE = 0, + CS_CT_URBAN = 1, + CS_T_TERROR = 2, + CS_T_LEET = 3, + CS_T_ARCTIC = 4, + CS_CT_GSG9 = 5, + CS_CT_GIGN = 6, + CS_CT_SAS = 7, + CS_T_GUERILLA = 8, + CS_CT_VIP = 9, + CZ_T_MILITIA = 10, + CZ_CT_SPETSNAZ = 11 +}; + +enum +{ + CS_RESET_ZOOM = 0, + CS_SET_NO_ZOOM, + CS_SET_FIRST_ZOOM, + CS_SET_SECOND_ZOOM, + CS_SET_AUGSG552_ZOOM, +}; + +#endif // CSTRIKE_DATA_H \ No newline at end of file diff --git a/dlls/cstrike/cstrike/CstrikeHacks.cpp b/dlls/cstrike/cstrike/CstrikeHacks.cpp index 11119b43..09f8be3c 100644 --- a/dlls/cstrike/cstrike/CstrikeHacks.cpp +++ b/dlls/cstrike/cstrike/CstrikeHacks.cpp @@ -1,6 +1,6 @@ #include #include -#include "CstrikeNatives.h" +#include "CstrikeDatas.h" #if defined(__linux__) || defined(__APPLE__) #include diff --git a/dlls/cstrike/cstrike/CstrikeNatives.cpp b/dlls/cstrike/cstrike/CstrikeNatives.cpp index ef106976..ed581af2 100644 --- a/dlls/cstrike/cstrike/CstrikeNatives.cpp +++ b/dlls/cstrike/cstrike/CstrikeNatives.cpp @@ -31,6 +31,7 @@ * version. */ #include "CstrikeNatives.h" +#include "CstrikeDatas.h" CCstrikePlayer g_players[33]; int g_zooming[33] = {0}; diff --git a/dlls/cstrike/cstrike/CstrikeNatives.h b/dlls/cstrike/cstrike/CstrikeNatives.h index ea82308e..d58b77b0 100644 --- a/dlls/cstrike/cstrike/CstrikeNatives.h +++ b/dlls/cstrike/cstrike/CstrikeNatives.h @@ -35,8 +35,6 @@ // This implementation uses Vexd's way (lightly modified) of setting models on players. #include "amxxmodule.h" -#include -#include #include "CstrikePlayer.h" #define GETINFOKEYBUFFER (*g_engfuncs.pfnGetInfoKeyBuffer) @@ -44,257 +42,6 @@ #define GETCLIENTKEYVALUE (*g_engfuncs.pfnInfoKeyValue) #define CREATENAMEDENTITY (*g_engfuncs.pfnCreateNamedEntity) -#if defined(__linux__) || defined (__APPLE__) - #define EXTRAOFFSET 5 // offsets 5 higher in Linux builds - #define EXTRAOFFSET_WEAPONS 4 // weapon offsets are obviously only 4 steps higher on Linux! - #define ACTUAL_EXTRA_OFFSET 20 // actual, byte-addressable offset -#else - #define EXTRAOFFSET 0 // no change in Windows builds - #define EXTRAOFFSET_WEAPONS 0 - #define ACTUAL_EXTRA_OFFSET 0 -#endif // defined(__linux__) || defined(__APPLE__) -/* - Offset history: - 041029: - Confirmed (pretty much) ALL offsets for 32 bit Windows, 32 bit Linux and amd64 (yes that's all of them). - Found out that weapon offsets are only +4 higher on Linux. - Also backpack ammo offsets were all obviously 5 steps too high since unknown time... - -*/ - -#define HAS_SHIELD (1<<24) //16777216 - -// "player" entities -#if !defined __amd64__ - // 32 bit offsets here - #define OFFSET_ARMORTYPE 112 + EXTRAOFFSET - #define OFFSET_TEAM 114 + EXTRAOFFSET - #define OFFSET_CSMONEY 115 + EXTRAOFFSET - #define OFFSET_PRIMARYWEAPON 116 + EXTRAOFFSET - #define OFFSET_LASTACTIVITY 124 + EXTRAOFFSET - #define OFFSET_INTERNALMODEL 126 + EXTRAOFFSET - #define OFFSET_NVGOGGLES 129 + EXTRAOFFSET - #define OFFSET_DEFUSE_PLANT 193 + EXTRAOFFSET - #define OFFSET_VIP 209 + EXTRAOFFSET - #define OFFSET_TK 216 + EXTRAOFFSET // 040926 - #define OFFSET_HOSTAGEKILLS 217 + EXTRAOFFSET - #define OFFSET_MAPZONE 235 + EXTRAOFFSET - #define OFFSET_ISDRIVING 350 + EXTRAOFFSET // 040926 - #define OFFSET_STATIONARY 362 + EXTRAOFFSET // 040927 (363 works also!) - #define OFFSET_ZOOMTYPE 363 + EXTRAOFFSET - - #define OFFSET_AWM_AMMO 377 + EXTRAOFFSET // 041029: All of these *_AMMO:s were changed -5 - #define OFFSET_SCOUT_AMMO 378 + EXTRAOFFSET - #define OFFSET_PARA_AMMO 379 + EXTRAOFFSET - #define OFFSET_FAMAS_AMMO 380 + EXTRAOFFSET - #define OFFSET_M3_AMMO 381 + EXTRAOFFSET - #define OFFSET_USP_AMMO 382 + EXTRAOFFSET - #define OFFSET_FIVESEVEN_AMMO 383 + EXTRAOFFSET - #define OFFSET_DEAGLE_AMMO 384 + EXTRAOFFSET - #define OFFSET_P228_AMMO 385 + EXTRAOFFSET - #define OFFSET_GLOCK_AMMO 386 + EXTRAOFFSET - #define OFFSET_FLASH_AMMO 387 + EXTRAOFFSET - #define OFFSET_HE_AMMO 388 + EXTRAOFFSET - #define OFFSET_SMOKE_AMMO 389 + EXTRAOFFSET - #define OFFSET_C4_AMMO 390 + EXTRAOFFSET - - #define OFFSET_CSDEATHS 444 + EXTRAOFFSET // 040926 - #define OFFSET_SHIELD 510 + EXTRAOFFSET - // "weapon_*" entities - #define OFFSET_WEAPONTYPE 43 + EXTRAOFFSET_WEAPONS - #define OFFSET_CLIPAMMO 51 + EXTRAOFFSET_WEAPONS - #define OFFSET_SILENCER_FIREMODE 74 + EXTRAOFFSET_WEAPONS - // "hostage_entity" entities - #define OFFSET_HOSTAGEFOLLOW 86 + EXTRAOFFSET - #define OFFSET_HOSTAGE_NEXTUSE 100 + EXTRAOFFSET - #define OFFSET_HOSTAGE_LASTUSE 483 + EXTRAOFFSET - #define OFFSET_HOSTAGEID 487 + EXTRAOFFSET - // "armoury_entity" - #define OFFSET_ARMOURY_TYPE 34 + EXTRAOFFSET_WEAPONS - // C4 offsets - #define OFFSET_C4_EXPLODE_TIME 100 + EXTRAOFFSET - #define OFFSET_C4_DEFUSING 0x181 + ACTUAL_EXTRA_OFFSET -#else - // Amd64 offsets here - #define OFFSET_ARMORTYPE 137 + EXTRAOFFSET - #define OFFSET_TEAM 139 + EXTRAOFFSET // +25 - #define OFFSET_CSMONEY 140 + EXTRAOFFSET // +25 - #define OFFSET_PRIMARYWEAPON 141 + EXTRAOFFSET // +25 - #define OFFSET_INTERNALMODEL 152 + EXTRAOFFSET // +26 - #define OFFSET_NVGOGGLES 155 + EXTRAOFFSET // +26 - #define OFFSET_DEFUSE_PLANT 219 + EXTRAOFFSET // +26 - #define OFFSET_VIP 242 + EXTRAOFFSET // +27 - #define OFFSET_TK 249 + EXTRAOFFSET // +33 040927 - #define OFFSET_MAPZONE 268 + EXTRAOFFSET // +27 - #define OFFSET_ISDRIVING 386 + EXTRAOFFSET // 040927 - #define OFFSET_STATIONARY 400 + EXTRAOFFSET // 040927 (401 works also) - #define OFFSET_ZOOMTYPE 402 + EXTRAOFFSET - - #define OFFSET_AWM_AMMO 426 + EXTRAOFFSET // +44 - #define OFFSET_SCOUT_AMMO 427 + EXTRAOFFSET // +44 - #define OFFSET_PARA_AMMO 428 + EXTRAOFFSET // +44 - #define OFFSET_FAMAS_AMMO 429 + EXTRAOFFSET // +44 - #define OFFSET_M3_AMMO 430 + EXTRAOFFSET // +44 - #define OFFSET_USP_AMMO 431 + EXTRAOFFSET // +44 - #define OFFSET_FIVESEVEN_AMMO 432 + EXTRAOFFSET // +44 - #define OFFSET_DEAGLE_AMMO 433 + EXTRAOFFSET // +44 - #define OFFSET_P228_AMMO 434 + EXTRAOFFSET // +44 - #define OFFSET_GLOCK_AMMO 435 + EXTRAOFFSET // +44 - #define OFFSET_FLASH_AMMO 436 + EXTRAOFFSET // +44 - #define OFFSET_HE_AMMO 437 + EXTRAOFFSET // +44 - #define OFFSET_SMOKE_AMMO 438 + EXTRAOFFSET // +44 - #define OFFSET_C4_AMMO 439 + EXTRAOFFSET // +44 - - #define OFFSET_CSDEATHS 493 + EXTRAOFFSET // +49 - #define OFFSET_SHIELD 559 + EXTRAOFFSET - // "weapon_*" entities - #define OFFSET_WEAPONTYPE 57 + EXTRAOFFSET // +14 - #define OFFSET_CLIPAMMO 65 + EXTRAOFFSET // +14 - #define OFFSET_SILENCER_FIREMODE 88 + EXTRAOFFSET // +14 - // "hostage_entity" entities - #define OFFSET_HOSTAGEFOLLOW 51 + EXTRAOFFSET // +21, long=51, int=107! (must use the long* offset because pointers on amd64 are stored the size of longs, 8 bytes, instead of the usual int 4 bytes.) - #define OFFSET_HOSTAGEID 516 + EXTRAOFFSET // +29 -#endif - -#if defined __linux__ -#define CS_DETOURCOPYBYTES_CLIENTCOMMAND 6 -#elif defined __APPLE__ -#define CS_DETOURCOPYBYTES_CLIENTCOMMAND 5 -#else -#define CS_DETOURCOPYBYTES_CLIENTCOMMAND 6 -#define CS_CLICMD_OFFS_USEBOTARGS 2 -#define CS_CLICMD_OFFS_BOTARGS 22 -#endif - - -// Ids of weapons in CS -#define CSW_P228 1 -//#define CSW_SHIELD 2 -#define CSW_SCOUT 3 -#define CSW_HEGRENADE 4 -#define CSW_XM1014 5 -#define CSW_C4 6 -#define CSW_MAC10 7 -#define CSW_AUG 8 -#define CSW_SMOKEGRENADE 9 -#define CSW_ELITE 10 -#define CSW_FIVESEVEN 11 -#define CSW_UMP45 12 -#define CSW_SG550 13 -#define CSW_GALI 14 -#define CSW_FAMAS 15 -#define CSW_USP 16 -#define CSW_GLOCK18 17 -#define CSW_AWP 18 -#define CSW_MP5NAVY 19 -#define CSW_M249 20 -#define CSW_M3 21 -#define CSW_M4A1 22 -#define CSW_TMP 23 -#define CSW_G3SG1 24 -#define CSW_FLASHBANG 25 -#define CSW_DEAGLE 26 -#define CSW_SG552 27 -#define CSW_AK47 28 -//#define CSW_KNIFE 29 -#define CSW_P90 30 -#define CSW_VEST 31 // Brand new invention! -#define CSW_VESTHELM 32 // Brand new invention! - -// These are used with armoury_entity:s. -#define CSA_MP5NAVY 0 -#define CSA_TMP 1 -#define CSA_P90 2 -#define CSA_MAC10 3 -#define CSA_AK47 4 -#define CSA_SG552 5 -#define CSA_M4A1 6 -#define CSA_AUG 7 -#define CSA_SCOUT 8 -#define CSA_G3SG1 9 -#define CSA_AWP 10 -#define CSA_M3 11 -#define CSA_XM1014 12 -#define CSA_M249 13 -#define CSA_FLASHBANG 14 -#define CSA_HEGRENADE 15 -#define CSA_VEST 16 -#define CSA_VESTHELM 17 -#define CSA_SMOKEGRENADE 18 - -#define M4A1_SILENCED (1<<2) -#define M4A1_ATTACHSILENCEANIM 6 -#define M4A1_DETACHSILENCEANIM 13 -#define USP_SILENCED (1<<0) -#define USP_ATTACHSILENCEANIM 7 -#define USP_DETACHSILENCEANIM 15 - -#define GLOCK_SEMIAUTOMATIC 0 -#define GLOCK_BURSTMODE 2 -#define FAMAS_AUTOMATIC 0 -#define FAMAS_BURSTMODE 16 - -#define PLAYER_IS_VIP (1<<8) - -#define PLAYER_IN_BUYZONE (1<<0) - -#define TEAM_UNASSIGNED 0 -#define TEAM_T 1 -#define TEAM_CT 2 -#define TEAM_SPECTATOR 3 - -#define CAN_PLANT_BOMB (1<<8) // 256 -#define HAS_DEFUSE_KIT (1<<16) // 65536 - -#define DEFUSER_COLOUR_R 0 -#define DEFUSER_COLOUR_G 160 -#define DEFUSER_COLOUR_B 0 - -#define HAS_NVGOGGLES (1<<0) - -#define SCOREATTRIB_NOTHING 0 -#define SCOREATTRIB_DEAD 1 -#define SCOREATTRIB_BOMB 2 // t only -#define SCOREATTRIB_VIP 4 // ct only - -#define AMD64_STATIONARY_NO 2 -#define AMD64_STATIONARY_YES 3 - -#define CS_ARMOR_NONE 0 -#define CS_ARMOR_KEVLAR 1 -#define CS_ARMOR_ASSAULTSUIT 2 - -#define CS_FIRST_ZOOM 0x28 -#define CS_SECOND_AWP_ZOOM 0xA -#define CS_SECOND_NONAWP_ZOOM 0xF -#define CS_AUGSG552_ZOOM 0x37 -#define CS_NO_ZOOM 0x5A - -enum CS_Internal_Models { - CS_DONTCHANGE = 0, - CS_CT_URBAN = 1, - CS_T_TERROR = 2, - CS_T_LEET = 3, - CS_T_ARCTIC = 4, - CS_CT_GSG9 = 5, - CS_CT_GIGN = 6, - CS_CT_SAS = 7, - CS_T_GUERILLA = 8, - CS_CT_VIP = 9, - CZ_T_MILITIA = 10, - CZ_CT_SPETSNAZ = 11 -}; - -enum -{ - CS_RESET_ZOOM = 0, - CS_SET_NO_ZOOM, - CS_SET_FIRST_ZOOM, - CS_SET_SECOND_ZOOM, - CS_SET_AUGSG552_ZOOM, -}; -// cstrike-specific defines above - extern CCstrikePlayer g_players[33]; extern int g_zooming[33]; extern bool g_precachedknife; diff --git a/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj b/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj index 7232ab8a..33702db6 100644 --- a/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj +++ b/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj @@ -142,6 +142,7 @@ + diff --git a/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj.filters b/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj.filters index b3e7ccc3..f0ca883d 100644 --- a/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj.filters +++ b/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj.filters @@ -52,6 +52,9 @@ Header Files + + Header Files + From d7b3b47aa47038bcfd71ae6fc2639cf1d0efc00a Mon Sep 17 00:00:00 2001 From: Arkshine Date: Wed, 28 May 2014 00:06:51 +0200 Subject: [PATCH 04/14] Cstrike: Import some memory tools from SourceMod --- AMBuildScript | 3 + dlls/cstrike/cstrike/AMBuilder | 3 + dlls/cstrike/cstrike/Makefile | 6 +- dlls/cstrike/cstrike/msvc10/cstrike.vcxproj | 11 +- .../cstrike/msvc10/cstrike.vcxproj.filters | 30 + public/memtools/CDetour/asm/asm.c | 419 +++++++++++ public/memtools/CDetour/asm/asm.h | 40 ++ public/memtools/CDetour/detourhelpers.h | 129 ++++ public/memtools/CDetour/detours.cpp | 231 ++++++ public/memtools/CDetour/detours.h | 361 ++++++++++ public/memtools/MemoryUtils.cpp | 657 ++++++++++++++++++ public/memtools/MemoryUtils.h | 89 +++ public/sm_memtable.h | 170 +++++ public/sm_symtable.h | 231 ++++++ 14 files changed, 2376 insertions(+), 4 deletions(-) create mode 100644 public/memtools/CDetour/asm/asm.c create mode 100644 public/memtools/CDetour/asm/asm.h create mode 100644 public/memtools/CDetour/detourhelpers.h create mode 100644 public/memtools/CDetour/detours.cpp create mode 100644 public/memtools/CDetour/detours.h create mode 100644 public/memtools/MemoryUtils.cpp create mode 100644 public/memtools/MemoryUtils.h create mode 100644 public/sm_memtable.h create mode 100644 public/sm_symtable.h diff --git a/AMBuildScript b/AMBuildScript index 038ac32b..506c5b43 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -225,6 +225,7 @@ class AMXXConfig(object): '-arch', 'i386', '-lstdc++', '-stdlib=libstdc++', + '-framework', 'CoreServices', ] cfg.cxxflags += ['-stdlib=libstdc++'] elif builder.target_platform == 'windows': @@ -238,7 +239,9 @@ class AMXXConfig(object): ] cfg.includes += [os.path.join(builder.buildPath, 'includes')] + cfg.includes += [os.path.join(builder.sourcePath, 'public')] cfg.includes += [os.path.join(builder.sourcePath, 'public', 'amtl')] + cfg.includes += [os.path.join(builder.sourcePath, 'public', 'memtools')] return # diff --git a/dlls/cstrike/cstrike/AMBuilder b/dlls/cstrike/cstrike/AMBuilder index 904ab6d6..5efeb1d0 100644 --- a/dlls/cstrike/cstrike/AMBuilder +++ b/dlls/cstrike/cstrike/AMBuilder @@ -9,6 +9,9 @@ binary.sources = [ 'CstrikePlayer.cpp', 'CstrikeNatives.cpp', 'CstrikeHacks.cpp', + '../../../public/memtools/MemoryUtils.cpp', + '../../../public/memtools/CDetour/detours.cpp', + '../../../public/memtools/CDetour/asm/asm.c', ] AMXX.modules += [builder.Add(binary)] diff --git a/dlls/cstrike/cstrike/Makefile b/dlls/cstrike/cstrike/Makefile index 61140da5..dae7b5ac 100755 --- a/dlls/cstrike/cstrike/Makefile +++ b/dlls/cstrike/cstrike/Makefile @@ -14,7 +14,9 @@ MM_ROOT = ../../../../metamod/metamod PROJECT = cstrike -OBJECTS = sdk/amxxmodule.cpp amxx_api.cpp CstrikePlayer.cpp CstrikeNatives.cpp CstrikeHacks.cpp +OBJECTS = sdk/amxxmodule.cpp amxx_api.cpp CstrikePlayer.cpp CstrikeNatives.cpp CstrikeHacks.cpp \ + ../../../public/memtools/MemoryUtils.cpp ../../../public/memtools/CDetour/detours.cpp \ + ../../../public/memtools/CDetour/asm/asm.c ############################################## ### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### @@ -29,7 +31,7 @@ CPP_OSX = clang LINK = -INCLUDE = -I. -I$(HLSDK) -I$(HLSDK)/common -I$(HLSDK)/dlls -I$(HLSDK)/engine -I$(HLSDK)/game_shared \ +INCLUDE = -I. -I../../../public -I../../../public/amtl -I$(HLSDK) -I$(HLSDK)/common -I$(HLSDK)/dlls -I$(HLSDK)/engine -I$(HLSDK)/game_shared \ -I$(HLSDK)/public -I$(MM_ROOT) -Isdk ################################################ diff --git a/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj b/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj index 33702db6..355ccb75 100644 --- a/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj +++ b/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj @@ -62,7 +62,7 @@ Disabled - ..\;..\sdk;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories) + ..\;..\..\..\..\public; ..\..\..\..\public\amtl;..\..\..\..\public\memtools;..\sdk;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;CSTRIKE_EXPORTS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug @@ -105,7 +105,7 @@ MaxSpeed OnlyExplicitInline - ..\;..\sdk;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories) + ..\;..\..\..\..\public; ..\..\..\..\public\amtl;..\..\..\..\public\memtools;..\sdk;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;CSTRIKE_EXPORTS;%(PreprocessorDefinitions) true MultiThreaded @@ -135,6 +135,9 @@ + + + @@ -142,6 +145,10 @@ + + + + diff --git a/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj.filters b/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj.filters index f0ca883d..c73b5ac0 100644 --- a/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj.filters +++ b/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj.filters @@ -18,6 +18,15 @@ {7be12e0f-47b1-4d7e-880c-83e5d1c378d1} + + {bbcd1d67-4670-423d-912f-695737e76bad} + + + {074d4da1-d1be-40ba-8417-1fc388d85568} + + + {4f3c4a13-065a-49b1-83a1-f646a3ec3678} + @@ -35,6 +44,15 @@ Source Files + + Memtools + + + Memtools\CDetour + + + Memtools\CDetour\asm + @@ -55,6 +73,18 @@ Header Files + + Memtools + + + Memtools\CDetour + + + Memtools\CDetour + + + Memtools\CDetour\asm + diff --git a/public/memtools/CDetour/asm/asm.c b/public/memtools/CDetour/asm/asm.c new file mode 100644 index 00000000..f415f21b --- /dev/null +++ b/public/memtools/CDetour/asm/asm.c @@ -0,0 +1,419 @@ +#include "asm.h" + +#ifndef WIN32 +#define _GNU_SOURCE +#include +#include + +#define REG_EAX 0 +#define REG_ECX 1 +#define REG_EDX 2 +#define REG_EBX 3 + +#define IA32_MOV_REG_IMM 0xB8 // encoding is +r +#endif + +/** +* Checks if a call to a fpic thunk has just been written into dest. +* If found replaces it with a direct mov that sets the required register to the value of pc. +* +* @param dest Destination buffer where a call opcode + addr (5 bytes) has just been written. +* @param pc The program counter value that needs to be set (usually the next address from the source). +* @noreturn +*/ +void check_thunks(unsigned char *dest, unsigned char *pc) +{ +#if defined WIN32 + return; +#else + /* Step write address back 4 to the start of the function address */ + unsigned char *writeaddr = dest - 4; + unsigned char *calloffset = *(unsigned char **)writeaddr; + unsigned char *calladdr = (unsigned char *)(dest + (unsigned int)calloffset); + + /* Lookup name of function being called */ + if ((*calladdr == 0x8B) && (*(calladdr+2) == 0x24) && (*(calladdr+3) == 0xC3)) + { + //a thunk maybe? + char movByte = IA32_MOV_REG_IMM; + + /* Calculate the correct mov opcode */ + switch (*(calladdr+1)) + { + case 0x04: + { + movByte += REG_EAX; + break; + } + case 0x1C: + { + movByte += REG_EBX; + break; + } + case 0x0C: + { + movByte += REG_ECX; + break; + } + case 0x14: + { + movByte += REG_EDX; + break; + } + default: + { + //Msg("Unknown thunk: %c\n", *(calladdr+1)); + break; + } + } + + /* Move our write address back one to where the call opcode was */ + writeaddr--; + + + /* Write our mov */ + *writeaddr = movByte; + writeaddr++; + + /* Write the value - The provided program counter value */ + *(void **)writeaddr = (void *)pc; + writeaddr += 4; + } + + return; +#endif +} + +//if dest is NULL, returns minimum number of bytes needed to be copied +//if dest is not NULL, it will copy the bytes to dest as well as fix CALLs and JMPs +//http://www.devmaster.net/forums/showthread.php?t=2311 +int copy_bytes(unsigned char *func, unsigned char* dest, int required_len) { + int bytecount = 0; + + while(bytecount < required_len && *func != 0xCC) + { + // prefixes F0h, F2h, F3h, 66h, 67h, D8h-DFh, 2Eh, 36h, 3Eh, 26h, 64h and 65h + int operandSize = 4; + int FPU = 0; + int twoByte = 0; + unsigned char opcode = 0x90; + unsigned char modRM = 0xFF; + while(*func == 0xF0 || + *func == 0xF2 || + *func == 0xF3 || + (*func & 0xFC) == 0x64 || + (*func & 0xF8) == 0xD8 || + (*func & 0x7E) == 0x62) + { + if(*func == 0x66) + { + operandSize = 2; + } + else if((*func & 0xF8) == 0xD8) + { + FPU = *func; + if (dest) + *dest++ = *func++; + else + func++; + bytecount++; + break; + } + + if (dest) + *dest++ = *func++; + else + func++; + bytecount++; + } + + // two-byte opcode byte + if(*func == 0x0F) + { + twoByte = 1; + if (dest) + *dest++ = *func++; + else + func++; + bytecount++; + } + + // opcode byte + opcode = *func++; + if (dest) *dest++ = opcode; + bytecount++; + + // mod R/M byte + modRM = 0xFF; + if(FPU) + { + if((opcode & 0xC0) != 0xC0) + { + modRM = opcode; + } + } + else if(!twoByte) + { + if((opcode & 0xC4) == 0x00 || + ((opcode & 0xF4) == 0x60 && ((opcode & 0x0A) == 0x02 || (opcode & 0x09) == 0x09)) || + (opcode & 0xF0) == 0x80 || + ((opcode & 0xF8) == 0xC0 && (opcode & 0x0E) != 0x02) || + (opcode & 0xFC) == 0xD0 || + (opcode & 0xF6) == 0xF6) + { + modRM = *func++; + if (dest) *dest++ = modRM; + bytecount++; + } + } + else + { + if(((opcode & 0xF0) == 0x00 && (opcode & 0x0F) >= 0x04 && (opcode & 0x0D) != 0x0D) || + (opcode & 0xF0) == 0x30 || + opcode == 0x77 || + (opcode & 0xF0) == 0x80 || + ((opcode & 0xF0) == 0xA0 && (opcode & 0x07) <= 0x02) || + (opcode & 0xF8) == 0xC8) + { + // No mod R/M byte + } + else + { + modRM = *func++; + if (dest) *dest++ = modRM; + bytecount++; + } + } + + // SIB + if((modRM & 0x07) == 0x04 && + (modRM & 0xC0) != 0xC0) + { + if (dest) + *dest++ = *func++; //SIB + else + func++; + bytecount++; + } + + // mod R/M displacement + + // Dword displacement, no base + if((modRM & 0xC5) == 0x05) { + if (dest) { + *(unsigned int*)dest = *(unsigned int*)func; + dest += 4; + } + func += 4; + bytecount += 4; + } + + // Byte displacement + if((modRM & 0xC0) == 0x40) { + if (dest) + *dest++ = *func++; + else + func++; + bytecount++; + } + + // Dword displacement + if((modRM & 0xC0) == 0x80) { + if (dest) { + *(unsigned int*)dest = *(unsigned int*)func; + dest += 4; + } + func += 4; + bytecount += 4; + } + + // immediate + if(FPU) + { + // Can't have immediate operand + } + else if(!twoByte) + { + if((opcode & 0xC7) == 0x04 || + (opcode & 0xFE) == 0x6A || // PUSH/POP/IMUL + (opcode & 0xF0) == 0x70 || // Jcc + opcode == 0x80 || + opcode == 0x83 || + (opcode & 0xFD) == 0xA0 || // MOV + opcode == 0xA8 || // TEST + (opcode & 0xF8) == 0xB0 || // MOV + (opcode & 0xFE) == 0xC0 || // RCL + opcode == 0xC6 || // MOV + opcode == 0xCD || // INT + (opcode & 0xFE) == 0xD4 || // AAD/AAM + (opcode & 0xF8) == 0xE0 || // LOOP/JCXZ + opcode == 0xEB || + (opcode == 0xF6 && (modRM & 0x30) == 0x00)) // TEST + { + if (dest) + *dest++ = *func++; + else + func++; + bytecount++; + } + else if((opcode & 0xF7) == 0xC2) // RET + { + if (dest) { + *(unsigned short*)dest = *(unsigned short*)func; + dest += 2; + } + func += 2; + bytecount += 2; + } + else if((opcode & 0xFC) == 0x80 || + (opcode & 0xC7) == 0x05 || + (opcode & 0xF8) == 0xB8 || + (opcode & 0xFE) == 0xE8 || // CALL/Jcc + (opcode & 0xFE) == 0x68 || + (opcode & 0xFC) == 0xA0 || + (opcode & 0xEE) == 0xA8 || + opcode == 0xC7 || + (opcode == 0xF7 && (modRM & 0x30) == 0x00)) + { + if (dest) { + //Fix CALL/JMP offset + if ((opcode & 0xFE) == 0xE8) { + if (operandSize == 4) + { + *(long*)dest = ((func + *(long*)func) - dest); + + //pRED* edit. func is the current address of the call address, +4 is the next instruction, so the value of $pc + check_thunks(dest+4, func+4); + } + else + *(short*)dest = ((func + *(short*)func) - dest); + + } else { + if (operandSize == 4) + *(unsigned long*)dest = *(unsigned long*)func; + else + *(unsigned short*)dest = *(unsigned short*)func; + } + dest += operandSize; + } + func += operandSize; + bytecount += operandSize; + + } + } + else + { + if(opcode == 0xBA || // BT + opcode == 0x0F || // 3DNow! + (opcode & 0xFC) == 0x70 || // PSLLW + (opcode & 0xF7) == 0xA4 || // SHLD + opcode == 0xC2 || + opcode == 0xC4 || + opcode == 0xC5 || + opcode == 0xC6) + { + if (dest) + *dest++ = *func++; + else + func++; + } + else if((opcode & 0xF0) == 0x80) // Jcc -i + { + if (dest) { + if (operandSize == 4) + *(unsigned long*)dest = *(unsigned long*)func; + else + *(unsigned short*)dest = *(unsigned short*)func; + + dest += operandSize; + } + func += operandSize; + bytecount += operandSize; + } + } + } + + return bytecount; +} + +//insert a specific JMP instruction at the given location +void inject_jmp(void* src, void* dest) { + *(unsigned char*)src = OP_JMP; + *(long*)((unsigned char*)src+1) = (long)((unsigned char*)dest - ((unsigned char*)src + OP_JMP_SIZE)); +} + +//fill a given block with NOPs +void fill_nop(void* src, unsigned int len) { + unsigned char* src2 = (unsigned char*)src; + while (len) { + *src2++ = OP_NOP; + --len; + } +} + +void* eval_jump(void* src) { + unsigned char* addr = (unsigned char*)src; + + if (!addr) return 0; + + //import table jump + if (addr[0] == OP_PREFIX && addr[1] == OP_JMP_SEG) { + addr += 2; + addr = *(unsigned char**)addr; + //TODO: if addr points into the IAT + return *(void**)addr; + } + + //8bit offset + else if (addr[0] == OP_JMP_BYTE) { + addr = &addr[OP_JMP_BYTE_SIZE] + *(char*)&addr[1]; + //mangled 32bit jump? + if (addr[0] == OP_JMP) { + addr = addr + *(int*)&addr[1]; + } + return addr; + } + /* + //32bit offset + else if (addr[0] == OP_JMP) { + addr = &addr[OP_JMP_SIZE] + *(int*)&addr[1]; + } + */ + + return addr; +} +/* +from ms detours package +static bool detour_is_imported(PBYTE pbCode, PBYTE pbAddress) +{ + MEMORY_BASIC_INFORMATION mbi; + VirtualQuery((PVOID)pbCode, &mbi, sizeof(mbi)); + __try { + PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)mbi.AllocationBase; + if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { + return false; + } + + PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader + + pDosHeader->e_lfanew); + if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { + return false; + } + + if (pbAddress >= ((PBYTE)pDosHeader + + pNtHeader->OptionalHeader + .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress) && + pbAddress < ((PBYTE)pDosHeader + + pNtHeader->OptionalHeader + .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress + + pNtHeader->OptionalHeader + .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size)) { + return true; + } + return false; + } + __except(EXCEPTION_EXECUTE_HANDLER) { + return false; + } +} +*/ diff --git a/public/memtools/CDetour/asm/asm.h b/public/memtools/CDetour/asm/asm.h new file mode 100644 index 00000000..838e6916 --- /dev/null +++ b/public/memtools/CDetour/asm/asm.h @@ -0,0 +1,40 @@ +#ifndef __ASM_H__ +#define __ASM_H__ + +#define OP_JMP 0xE9 +#define OP_JMP_SIZE 5 + +#define OP_NOP 0x90 +#define OP_NOP_SIZE 1 + +#define OP_PREFIX 0xFF +#define OP_JMP_SEG 0x25 + +#define OP_JMP_BYTE 0xEB +#define OP_JMP_BYTE_SIZE 2 + +#ifdef __cplusplus +extern "C" { +#endif + +void check_thunks(unsigned char *dest, unsigned char *pc); + +//if dest is NULL, returns minimum number of bytes needed to be copied +//if dest is not NULL, it will copy the bytes to dest as well as fix CALLs and JMPs +//http://www.devmaster.net/forums/showthread.php?t=2311 +int copy_bytes(unsigned char *func, unsigned char* dest, int required_len); + +//insert a specific JMP instruction at the given location +void inject_jmp(void* src, void* dest); + +//fill a given block with NOPs +void fill_nop(void* src, unsigned int len); + +//evaluate a JMP at the target +void* eval_jump(void* src); + +#ifdef __cplusplus +} +#endif + +#endif //__ASM_H__ diff --git a/public/memtools/CDetour/detourhelpers.h b/public/memtools/CDetour/detourhelpers.h new file mode 100644 index 00000000..291d8df2 --- /dev/null +++ b/public/memtools/CDetour/detourhelpers.h @@ -0,0 +1,129 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id: detourhelpers.h 248 2008-08-27 00:56:22Z pred $ + */ + +#ifndef _INCLUDE_SOURCEMOD_DETOURHELPERS_H_ +#define _INCLUDE_SOURCEMOD_DETOURHELPERS_H_ + +#if defined(__linux__) || defined(__APPLE__) + #include + #ifndef PAGE_SIZE + #define PAGE_SIZE 4096 + #endif + #define ALIGN(ar) ((long)ar & ~(PAGE_SIZE-1)) + #define PAGE_EXECUTE_READWRITE PROT_READ|PROT_WRITE|PROT_EXEC + #if defined(__linux) + #include + #endif +#elif defined(WIN32) + #include +#endif + +struct patch_t +{ + patch_t() + { + patch[0] = 0; + bytes = 0; + } + unsigned char patch[20]; + size_t bytes; +}; + +inline void ProtectMemory(void *addr, int length, int prot) +{ +#if defined(__linux__) || defined(__APPLE__) + void *addr2 = (void *)ALIGN(addr); + mprotect(addr2, sysconf(_SC_PAGESIZE), prot); +#elif defined(WIN32) + DWORD old_prot; + VirtualProtect(addr, length, prot, &old_prot); +#endif +} + +inline unsigned char *AllocatePageMemory(size_t size) +{ +#if defined WIN32 + return (unsigned char *)VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); +#elif defined __GNUC__ +#if defined __APPLE__ + unsigned char *addr = (unsigned char *)valloc(size); +#else + unsigned char *addr = (unsigned char *)memalign(sysconf(_SC_PAGESIZE), size); +#endif + mprotect(addr, size, PROT_READ | PROT_WRITE | PROT_EXEC); + return addr; +#endif +} + +inline void FreePageMemory(void *addr) +{ +#if defined(WIN32) + VirtualFree(addr, 0, MEM_RELEASE); +#else + free(addr); +#endif +} + +inline void SetMemPatchable(void *address, size_t size) +{ + ProtectMemory(address, (int)size, PAGE_EXECUTE_READWRITE); +} + +inline void DoGatePatch(unsigned char *target, void *callback) +{ + SetMemPatchable(target, 20); + + target[0] = 0xFF; /* JMP */ + target[1] = 0x25; /* MEM32 */ + *(void **)(&target[2]) = callback; +} + +inline void ApplyPatch(void *address, int offset, const patch_t *patch, patch_t *restore) +{ + ProtectMemory(address, 20, PAGE_EXECUTE_READWRITE); + + unsigned char *addr = (unsigned char *)address + offset; + if (restore) + { + for (size_t i=0; ibytes; i++) + { + restore->patch[i] = addr[i]; + } + restore->bytes = patch->bytes; + } + + for (size_t i=0; ibytes; i++) + { + addr[i] = patch->patch[i]; + } +} + +#endif //_INCLUDE_SOURCEMOD_DETOURHELPERS_H_ diff --git a/public/memtools/CDetour/detours.cpp b/public/memtools/CDetour/detours.cpp new file mode 100644 index 00000000..2bd1fcb4 --- /dev/null +++ b/public/memtools/CDetour/detours.cpp @@ -0,0 +1,231 @@ +/** +* vim: set ts=4 : +* ============================================================================= +* SourceMod +* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. +* ============================================================================= +* +* This program is free software; you can redistribute it and/or modify it under +* the terms of the GNU General Public License, version 3.0, as published by the +* Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +* details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see . +* +* As a special exception, AlliedModders LLC gives you permission to link the +* code of this program (as well as its derivative works) to "Half-Life 2," the +* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software +* by the Valve Corporation. You must obey the GNU General Public License in +* all respects for all other code used. Additionally, AlliedModders LLC grants +* this exception to all derivative works. AlliedModders LLC defines further +* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), +* or . +* +* Version: $Id: detours.cpp 248 2008-08-27 00:56:22Z pred $ +*/ + +#include "detours.h" +#include "asm/asm.h" + +//ISourcePawnEngine *CDetourManager::spengine = NULL; +//IGameConfig *CDetourManager::gameconf = NULL; + +void CDetourManager::Init(/*ISourcePawnEngine *spengine, IGameConfig *gameconf*/) +{ + //CDetourManager::spengine = spengine; + //CDetourManager::gameconf = gameconf; +} + +CDetour *CDetourManager::CreateDetour(void *callbackfunction, void **trampoline, const char *signame) +{ + CDetour *detour = new CDetour(callbackfunction, trampoline, signame); + if (detour) + { + if (!detour->Init(/*spengine, gameconf*/)) + { + delete detour; + return NULL; + } + + return detour; + } + + return NULL; +} + +CDetour *CDetourManager::CreateDetour(void *callbackfunction, void **trampoline, void *address) +{ + CDetour *detour = new CDetour(callbackfunction, trampoline, address); + if (detour) + { + if (!detour->Init(/*spengine, gameconf*/)) + { + delete detour; + return NULL; + } + + return detour; + } + + return NULL; +} + + +CDetour::CDetour(void *callbackfunction, void **trampoline, const char *signame) +{ + enabled = false; + detoured = false; + detour_address = NULL; + detour_trampoline = NULL; + this->signame = signame; + this->detour_callback = callbackfunction; + this->address = NULL; + //spengine = NULL; + //gameconf = NULL; + this->trampoline = trampoline; +} + +CDetour::CDetour(void *callbackfunction, void **trampoline, void *address) +{ + enabled = false; + detoured = false; + detour_address = address; + detour_trampoline = NULL; + this->signame = NULL; + this->detour_callback = callbackfunction; + this->address = address; + //spengine = NULL; + //gameconf = NULL; + this->trampoline = trampoline; +} + + +bool CDetour::Init(/*ISourcePawnEngine *spengine, IGameConfig *gameconf*/) +{ + //this->spengine = spengine; + //this->gameconf = gameconf; + + if (!CreateDetour()) + { + enabled = false; + return enabled; + } + + enabled = true; + + return enabled; +} + +void CDetour::Destroy() +{ + DeleteDetour(); + delete this; +} + +bool CDetour::IsEnabled() +{ + return enabled; +} + +bool CDetour::CreateDetour() +{ + /*if (signame != NULL && !gameconf->GetMemSig(signame, &detour_address)) + { + g_pSM->LogError(myself, "Could not locate %s - Disabling detour", signame); + return false; + }*/ + + if (address != NULL) + { + detour_address = address; + } + + if (!detour_address) + { + //g_pSM->LogError(myself, "Sigscan for %s failed - Disabling detour to prevent crashes", signame); + return false; + } + + detour_restore.bytes = copy_bytes((unsigned char *)detour_address, NULL, OP_JMP_SIZE+1); + + /* First, save restore bits */ + for (size_t i=0; iSetReadWrite(wr.outbase); + wr.outptr = wr.outbase; + detour_trampoline = wr.outbase; + goto jit_rewind; + } + + //spengine->SetReadExecute(wr.outbase); + + *trampoline = detour_trampoline; + + return true; +} + +void CDetour::DeleteDetour() +{ + if (detoured) + { + DisableDetour(); + } + + if (detour_trampoline) + { + /* Free the allocated trampoline memory */ + FreePageMemory(detour_trampoline); + detour_trampoline = NULL; + } +} + +void CDetour::EnableDetour() +{ + if (!detoured) + { + DoGatePatch((unsigned char *)detour_address, &detour_callback); + detoured = true; + } +} + +void CDetour::DisableDetour() +{ + if (detoured) + { + /* Remove the patch */ + ApplyPatch(detour_address, 0, &detour_restore, NULL); + detoured = false; + } +} diff --git a/public/memtools/CDetour/detours.h b/public/memtools/CDetour/detours.h new file mode 100644 index 00000000..797cb1c8 --- /dev/null +++ b/public/memtools/CDetour/detours.h @@ -0,0 +1,361 @@ +/** +* vim: set ts=4 : +* ============================================================================= +* SourceMod +* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. +* ============================================================================= +* +* This program is free software; you can redistribute it and/or modify it under +* the terms of the GNU General Public License, version 3.0, as published by the +* Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +* details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see . +* +* As a special exception, AlliedModders LLC gives you permission to link the +* code of this program (as well as its derivative works) to "Half-Life 2," the +* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software +* by the Valve Corporation. You must obey the GNU General Public License in +* all respects for all other code used. Additionally, AlliedModders LLC grants +* this exception to all derivative works. AlliedModders LLC defines further +* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), +* or . +* +* Version: $Id: detours.h 257 2008-09-23 03:12:13Z pred $ +*/ + +#ifndef _INCLUDE_SOURCEMOD_DETOURS_H_ +#define _INCLUDE_SOURCEMOD_DETOURS_H_ + +#include "amxxmodule.h" +//#include +//#include +#include "detourhelpers.h" + +/** + * CDetours class for SourceMod Extensions by pRED* + * detourhelpers.h entirely stolen from CSS:DM and were written by BAILOPAN (I assume). + * asm.h/c from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -fPIC thunks correctly + * Concept by Nephyrin Zey (http://www.doublezen.net/) and Windows Detour Library (http://research.microsoft.com/sn/detours/) + * Member function pointer ideas by Don Clugston (http://www.codeproject.com/cpp/FastDelegate.asp) + */ + +#define DETOUR_MEMBER_CALL(name) (this->*name##_Actual) +#define DETOUR_STATIC_CALL(name) (name##_Actual) + +#define DETOUR_DECL_STATIC0(name, ret) \ +ret (*name##_Actual)(void) = NULL; \ +ret name(void) + +#define DETOUR_DECL_STATIC1(name, ret, p1type, p1name) \ +ret (*name##_Actual)(p1type) = NULL; \ +ret name(p1type p1name) + +#define DETOUR_DECL_STATIC4(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name) \ +ret (*name##_Actual)(p1type, p2type, p3type, p4type) = NULL; \ +ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name) + +#define DETOUR_DECL_MEMBER0(name, ret) \ +class name##Class \ +{ \ +public: \ + ret name(); \ + static ret (name##Class::* name##_Actual)(void); \ +}; \ +ret (name##Class::* name##Class::name##_Actual)(void) = NULL; \ +ret name##Class::name() + +#define DETOUR_DECL_MEMBER1(name, ret, p1type, p1name) \ +class name##Class \ +{ \ +public: \ + ret name(p1type p1name); \ + static ret (name##Class::* name##_Actual)(p1type); \ +}; \ +ret (name##Class::* name##Class::name##_Actual)(p1type) = NULL; \ +ret name##Class::name(p1type p1name) + +#define DETOUR_DECL_MEMBER2(name, ret, p1type, p1name, p2type, p2name) \ +class name##Class \ +{ \ +public: \ + ret name(p1type p1name, p2type p2name); \ + static ret (name##Class::* name##_Actual)(p1type, p2type); \ +}; \ +ret (name##Class::* name##Class::name##_Actual)(p1type, p2type) = NULL; \ +ret name##Class::name(p1type p1name, p2type p2name) + +#define DETOUR_DECL_MEMBER3(name, ret, p1type, p1name, p2type, p2name, p3type, p3name) \ +class name##Class \ +{ \ +public: \ + ret name(p1type p1name, p2type p2name, p3type p3name); \ + static ret (name##Class::* name##_Actual)(p1type, p2type, p3type); \ +}; \ +ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type) = NULL; \ +ret name##Class::name(p1type p1name, p2type p2name, p3type p3name) + +#define DETOUR_DECL_MEMBER4(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name) \ +class name##Class \ +{ \ +public: \ + ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name); \ + static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type); \ +}; \ +ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type) = NULL; \ +ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name) + +#define DETOUR_DECL_MEMBER8(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name, p7type, p7name, p8type, p8name) \ +class name##Class \ +{ \ +public: \ + ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name); \ + static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type); \ +}; \ +ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type) = NULL; \ +ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name) + + +#define GET_MEMBER_CALLBACK(name) (void *)GetCodeAddress(&name##Class::name) +#define GET_MEMBER_TRAMPOLINE(name) (void **)(&name##Class::name##_Actual) + +#define GET_STATIC_CALLBACK(name) (void *)&name +#define GET_STATIC_TRAMPOLINE(name) (void **)&name##_Actual + +#define DETOUR_CREATE_MEMBER(name, gamedata, target) CDetourManager::CreateDetour(GET_MEMBER_CALLBACK(name), GET_MEMBER_TRAMPOLINE(name), gamedata, target); +#define DETOUR_CREATE_STATIC(name, gamedata, target) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), gamedata, target); +#define DETOUR_CREATE_STATIC_FIXED(name, address) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), address); + +class GenericClass {}; +typedef void (GenericClass::*VoidFunc)(); + +inline void *GetCodeAddr(VoidFunc mfp) +{ + return *(void **)&mfp; +} + +/** + * Converts a member function pointer to a void pointer. + * This relies on the assumption that the code address lies at mfp+0 + * This is the case for both g++ and later MSVC versions on non virtual functions but may be different for other compilers + * Based on research by Don Clugston : http://www.codeproject.com/cpp/FastDelegate.asp + */ +#define GetCodeAddress(mfp) GetCodeAddr(reinterpret_cast(mfp)) + +class CDetourManager; + +class CDetour +{ +public: + + bool IsEnabled(); + + /** + * These would be somewhat self-explanatory I hope + */ + void EnableDetour(); + void DisableDetour(); + + void Destroy(); + + friend class CDetourManager; + +protected: + CDetour(void *callbackfunction, void **trampoline, const char *signame); + CDetour(void *callbackfunction, void **trampoline, void *address); + + bool Init(); +private: + + /* These create/delete the allocated memory */ + bool CreateDetour(); + void DeleteDetour(); + + bool enabled; + bool detoured; + + patch_t detour_restore; + /* Address of the detoured function */ + void *detour_address; + /* Address of the allocated trampoline function */ + void *detour_trampoline; + /* Address of the callback handler */ + void *detour_callback; + /* The function pointer used to call our trampoline */ + void **trampoline; + + const char *signame; + void *address; +}; + +class CDetourManager +{ +public: + + static void Init(); + + /** + * Creates a new detour + * + * @param callbackfunction Void pointer to your detour callback function. + * @param trampoline Address of the trampoline pointer + * @param signame Section name containing a signature to fetch from the gamedata file. + * @return A new CDetour pointer to control your detour. + * + * Example: + * + * CBaseServer::ConnectClient(netadr_s &, int, int, int, char const*, char const*, char const*, int) + * + * Define a new class with the required function and a member function pointer to the same type: + * + * class CBaseServerDetour + * { + * public: + * bool ConnectClient(void *netaddr_s, int, int, int, char const*, char const*, char const*, int); + * static bool (CBaseServerDetour::* ConnectClient_Actual)(void *netaddr_s, int, int, int, char const*, char const*, char const*, int); + * } + * + * void *callbackfunc = GetCodeAddress(&CBaseServerDetour::ConnectClient); + * void **trampoline = (void **)(&CBaseServerDetour::ConnectClient_Actual); + * + * Creation: + * CDetourManager::CreateDetour(callbackfunc, trampoline, "ConnectClient"); + * + * Usage: + * + * CBaseServerDetour::ConnectClient(void *netaddr_s, int, int, int, char const*, char const*, char const*, int) + * { + * //pre hook code + * bool result = (this->*ConnectClient_Actual)(netaddr_s, rest of params); + * //post hook code + * return result; + * } + * + * Note we changed the netadr_s reference into a void* to avoid needing to define the type + */ + static CDetour *CreateDetour(void *callbackfunction, void **trampoline, const char *signame); + static CDetour *CreateDetour(void *callbackfunction, void **trampoline, void *address); + + friend class CBlocker; + friend class CDetour; + +/*private: + static ISourcePawnEngine *spengine; + static IGameConfig *gameconf;*/ +}; + + +// Helpers from jit_helpers.h/x86_macros.h. + +class JitWriter +{ +public: + inline cell read_cell() + { + cell val = *(inptr); + inptr++; + return val; + } + inline cell peek_cell() + { + return *inptr; + } + inline cell *read_cellptr() + { + cell *val = *(cell **)(inptr); + inptr++; + return val; + } + inline void write_ubyte(unsigned char c) + { + if (outbase) + { + *outptr = c; + } + outptr++; + } + inline void write_ushort(unsigned short c) + { + if (outbase) + { + *(unsigned short *)outptr = c; + } + outptr += sizeof(unsigned short); + } + inline void write_byte(char c) + { + if (outbase) + { + *outptr = c; + } + outptr++; + } + inline void write_int32(int c) + { + if (outbase) + { + *(int *)outptr = c; + } + outptr += sizeof(int); + } + inline void write_uint32(unsigned int c) + { + if (outbase) + { + *(unsigned int *)outptr = c; + } + outptr += sizeof(unsigned int); + } + inline unsigned int get_outputpos() + { + return (outptr - outbase); + } + inline void set_outputpos(unsigned int offs) + { + outptr = outbase + offs; + } + inline unsigned int get_inputpos() + { + return (unsigned int)((char *)inptr - (char *)inbase); + } +public: + cell *inptr; /* input pointer */ + cell *inbase; /* input base */ + char *outbase; /* output pointer */ + char *outptr; /* output base */ +}; + +#define IA32_JMP_IMM32 0xE9 // encoding is imm32 + +inline unsigned int IA32_Jump_Imm32(JitWriter *jit, int disp) +{ + unsigned int ptr; + jit->write_ubyte(IA32_JMP_IMM32); + ptr = jit->get_outputpos(); + jit->write_int32(disp); + return ptr; +} + +/** +* Corrects a jump using an absolute offset, not a relative one. +*/ +inline void IA32_Write_Jump32_Abs(JitWriter *jit, unsigned int jmp, void *target) +{ + //save old ptr + char *oldptr = jit->outptr; + //get relative difference + long diff = ((long)target - ((long)jit->outbase + jmp + 4)); + //overwrite old value + jit->outptr = jit->outbase + jmp; + jit->write_int32(diff); + //restore old ptr + jit->outptr = oldptr; +} + + +#endif // _INCLUDE_SOURCEMOD_DETOURS_H_ diff --git a/public/memtools/MemoryUtils.cpp b/public/memtools/MemoryUtils.cpp new file mode 100644 index 00000000..843d0f6f --- /dev/null +++ b/public/memtools/MemoryUtils.cpp @@ -0,0 +1,657 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2011 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + */ + +#include "MemoryUtils.h" +#include + +#if defined(__linux__) + #include + #include + #include + #include + #include + #include + + #define PAGE_SIZE 4096 + #define PAGE_ALIGN_UP(x) ((x + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) +#endif + +#if defined(__APPLE__) + #include + #include + #include + #include + #include + #include + + /* Define things from 10.6 SDK for older SDKs */ + #ifndef MAC_OS_X_VERSION_10_6 + struct task_dyld_info + { + mach_vm_address_t all_image_info_addr; + mach_vm_size_t all_image_info_size; + }; + typedef struct task_dyld_info task_dyld_info_data_t; + #define TASK_DYLD_INFO 17 + #define TASK_DYLD_INFO_COUNT (sizeof(task_dyld_info_data_t) / sizeof(natural_t)) + #endif // MAC_OS_X_VERSION_10_6 +#endif // __APPLE__ + + + +MemoryUtils g_MemUtils; + +MemoryUtils::MemoryUtils() +{ +#if defined(__APPLE__) + Gestalt(gestaltSystemVersionMajor, &m_OSXMajor); + Gestalt(gestaltSystemVersionMinor, &m_OSXMinor); + + /* Get pointer to struct that describes all loaded mach-o images in process */ + if ((m_OSXMajor == 10 && m_OSXMinor >= 6) || m_OSXMajor > 10) + { + task_dyld_info_data_t dyld_info; + mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; + task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&dyld_info, &count); + m_ImageList = (struct dyld_all_image_infos *)dyld_info.all_image_info_addr; + } + else + { + struct nlist list[2]; + memset(list, 0, sizeof(list)); + list[0].n_un.n_name = (char *)"_dyld_all_image_infos"; + nlist("/usr/lib/dyld", list); + m_ImageList = (struct dyld_all_image_infos *)list[0].n_value; + } +#endif +} + +MemoryUtils::~MemoryUtils() +{ +#if defined(__linux__) || defined(__APPLE__) + for (size_t i = 0; i < m_SymTables.length(); i++) + { + delete m_SymTables[i]; + } + m_SymTables.clear(); +#endif +} + +void *MemoryUtils::FindPattern(const void *libPtr, const char *pattern, size_t len) +{ + DynLibInfo lib; + bool found; + char *ptr, *end; + + memset(&lib, 0, sizeof(DynLibInfo)); + + if (!GetLibraryInfo(libPtr, lib)) + { + return NULL; + } + + ptr = reinterpret_cast(lib.baseAddress); + end = ptr + lib.memorySize - len; + + while (ptr < end) + { + found = true; + for (register size_t i = 0; i < len; i++) + { + if (pattern[i] != '\x2A' && pattern[i] != ptr[i]) + { + found = false; + break; + } + } + + if (found) + return ptr; + + ptr++; + } + + return NULL; +} + +void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol) +{ +#if defined(WIN32) + + return GetProcAddress((HMODULE)handle, symbol); + +#elif defined(__linux__) + + struct link_map *dlmap; + struct stat dlstat; + int dlfile; + uintptr_t map_base; + Elf32_Ehdr *file_hdr; + Elf32_Shdr *sections, *shstrtab_hdr, *symtab_hdr, *strtab_hdr; + Elf32_Sym *symtab; + const char *shstrtab, *strtab; + uint16_t section_count; + uint32_t symbol_count; + LibSymbolTable *libtable; + SymbolTable *table; + Symbol *symbol_entry; + + dlmap = (struct link_map *)handle; + symtab_hdr = NULL; + strtab_hdr = NULL; + table = NULL; + + /* See if we already have a symbol table for this library */ + for (size_t i = 0; i < m_SymTables.length(); i++) + { + libtable = m_SymTables[i]; + if (libtable->lib_base == dlmap->l_addr) + { + table = &libtable->table; + break; + } + } + + /* If we don't have a symbol table for this library, then create one */ + if (table == NULL) + { + libtable = new LibSymbolTable(); + libtable->table.Initialize(); + libtable->lib_base = dlmap->l_addr; + libtable->last_pos = 0; + table = &libtable->table; + m_SymTables.append(libtable); + } + + /* See if the symbol is already cached in our table */ + symbol_entry = table->FindSymbol(symbol, strlen(symbol)); + if (symbol_entry != NULL) + { + return symbol_entry->address; + } + + /* If symbol isn't in our table, then we have open the actual library */ + dlfile = open(dlmap->l_name, O_RDONLY); + if (dlfile == -1 || fstat(dlfile, &dlstat) == -1) + { + close(dlfile); + return NULL; + } + + /* Map library file into memory */ + file_hdr = (Elf32_Ehdr *)mmap(NULL, dlstat.st_size, PROT_READ, MAP_PRIVATE, dlfile, 0); + map_base = (uintptr_t)file_hdr; + if (file_hdr == MAP_FAILED) + { + close(dlfile); + return NULL; + } + close(dlfile); + + if (file_hdr->e_shoff == 0 || file_hdr->e_shstrndx == SHN_UNDEF) + { + munmap(file_hdr, dlstat.st_size); + return NULL; + } + + sections = (Elf32_Shdr *)(map_base + file_hdr->e_shoff); + section_count = file_hdr->e_shnum; + /* Get ELF section header string table */ + shstrtab_hdr = §ions[file_hdr->e_shstrndx]; + shstrtab = (const char *)(map_base + shstrtab_hdr->sh_offset); + + /* Iterate sections while looking for ELF symbol table and string table */ + for (uint16_t i = 0; i < section_count; i++) + { + Elf32_Shdr &hdr = sections[i]; + const char *section_name = shstrtab + hdr.sh_name; + + if (strcmp(section_name, ".symtab") == 0) + { + symtab_hdr = &hdr; + } + else if (strcmp(section_name, ".strtab") == 0) + { + strtab_hdr = &hdr; + } + } + + /* Uh oh, we don't have a symbol table or a string table */ + if (symtab_hdr == NULL || strtab_hdr == NULL) + { + munmap(file_hdr, dlstat.st_size); + return NULL; + } + + symtab = (Elf32_Sym *)(map_base + symtab_hdr->sh_offset); + strtab = (const char *)(map_base + strtab_hdr->sh_offset); + symbol_count = symtab_hdr->sh_size / symtab_hdr->sh_entsize; + + /* Iterate symbol table starting from the position we were at last time */ + for (uint32_t i = libtable->last_pos; i < symbol_count; i++) + { + Elf32_Sym &sym = symtab[i]; + unsigned char sym_type = ELF32_ST_TYPE(sym.st_info); + const char *sym_name = strtab + sym.st_name; + Symbol *cur_sym; + + /* Skip symbols that are undefined or do not refer to functions or objects */ + if (sym.st_shndx == SHN_UNDEF || (sym_type != STT_FUNC && sym_type != STT_OBJECT)) + { + continue; + } + + /* Caching symbols as we go along */ + cur_sym = table->InternSymbol(sym_name, strlen(sym_name), (void *)(dlmap->l_addr + sym.st_value)); + if (strcmp(symbol, sym_name) == 0) + { + symbol_entry = cur_sym; + libtable->last_pos = ++i; + break; + } + } + + munmap(file_hdr, dlstat.st_size); + return symbol_entry ? symbol_entry->address : NULL; + +#elif defined(__APPLE__) + + uintptr_t dlbase, linkedit_addr; + uint32_t image_count; + struct mach_header *file_hdr; + struct load_command *loadcmds; + struct segment_command *linkedit_hdr; + struct symtab_command *symtab_hdr; + struct nlist *symtab; + const char *strtab; + uint32_t loadcmd_count; + uint32_t symbol_count; + LibSymbolTable *libtable; + SymbolTable *table; + Symbol *symbol_entry; + + dlbase = 0; + image_count = m_ImageList->infoArrayCount; + linkedit_hdr = NULL; + symtab_hdr = NULL; + table = NULL; + + /* Loop through mach-o images in process. + * We can skip index 0 since that is just the executable. + */ + for (uint32_t i = 1; i < image_count; i++) + { + const struct dyld_image_info &info = m_ImageList->infoArray[i]; + + /* "Load" each one until we get a matching handle */ + void *h = dlopen(info.imageFilePath, RTLD_NOLOAD); + if (h == handle) + { + dlbase = (uintptr_t)info.imageLoadAddress; + dlclose(h); + break; + } + + dlclose(h); + } + + if (!dlbase) + { + /* Uh oh, we couldn't find a matching handle */ + return NULL; + } + + /* See if we already have a symbol table for this library */ + for (size_t i = 0; i < m_SymTables.length(); i++) + { + libtable = m_SymTables[i]; + if (libtable->lib_base == dlbase) + { + table = &libtable->table; + break; + } + } + + /* If we don't have a symbol table for this library, then create one */ + if (table == NULL) + { + libtable = new LibSymbolTable(); + libtable->table.Initialize(); + libtable->lib_base = dlbase; + libtable->last_pos = 0; + table = &libtable->table; + m_SymTables.append(libtable); + } + + /* See if the symbol is already cached in our table */ + symbol_entry = table->FindSymbol(symbol, strlen(symbol)); + if (symbol_entry != NULL) + { + return symbol_entry->address; + } + + /* If symbol isn't in our table, then we have to locate it in memory */ + + file_hdr = (struct mach_header *)dlbase; + loadcmds = (struct load_command *)(dlbase + sizeof(struct mach_header)); + loadcmd_count = file_hdr->ncmds; + + /* Loop through load commands until we find the ones for the symbol table */ + for (uint32_t i = 0; i < loadcmd_count; i++) + { + if (loadcmds->cmd == LC_SEGMENT && !linkedit_hdr) + { + struct segment_command *seg = (struct segment_command *)loadcmds; + if (strcmp(seg->segname, "__LINKEDIT") == 0) + { + linkedit_hdr = seg; + if (symtab_hdr) + { + break; + } + } + } + else if (loadcmds->cmd == LC_SYMTAB) + { + symtab_hdr = (struct symtab_command *)loadcmds; + if (linkedit_hdr) + { + break; + } + } + + /* Load commands are not of a fixed size which is why we add the size */ + loadcmds = (struct load_command *)((uintptr_t)loadcmds + loadcmds->cmdsize); + } + + if (!linkedit_hdr || !symtab_hdr || !symtab_hdr->symoff || !symtab_hdr->stroff) + { + /* Uh oh, no symbol table */ + return NULL; + } + + linkedit_addr = dlbase + linkedit_hdr->vmaddr; + symtab = (struct nlist *)(linkedit_addr + symtab_hdr->symoff - linkedit_hdr->fileoff); + strtab = (const char *)(linkedit_addr + symtab_hdr->stroff - linkedit_hdr->fileoff); + symbol_count = symtab_hdr->nsyms; + + /* Iterate symbol table starting from the position we were at last time */ + for (uint32_t i = libtable->last_pos; i < symbol_count; i++) + { + struct nlist &sym = symtab[i]; + /* Ignore the prepended underscore on all symbols, so +1 here */ + const char *sym_name = strtab + sym.n_un.n_strx + 1; + Symbol *cur_sym; + + /* Skip symbols that are undefined */ + if (sym.n_sect == NO_SECT) + { + continue; + } + + /* Caching symbols as we go along */ + cur_sym = table->InternSymbol(sym_name, strlen(sym_name), (void *)(dlbase + sym.n_value)); + if (strcmp(symbol, sym_name) == 0) + { + symbol_entry = cur_sym; + libtable->last_pos = ++i; + break; + } + } + + return symbol_entry ? symbol_entry->address : NULL; + +#endif +} + +bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib) +{ + uintptr_t baseAddr; + + if (libPtr == NULL) + { + return false; + } + +#if defined(WIN32) + + MEMORY_BASIC_INFORMATION info; + IMAGE_DOS_HEADER *dos; + IMAGE_NT_HEADERS *pe; + IMAGE_FILE_HEADER *file; + IMAGE_OPTIONAL_HEADER *opt; + + if (!VirtualQuery(libPtr, &info, sizeof(MEMORY_BASIC_INFORMATION))) + { + return false; + } + + baseAddr = reinterpret_cast(info.AllocationBase); + + /* All this is for our insane sanity checks :o */ + dos = reinterpret_cast(baseAddr); + pe = reinterpret_cast(baseAddr + dos->e_lfanew); + file = &pe->FileHeader; + opt = &pe->OptionalHeader; + + /* Check PE magic and signature */ + if (dos->e_magic != IMAGE_DOS_SIGNATURE || pe->Signature != IMAGE_NT_SIGNATURE || opt->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) + { + return false; + } + + /* Check architecture, which is 32-bit/x86 right now + * Should change this for 64-bit if Valve gets their act together + */ + if (file->Machine != IMAGE_FILE_MACHINE_I386) + { + return false; + } + + /* For our purposes, this must be a dynamic library */ + if ((file->Characteristics & IMAGE_FILE_DLL) == 0) + { + return false; + } + + /* Finally, we can do this */ + lib.memorySize = opt->SizeOfImage; + +#elif defined(__linux__) + + Dl_info info; + Elf32_Ehdr *file; + Elf32_Phdr *phdr; + uint16_t phdrCount; + + if (!dladdr(libPtr, &info)) + { + return false; + } + + if (!info.dli_fbase || !info.dli_fname) + { + return false; + } + + /* This is for our insane sanity checks :o */ + baseAddr = reinterpret_cast(info.dli_fbase); + file = reinterpret_cast(baseAddr); + + /* Check ELF magic */ + if (memcmp(ELFMAG, file->e_ident, SELFMAG) != 0) + { + return false; + } + + /* Check ELF version */ + if (file->e_ident[EI_VERSION] != EV_CURRENT) + { + return false; + } + + /* Check ELF architecture, which is 32-bit/x86 right now + * Should change this for 64-bit if Valve gets their act together + */ + if (file->e_ident[EI_CLASS] != ELFCLASS32 || file->e_machine != EM_386 || file->e_ident[EI_DATA] != ELFDATA2LSB) + { + return false; + } + + /* For our purposes, this must be a dynamic library/shared object */ + if (file->e_type != ET_DYN) + { + return false; + } + + phdrCount = file->e_phnum; + phdr = reinterpret_cast(baseAddr + file->e_phoff); + + for (uint16_t i = 0; i < phdrCount; i++) + { + Elf32_Phdr &hdr = phdr[i]; + + /* We only really care about the segment with executable code */ + if (hdr.p_type == PT_LOAD && hdr.p_flags == (PF_X|PF_R)) + { + /* From glibc, elf/dl-load.c: + * c->mapend = ((ph->p_vaddr + ph->p_filesz + GLRO(dl_pagesize) - 1) + * & ~(GLRO(dl_pagesize) - 1)); + * + * In glibc, the segment file size is aligned up to the nearest page size and + * added to the virtual address of the segment. We just want the size here. + */ + lib.memorySize = PAGE_ALIGN_UP(hdr.p_filesz); + break; + } + } + +#elif defined(__APPLE__) + + Dl_info info; + struct mach_header *file; + struct segment_command *seg; + uint32_t cmd_count; + + if (!dladdr(libPtr, &info)) + { + return false; + } + + if (!info.dli_fbase || !info.dli_fname) + { + return false; + } + + /* This is for our insane sanity checks :o */ + baseAddr = (uintptr_t)info.dli_fbase; + file = (struct mach_header *)baseAddr; + + /* Check Mach-O magic */ + if (file->magic != MH_MAGIC) + { + return false; + } + + /* Check architecture (32-bit/x86) */ + if (file->cputype != CPU_TYPE_I386 || file->cpusubtype != CPU_SUBTYPE_I386_ALL) + { + return false; + } + + /* For our purposes, this must be a dynamic library */ + if (file->filetype != MH_DYLIB) + { + return false; + } + + cmd_count = file->ncmds; + seg = (struct segment_command *)(baseAddr + sizeof(struct mach_header)); + + /* Add up memory sizes of mapped segments */ + for (uint32_t i = 0; i < cmd_count; i++) + { + if (seg->cmd == LC_SEGMENT) + { + lib.memorySize += seg->vmsize; + } + + seg = (struct segment_command *)((uintptr_t)seg + seg->cmdsize); + } + +#endif + + lib.baseAddress = reinterpret_cast(baseAddr); + + return true; +} + +bool MemoryUtils::GetLibraryOfAddress(const void *libPtr, char *buffer, size_t maxlength, uintptr_t *base) +{ +#if defined(__linux__) || defined(__APPLE__) + + Dl_info info; + if (!dladdr(libPtr, &info)) + { + return false; + } + if (!info.dli_fbase || !info.dli_fname) + { + return false; + } + const char *dllpath = info.dli_fname; + snprintf(buffer, maxlength, "%s", dllpath); + if (base) + { + *base = (uintptr_t)info.dli_fbase; + } + +#else + + MEMORY_BASIC_INFORMATION mem; + if (!VirtualQuery(libPtr, &mem, sizeof(mem))) + { + return false; + } + if (mem.AllocationBase == NULL) + { + return false; + } + HMODULE dll = (HMODULE)mem.AllocationBase; + GetModuleFileName(dll, (LPTSTR)buffer, maxlength); + if (base) + { + *base = (uintptr_t)mem.AllocationBase; + } + +#endif + + return true; +} + diff --git a/public/memtools/MemoryUtils.h b/public/memtools/MemoryUtils.h new file mode 100644 index 00000000..1e7a5fdc --- /dev/null +++ b/public/memtools/MemoryUtils.h @@ -0,0 +1,89 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2011 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + */ + +#ifndef _INCLUDE_SOURCEMOD_MEMORYUTILS_H_ +#define _INCLUDE_SOURCEMOD_MEMORYUTILS_H_ + +#if defined(__linux__) || defined(__APPLE__) + #include + #include + #include +#endif + +#if defined(__APPLE__) + #include +#endif + +#if defined(WIN32) + #include +#endif + +struct DynLibInfo +{ + void *baseAddress; + size_t memorySize; +}; + +#if defined(__linux__) || defined(__APPLE__) + struct LibSymbolTable + { + SymbolTable table; + uintptr_t lib_base; + uint32_t last_pos; + }; +#endif + +class MemoryUtils +{ + public: + MemoryUtils(); + ~MemoryUtils(); + + public: + void *FindPattern(const void *libPtr, const char *pattern, size_t len); + void *ResolveSymbol(void *handle, const char *symbol); + + public: + bool GetLibraryInfo(const void *libPtr, DynLibInfo &lib); + bool GetLibraryOfAddress(const void *libPtr, char *buffer, size_t maxlength, uintptr_t *base); + +#if defined(__linux__) || defined(__APPLE__) + private: + ke::Vector m_SymTables; + #if defined(__APPLE__) + struct dyld_all_image_infos *m_ImageList; + SInt32 m_OSXMajor; + SInt32 m_OSXMinor; + #endif // __APPLE__ +#endif +}; + +extern MemoryUtils g_MemUtils; + +#endif // _INCLUDE_SOURCEMOD_MEMORYUTILS_H_ diff --git a/public/sm_memtable.h b/public/sm_memtable.h new file mode 100644 index 00000000..d7e2d90d --- /dev/null +++ b/public/sm_memtable.h @@ -0,0 +1,170 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SOURCEMOD_CORE_STRINGTABLE_H_ +#define _INCLUDE_SOURCEMOD_CORE_STRINGTABLE_H_ + +#include +#include + +class BaseMemTable +{ +public: + BaseMemTable(unsigned int init_size) + { + membase = (unsigned char *)malloc(init_size); + size = init_size; + tail = 0; + } + ~BaseMemTable() + { + free(membase); + membase = NULL; + } +public: + /** + * Allocates 'size' bytes of memory. + * Optionally outputs the address through 'addr'. + * Returns an index >= 0 on success, < 0 on failure. + */ + int CreateMem(unsigned int addsize, void **addr) + { + int idx = (int)tail; + + while (tail + addsize >= size) { + size *= 2; + membase = (unsigned char *)realloc(membase, size); + } + + tail += addsize; + if (addr) + *addr = (void *)&membase[idx]; + + return idx; + } + + /** + * Given an index into the memory table, returns its address. + * Returns NULL if invalid. + */ + void *GetAddress(int index) + { + if (index < 0 || (unsigned int)index >= tail) + return NULL; + return &membase[index]; + } + + /** + * Scraps the memory table. For caching purposes, the memory + * is not freed, however subsequent calls to CreateMem() will + * begin at the first index again. + */ + void Reset() + { + tail = 0; + } + + inline unsigned int GetMemUsage() + { + return size; + } + + inline unsigned int GetActualMemUsed() + { + return tail; + } + +private: + unsigned char *membase; + unsigned int size; + unsigned int tail; +}; + +class BaseStringTable +{ +public: + BaseStringTable(unsigned int init_size) : m_table(init_size) + { + } +public: + /** + * Adds a string to the string table and returns its index. + */ + int AddString(const char *string) + { + return AddString(string, strlen(string)); + } + + /** + * Adds a string to the string table and returns its index. + */ + int AddString(const char *string, size_t length) + { + size_t len = length + 1; + int idx; + char *addr; + + idx = m_table.CreateMem(len, (void **)&addr); + memcpy(addr, string, length + 1); + return idx; + } + + /** + * Given an index into the string table, returns the associated string. + */ + inline const char *GetString(int str) + { + return (const char *)m_table.GetAddress(str); + } + + /** + * Scraps the string table. For caching purposes, the memory + * is not freed, however subsequent calls to AddString() will + * begin at the first index again. + */ + void Reset() + { + m_table.Reset(); + } + + /** + * Returns the parent BaseMemTable that this string table uses. + */ + inline BaseMemTable *GetMemTable() + { + return &m_table; + } +private: + BaseMemTable m_table; +}; + +#endif //_INCLUDE_SOURCEMOD_CORE_STRINGTABLE_H_ + diff --git a/public/sm_symtable.h b/public/sm_symtable.h new file mode 100644 index 00000000..0f1d391f --- /dev/null +++ b/public/sm_symtable.h @@ -0,0 +1,231 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + */ + +#ifndef _INCLUDE_SOURCEMOD_CORE_SYMBOLTABLE_H_ +#define _INCLUDE_SOURCEMOD_CORE_SYMBOLTABLE_H_ + +#include +#include +#include + +#define KESTRING_TABLE_START_SIZE 65536 + +struct Symbol +{ + size_t length; + uint32_t hash; + void *address; + Symbol *tbl_next; + + inline char *buffer() + { + return reinterpret_cast(this + 1); + } +}; + +class SymbolTable +{ +public: + ~SymbolTable() + { + for (uint32_t i = 0; i < nbuckets; i++) + { + Symbol *sym = buckets[i]; + while (sym != NULL) + { + Symbol *next = sym->tbl_next; + free(sym); + sym = next; + } + } + free(buckets); + } + + bool Initialize() + { + buckets = (Symbol **)malloc(sizeof(Symbol *) * KESTRING_TABLE_START_SIZE); + if (buckets == NULL) + { + return false; + } + memset(buckets, 0, sizeof(Symbol *) * KESTRING_TABLE_START_SIZE); + + nbuckets = KESTRING_TABLE_START_SIZE; + nused = 0; + bucketmask = KESTRING_TABLE_START_SIZE - 1; + return true; + } + + static inline uint32_t HashString(const char *data, size_t len) + { + #undef get16bits + #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ + || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) + #define get16bits(d) (*((const uint16_t *) (d))) + #endif + #if !defined (get16bits) + #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\ + +(uint32_t)(((const uint8_t *)(d))[0]) ) + #endif + uint32_t hash = len, tmp; + int rem; + + if (len <= 0 || data == NULL) + { + return 0; + } + + rem = len & 3; + len >>= 2; + + /* Main loop */ + for (;len > 0; len--) { + hash += get16bits (data); + tmp = (get16bits (data+2) << 11) ^ hash; + hash = (hash << 16) ^ tmp; + data += 2 * sizeof (uint16_t); + hash += hash >> 11; + } + + /* Handle end cases */ + switch (rem) { + case 3: hash += get16bits (data); + hash ^= hash << 16; + hash ^= data[sizeof (uint16_t)] << 18; + hash += hash >> 11; + break; + case 2: hash += get16bits (data); + hash ^= hash << 11; + hash += hash >> 17; + break; + case 1: hash += *data; + hash ^= hash << 10; + hash += hash >> 1; + } + + /* Force "avalanching" of final 127 bits */ + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + + return hash; + + #undef get16bits + } + + Symbol **FindSymbolBucket(const char *str, size_t len, uint32_t hash) + { + uint32_t bucket = hash & bucketmask; + Symbol **pkvs = &buckets[bucket]; + + Symbol *kvs = *pkvs; + while (kvs != NULL) + { + if (len == kvs->length && memcmp(str, kvs->buffer(), len * sizeof(char)) == 0) + { + return pkvs; + } + pkvs = &kvs->tbl_next; + kvs = *pkvs; + } + + return pkvs; + } + + void ResizeSymbolTable() + { + uint32_t xnbuckets = nbuckets * 2; + Symbol **xbuckets = (Symbol **)malloc(sizeof(Symbol *) * xnbuckets); + if (xbuckets == NULL) + { + return; + } + memset(xbuckets, 0, sizeof(Symbol *) * xnbuckets); + uint32_t xbucketmask = xnbuckets - 1; + for (uint32_t i = 0; i < nbuckets; i++) + { + Symbol *sym = buckets[i]; + while (sym != NULL) + { + Symbol *next = sym->tbl_next; + uint32_t bucket = sym->hash & xbucketmask; + sym->tbl_next = xbuckets[bucket]; + xbuckets[bucket] = sym; + sym = next; + } + } + free(buckets); + buckets = xbuckets; + nbuckets = xnbuckets; + bucketmask = xbucketmask; + } + + Symbol *FindSymbol(const char *str, size_t len) + { + uint32_t hash = HashString(str, len); + Symbol **pkvs = FindSymbolBucket(str, len, hash); + return *pkvs; + } + + Symbol *InternSymbol(const char* str, size_t len, void *address) + { + uint32_t hash = HashString(str, len); + Symbol **pkvs = FindSymbolBucket(str, len, hash); + if (*pkvs != NULL) + { + return *pkvs; + } + + Symbol *kvs = (Symbol *)malloc(sizeof(Symbol) + sizeof(char) * (len + 1)); + kvs->length = len; + kvs->hash = hash; + kvs->address = address; + kvs->tbl_next = NULL; + memcpy(kvs + 1, str, sizeof(char) * (len + 1)); + *pkvs = kvs; + nused++; + + if (nused > nbuckets && nbuckets <= INT_MAX / 2) + { + ResizeSymbolTable(); + } + + return kvs; + } +private: + uint32_t nbuckets; + uint32_t nused; + uint32_t bucketmask; + Symbol **buckets; +}; + +#endif //_INCLUDE_SOURCEMOD_CORE_SYMBOLTABLE_H_ From e4ff6853dd3e86d7e22d564b55f5530be6acae12 Mon Sep 17 00:00:00 2001 From: Arkshine Date: Wed, 28 May 2014 23:59:34 +0200 Subject: [PATCH 05/14] Cstrike: Convert code to use CDetour and MemoryUtils. --- dlls/cstrike/cstrike/CstrikeHacks.cpp | 233 +++++--------------------- dlls/cstrike/cstrike/CstrikeNatives.h | 3 - dlls/cstrike/cstrike/amxx_api.cpp | 10 +- 3 files changed, 55 insertions(+), 191 deletions(-) diff --git a/dlls/cstrike/cstrike/CstrikeHacks.cpp b/dlls/cstrike/cstrike/CstrikeHacks.cpp index 09f8be3c..d8b15589 100644 --- a/dlls/cstrike/cstrike/CstrikeHacks.cpp +++ b/dlls/cstrike/cstrike/CstrikeHacks.cpp @@ -1,97 +1,66 @@ -#include -#include #include "CstrikeDatas.h" - -#if defined(__linux__) || defined(__APPLE__) -#include -#define PAGE_EXECUTE_READWRITE PROT_READ|PROT_WRITE|PROT_EXEC - -#if defined(__linux) -#include -#endif -#endif +#include +#include "CDetour/detours.h" #if defined(__APPLE__) -#include + #include #endif -/* Utils */ -unsigned char *UTIL_CodeAlloc(size_t size); -void UTIL_CodeFree(unsigned char *addr); -void UTIL_MemProtect(void *addr, int length, int prot); -bool UTIL_GetLibraryOfAddress(void *memInBase, char *buffer, size_t maxlength, uintptr_t *base); - -/* Detours */ void CtrlDetour_ClientCommand(bool set); -int Detour_ClientCommand(edict_t *pEdict); int g_CSCliCmdFwd = -1; int *g_UseBotArgs = NULL; const char **g_BotArgs = NULL; +CDetour *g_ClientCommandDetour = NULL; -/* Called on startup */ void InitializeHacks() { CtrlDetour_ClientCommand(true); } -void OnPluginsLoaded() -{ - g_CSCliCmdFwd = MF_RegisterForward("CS_InternalCommand", ET_STOP, FP_CELL, FP_STRING, FP_DONE); -} - void ShutdownHacks() { CtrlDetour_ClientCommand(false); } +DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) +{ + if (*g_UseBotArgs) + { + int client = ENTINDEX(pEdict); + const char *args = *g_BotArgs; + + if (MF_ExecuteForward(g_CSCliCmdFwd, static_cast(client), args) > 0) + { + return; + } + } + + DETOUR_STATIC_CALL(C_ClientCommand)(pEdict); +} + void CtrlDetour_ClientCommand(bool set) { #if defined AMD64 -#error UNSUPPORTED + #error UNSUPPORTED #endif - static unsigned char DetourOps[] = - { - 0x50, /* push eax ; just for safety */ - 0xff, 0x74, 0x24, 0x08, /* push [esp+0x8] ; push the edict pointer */ - 0xe8, 0x00, 0x00, 0x00, 0x00, /* call ; call our function */ - 0x83, 0xc4, 0x08, /* add esp, 8 ; correct stack */ - 0x85, 0xc0, /* test eax, eax ; do != 0 test */ - 0x74, 0x01, /* je ; if == 0, jump to where old func is saved */ - 0xc3 /* ret ; return otherwise */ - }; - static unsigned char DetourJmp = '\xE9'; - - const unsigned int DetourBytes = 18; - const unsigned int DetourCallPos = 6; - const unsigned int DetourJmpPos = DetourBytes + CS_DETOURCOPYBYTES_CLIENTCOMMAND; - const unsigned int DetourJmpBytes = 5; - static unsigned char *FullDetour = NULL; void *target = (void *)MDLL_ClientCommand; - unsigned char *paddr; if (!g_UseBotArgs) { -#if defined(__linux__) || defined(__APPLE__) - /* Find the DLL */ +#if defined(__linux__) + + g_UseBotArgs = (int *)g_MemUtils.ResolveSymbol(target, "UseBotArgs"); + g_BotArgs = (const char **)g_MemUtils.ResolveSymbol(target, "BotArgs"); + +#elif defined(__APPLE__) + + /* Using dlsym on OS X won't work because the symbols are hidden */ char dll[256]; uintptr_t base; - if (!UTIL_GetLibraryOfAddress(target, dll, sizeof(dll), &base)) - { - return; - } -#if defined(__linux__) - void *handle = dlopen(dll, RTLD_NOW); - if (!handle) - { - return; - } - g_UseBotArgs = (int *)dlsym(handle, "UseBotArgs"); - g_BotArgs = (const char **)dlsym(handle, "BotArgs"); - dlclose(handle); -#elif defined(__APPLE__) - /* Using dlsym on OS X won't work because the symbols are hidden */ + g_MemUtils.GetLibraryOfAddress(target, dll, sizeof(dll), &base); + struct nlist symbols[3]; memset(symbols, 0, sizeof(symbols)); symbols[0].n_un.n_name = (char *)"_UseBotArgs"; @@ -102,136 +71,26 @@ void CtrlDetour_ClientCommand(bool set) } g_UseBotArgs = (int *)(base + symbols[0].n_value); g_BotArgs = (const char **)(base + symbols[1].n_value); -#endif -#else /* Windows */ - /* Find the bot args addresses */ - paddr = (unsigned char *)target + CS_CLICMD_OFFS_USEBOTARGS; - g_UseBotArgs = *(int **)paddr; - paddr = (unsigned char *)target + CS_CLICMD_OFFS_BOTARGS; - g_BotArgs = (const char **)*(const char **)paddr; + +#elif defined(WIN32) + + g_UseBotArgs = *(int **)((unsigned char *)target + CS_CLICMD_OFFS_USEBOTARGS); + g_BotArgs = (const char **)*(const char **)((unsigned char *)target + CS_CLICMD_OFFS_BOTARGS); + #endif } if (set) { - assert(FullDetour == NULL); - FullDetour = UTIL_CodeAlloc(DetourBytes + CS_DETOURCOPYBYTES_CLIENTCOMMAND + DetourJmpBytes); - - /* Copy the main trampoline function */ - memcpy(FullDetour, DetourOps, DetourBytes); - - /* Copy our detour call into the trampoline */ - paddr = &FullDetour[DetourCallPos]; - *(unsigned long *)paddr = (unsigned long)Detour_ClientCommand - (unsigned long)(paddr + 4); - - /* Copy original bytes onto the end of the function */ - memcpy(&FullDetour[DetourBytes], target, CS_DETOURCOPYBYTES_CLIENTCOMMAND); - - /* Patch and copy the final jmp */ - paddr = &FullDetour[DetourJmpPos]; - *paddr++ = DetourJmp; - *(unsigned long *)paddr = ((unsigned long)target + CS_DETOURCOPYBYTES_CLIENTCOMMAND) - - (unsigned long)(paddr + 4); - - /* Now overwrite the target function with our trampoline */ - UTIL_MemProtect(target, CS_DETOURCOPYBYTES_CLIENTCOMMAND + 10, PAGE_EXECUTE_READWRITE); - paddr = (unsigned char *)target; - *paddr++ = DetourJmp; - *(unsigned long *)paddr = (unsigned long)FullDetour - (unsigned long)(paddr + 4); - } else { - assert(FullDetour != NULL); + g_ClientCommandDetour = DETOUR_CREATE_STATIC_FIXED(C_ClientCommand, target); - /* Copy back the original function bytes */ - memcpy(target, &FullDetour[DetourBytes], CS_DETOURCOPYBYTES_CLIENTCOMMAND); - - /* Free memory used */ - UTIL_CodeFree(FullDetour); - FullDetour = NULL; + if (g_ClientCommandDetour != NULL) + { + g_ClientCommandDetour->EnableDetour(); + } + } + else + { + g_ClientCommandDetour->Destroy(); } } - -int Detour_ClientCommand(edict_t *pEdict) -{ - if (*g_UseBotArgs) - { - int client = ENTINDEX(pEdict); - const char *args = *g_BotArgs; - return MF_ExecuteForward(g_CSCliCmdFwd, (cell)client, args); - } - return 0; -} - -unsigned char *UTIL_CodeAlloc(size_t size) -{ -#if defined WIN32 - return (unsigned char *)VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); -#elif defined __GNUC__ -#if defined __APPLE__ - unsigned char *addr = (unsigned char *)valloc(size); -#else - unsigned char *addr = (unsigned char *)memalign(sysconf(_SC_PAGESIZE), size); -#endif - mprotect(addr, size, PROT_READ|PROT_WRITE|PROT_EXEC); - return addr; -#endif -} - -void UTIL_CodeFree(unsigned char *addr) -{ -#if defined WIN32 - VirtualFree(addr, 0, MEM_RELEASE); -#else - free(addr); -#endif -} - -void UTIL_MemProtect(void *addr, int length, int prot) -{ -#if defined(__linux__) || defined(__APPLE__) -#define ALIGN(ar) ((long)ar & ~(sysconf(_SC_PAGESIZE)-1)) - void *addr2 = (void *)ALIGN(addr); - mprotect(addr2, sysconf(_SC_PAGESIZE), prot); -#else - DWORD old_prot; - VirtualProtect(addr, length, prot, &old_prot); -#endif -} - -bool UTIL_GetLibraryOfAddress(void *memInBase, char *buffer, size_t maxlength, uintptr_t *base) -{ -#if defined(__linux__) || defined(__APPLE__) - Dl_info info; - if (!dladdr(memInBase, &info)) - { - return false; - } - if (!info.dli_fbase || !info.dli_fname) - { - return false; - } - const char *dllpath = info.dli_fname; - snprintf(buffer, maxlength, "%s", dllpath); - if (base) - { - *base = (uintptr_t)info.dli_fbase; - } -#else - MEMORY_BASIC_INFORMATION mem; - if (!VirtualQuery(memInBase, &mem, sizeof(mem))) - { - return false; - } - if (mem.AllocationBase == NULL) - { - return false; - } - HMODULE dll = (HMODULE)mem.AllocationBase; - GetModuleFileName(dll, (LPTSTR)buffer, maxlength); - if (base) - { - *base = (uintptr_t)mem.AllocationBase; - } -#endif - return true; -} - diff --git a/dlls/cstrike/cstrike/CstrikeNatives.h b/dlls/cstrike/cstrike/CstrikeNatives.h index d58b77b0..1d39bc41 100644 --- a/dlls/cstrike/cstrike/CstrikeNatives.h +++ b/dlls/cstrike/cstrike/CstrikeNatives.h @@ -48,9 +48,6 @@ extern bool g_precachedknife; extern bool g_noknives; // Globals above -void InitializeHacks(); -void ShutdownHacks(); - #define CHECK_ENTITY(x) \ if (x < 0 || x > gpGlobals->maxEntities) { \ MF_LogError(amx, AMX_ERR_NATIVE, "Entity out of range (%d)", x); \ diff --git a/dlls/cstrike/cstrike/amxx_api.cpp b/dlls/cstrike/cstrike/amxx_api.cpp index 3a4f0c68..730ce81a 100644 --- a/dlls/cstrike/cstrike/amxx_api.cpp +++ b/dlls/cstrike/cstrike/amxx_api.cpp @@ -31,9 +31,12 @@ * version. */ #include "amxxmodule.h" -#include "CstrikeNatives.h" extern AMX_NATIVE_INFO cstrikeNatives[]; +extern int g_CSCliCmdFwd; + +void InitializeHacks(); +void ShutdownHacks(); int AmxxCheckGame(const char *game) { @@ -51,6 +54,11 @@ void OnAmxxAttach() InitializeHacks(); } +void OnPluginsLoaded() +{ + g_CSCliCmdFwd = MF_RegisterForward("CS_InternalCommand", ET_STOP, FP_CELL, FP_STRING, FP_DONE); +} + void OnAmxxDetach() { ShutdownHacks(); From 38e2e3e393354d6424f36e6c9dcbce4c2aa6139b Mon Sep 17 00:00:00 2001 From: Arkshine Date: Thu, 29 May 2014 01:19:52 +0200 Subject: [PATCH 06/14] Cstrike: Move utility stuff in its own file. --- dlls/cstrike/cstrike/AMBuilder | 1 + dlls/cstrike/cstrike/CstrikeNatives.cpp | 32 +------ dlls/cstrike/cstrike/CstrikeNatives.h | 93 ------------------- dlls/cstrike/cstrike/CstrikeUtils.cpp | 62 +++++++++++++ dlls/cstrike/cstrike/CstrikeUtils.h | 87 +++++++++++++++++ dlls/cstrike/cstrike/Makefile | 5 +- dlls/cstrike/cstrike/msvc10/cstrike.vcxproj | 8 +- .../cstrike/msvc10/cstrike.vcxproj.filters | 20 ++-- 8 files changed, 169 insertions(+), 139 deletions(-) delete mode 100644 dlls/cstrike/cstrike/CstrikeNatives.h create mode 100644 dlls/cstrike/cstrike/CstrikeUtils.cpp create mode 100644 dlls/cstrike/cstrike/CstrikeUtils.h diff --git a/dlls/cstrike/cstrike/AMBuilder b/dlls/cstrike/cstrike/AMBuilder index 5efeb1d0..fc243e71 100644 --- a/dlls/cstrike/cstrike/AMBuilder +++ b/dlls/cstrike/cstrike/AMBuilder @@ -9,6 +9,7 @@ binary.sources = [ 'CstrikePlayer.cpp', 'CstrikeNatives.cpp', 'CstrikeHacks.cpp', + 'CstrikeUtils.cpp', '../../../public/memtools/MemoryUtils.cpp', '../../../public/memtools/CDetour/detours.cpp', '../../../public/memtools/CDetour/asm/asm.c', diff --git a/dlls/cstrike/cstrike/CstrikeNatives.cpp b/dlls/cstrike/cstrike/CstrikeNatives.cpp index ed581af2..980f2cc1 100644 --- a/dlls/cstrike/cstrike/CstrikeNatives.cpp +++ b/dlls/cstrike/cstrike/CstrikeNatives.cpp @@ -30,43 +30,15 @@ * you do not wish to do so, delete this exception statement from your * version. */ -#include "CstrikeNatives.h" #include "CstrikeDatas.h" +#include "CstrikePlayer.h" +#include "CstrikeUtils.h" CCstrikePlayer g_players[33]; int g_zooming[33] = {0}; bool g_precachedknife = false; bool g_noknives = false; -// Utils first - -bool UTIL_IsPlayer(AMX* amx, edict_t* pPlayer) { - bool player = false; - - if (strcmp(STRING(pPlayer->v.classname), "player") == 0) - player = true; - - return player; -} - -void UTIL_TextMsg_Generic(edict_t* pPlayer, const char* message) -{ - MESSAGE_BEGIN(MSG_ONE, GET_USER_MSG_ID(PLID, "TextMsg", NULL), NULL, pPlayer); - WRITE_BYTE(HUD_PRINTCENTER); // 1 = console, 2 = console, 3 = chat, 4 = center - WRITE_STRING(message); - MESSAGE_END(); - /* - The byte above seems to use these: - #define HUD_PRINTNOTIFY 1 - #define HUD_PRINTCONSOLE 2 - #define HUD_PRINTTALK 3 - #define HUD_PRINTCENTER 4 - However both 1 and 2 seems to go to console with Steam CS. - */ -} - -// Then natives - static cell AMX_NATIVE_CALL cs_set_user_money(AMX *amx, cell *params) // cs_set_user_money(index, money, flash = 1); = 3 arguments { // Give money to user diff --git a/dlls/cstrike/cstrike/CstrikeNatives.h b/dlls/cstrike/cstrike/CstrikeNatives.h deleted file mode 100644 index 1d39bc41..00000000 --- a/dlls/cstrike/cstrike/CstrikeNatives.h +++ /dev/null @@ -1,93 +0,0 @@ -/* AMX Mod X - * Counter-Strike Module - * - * by the AMX Mod X Development Team - * - * This file is part of AMX Mod X. - * - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * In addition, as a special exception, the author gives permission to - * link the code of this program with the Half-Life Game Engine ("HL - * Engine") and Modified Game Libraries ("MODs") developed by Valve, - * L.L.C ("Valve"). You must obey the GNU General Public License in all - * respects for all of the code used other than the HL Engine and MODs - * from Valve. If you modify this file, you may extend this exception - * to your version of the file, but you are not obligated to do so. If - * you do not wish to do so, delete this exception statement from your - * version. - */ - -// cstrike MODULE TO DO HERE: http://www.amxmodx.org/forums/viewtopic.php?t=45 -// This implementation uses Vexd's way (lightly modified) of setting models on players. - -#include "amxxmodule.h" -#include "CstrikePlayer.h" - -#define GETINFOKEYBUFFER (*g_engfuncs.pfnGetInfoKeyBuffer) -#define SETCLIENTKEYVALUE (*g_engfuncs.pfnSetClientKeyValue) -#define GETCLIENTKEYVALUE (*g_engfuncs.pfnInfoKeyValue) -#define CREATENAMEDENTITY (*g_engfuncs.pfnCreateNamedEntity) - -extern CCstrikePlayer g_players[33]; -extern int g_zooming[33]; -extern bool g_precachedknife; -extern bool g_noknives; -// Globals above - -#define CHECK_ENTITY(x) \ - if (x < 0 || x > gpGlobals->maxEntities) { \ - MF_LogError(amx, AMX_ERR_NATIVE, "Entity out of range (%d)", x); \ - return 0; \ - } else { \ - if (x <= gpGlobals->maxClients) { \ - if (!MF_IsPlayerIngame(x)) { \ - MF_LogError(amx, AMX_ERR_NATIVE, "Invalid player %d (not in-game)", x); \ - return 0; \ - } \ - } else { \ - if (x != 0 && FNullEnt(INDEXENT(x))) { \ - MF_LogError(amx, AMX_ERR_NATIVE, "Invalid entity %d", x); \ - return 0; \ - } \ - } \ - } - -#define CHECK_PLAYER(x) \ - if (x < 1 || x > gpGlobals->maxClients) { \ - MF_LogError(amx, AMX_ERR_NATIVE, "Player out of range (%d)", x); \ - return 0; \ - } else { \ - if (!MF_IsPlayerIngame(x) || FNullEnt(MF_GetPlayerEdict(x))) { \ - MF_LogError(amx, AMX_ERR_NATIVE, "Invalid player %d", x); \ - return 0; \ - } \ - } - -#define CHECK_NONPLAYER(x) \ - if (x < 1 || x <= gpGlobals->maxClients || x > gpGlobals->maxEntities) { \ - MF_LogError(amx, AMX_ERR_NATIVE, "Non-player entity %d out of range", x); \ - return 0; \ - } else { \ - if (FNullEnt(INDEXENT(x))) { \ - MF_LogError(amx, AMX_ERR_NATIVE, "Invalid non-player entity %d", x); \ - return 0; \ - } \ - } - -#define GETEDICT(n) \ - ((n >= 1 && n <= gpGlobals->maxClients) ? MF_GetPlayerEdict(n) : INDEXENT(n)) - diff --git a/dlls/cstrike/cstrike/CstrikeUtils.cpp b/dlls/cstrike/cstrike/CstrikeUtils.cpp new file mode 100644 index 00000000..3f8de77f --- /dev/null +++ b/dlls/cstrike/cstrike/CstrikeUtils.cpp @@ -0,0 +1,62 @@ +/* AMX Mod X +* Counter-Strike Module +* +* by the AMX Mod X Development Team +* +* This file is part of AMX Mod X. +* +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at +* your option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +* In addition, as a special exception, the author gives permission to +* link the code of this program with the Half-Life Game Engine ("HL +* Engine") and Modified Game Libraries ("MODs") developed by Valve, +* L.L.C ("Valve"). You must obey the GNU General Public License in all +* respects for all of the code used other than the HL Engine and MODs +* from Valve. If you modify this file, you may extend this exception +* to your version of the file, but you are not obligated to do so. If +* you do not wish to do so, delete this exception statement from your +* version. +*/ +#include "amxxmodule.h" + +bool UTIL_IsPlayer(AMX* amx, edict_t* pPlayer) +{ + bool player = false; + + if (strcmp(STRING(pPlayer->v.classname), "player") == 0) + { + player = true; + } + + return player; +} + +void UTIL_TextMsg_Generic(edict_t* pPlayer, const char* message) +{ + MESSAGE_BEGIN(MSG_ONE, GET_USER_MSG_ID(PLID, "TextMsg", NULL), NULL, pPlayer); + WRITE_BYTE(HUD_PRINTCENTER); // 1 = console, 2 = console, 3 = chat, 4 = center, 5 = radio + WRITE_STRING(message); + MESSAGE_END(); + /* + The byte above seems to use these: + #define HUD_PRINTNOTIFY 1 + #define HUD_PRINTCONSOLE 2 + #define HUD_PRINTTALK 3 + #define HUD_PRINTCENTER 4 + #define HUD_PRINTRADIO 5 + However both 1 and 2 seems to go to console with Steam CS. + */ +} \ No newline at end of file diff --git a/dlls/cstrike/cstrike/CstrikeUtils.h b/dlls/cstrike/cstrike/CstrikeUtils.h new file mode 100644 index 00000000..0cdd0f95 --- /dev/null +++ b/dlls/cstrike/cstrike/CstrikeUtils.h @@ -0,0 +1,87 @@ +/* AMX Mod X +* Counter-Strike Module +* +* by the AMX Mod X Development Team +* +* This file is part of AMX Mod X. +* +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at +* your option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +* In addition, as a special exception, the author gives permission to +* link the code of this program with the Half-Life Game Engine ("HL +* Engine") and Modified Game Libraries ("MODs") developed by Valve, +* L.L.C ("Valve"). You must obey the GNU General Public License in all +* respects for all of the code used other than the HL Engine and MODs +* from Valve. If you modify this file, you may extend this exception +* to your version of the file, but you are not obligated to do so. If +* you do not wish to do so, delete this exception statement from your +* version. +*/ +#ifndef CSTRIKE_UTILS_H +#define CSTRIKE_UTILS_H + +bool UTIL_IsPlayer(AMX* amx, edict_t* pPlayer); +void UTIL_TextMsg_Generic(edict_t* pPlayer, const char* message); + +#define GETINFOKEYBUFFER (*g_engfuncs.pfnGetInfoKeyBuffer) +#define SETCLIENTKEYVALUE (*g_engfuncs.pfnSetClientKeyValue) +#define GETCLIENTKEYVALUE (*g_engfuncs.pfnInfoKeyValue) +#define CREATENAMEDENTITY (*g_engfuncs.pfnCreateNamedEntity) + +#define CHECK_ENTITY(x) \ + if (x < 0 || x > gpGlobals->maxEntities) { \ + MF_LogError(amx, AMX_ERR_NATIVE, "Entity out of range (%d)", x); \ + return 0; \ + } else { \ + if (x <= gpGlobals->maxClients) { \ + if (!MF_IsPlayerIngame(x)) { \ + MF_LogError(amx, AMX_ERR_NATIVE, "Invalid player %d (not in-game)", x); \ + return 0; \ + } \ + } else { \ + if (x != 0 && FNullEnt(INDEXENT(x))) { \ + MF_LogError(amx, AMX_ERR_NATIVE, "Invalid entity %d", x); \ + return 0; \ + } \ + } \ + } + +#define CHECK_PLAYER(x) \ + if (x < 1 || x > gpGlobals->maxClients) { \ + MF_LogError(amx, AMX_ERR_NATIVE, "Player out of range (%d)", x); \ + return 0; \ + } else { \ + if (!MF_IsPlayerIngame(x) || FNullEnt(MF_GetPlayerEdict(x))) { \ + MF_LogError(amx, AMX_ERR_NATIVE, "Invalid player %d", x); \ + return 0; \ + } \ + } + +#define CHECK_NONPLAYER(x) \ + if (x < 1 || x <= gpGlobals->maxClients || x > gpGlobals->maxEntities) { \ + MF_LogError(amx, AMX_ERR_NATIVE, "Non-player entity %d out of range", x); \ + return 0; \ + } else { \ + if (FNullEnt(INDEXENT(x))) { \ + MF_LogError(amx, AMX_ERR_NATIVE, "Invalid non-player entity %d", x); \ + return 0; \ + } \ + } + +#define GETEDICT(n) \ + ((n >= 1 && n <= gpGlobals->maxClients) ? MF_GetPlayerEdict(n) : INDEXENT(n)) + +#endif // CSTRIKE_UTILS_H \ No newline at end of file diff --git a/dlls/cstrike/cstrike/Makefile b/dlls/cstrike/cstrike/Makefile index dae7b5ac..4e0e9403 100755 --- a/dlls/cstrike/cstrike/Makefile +++ b/dlls/cstrike/cstrike/Makefile @@ -14,8 +14,9 @@ MM_ROOT = ../../../../metamod/metamod PROJECT = cstrike -OBJECTS = sdk/amxxmodule.cpp amxx_api.cpp CstrikePlayer.cpp CstrikeNatives.cpp CstrikeHacks.cpp \ - ../../../public/memtools/MemoryUtils.cpp ../../../public/memtools/CDetour/detours.cpp \ +OBJECTS = sdk/amxxmodule.cpp amxx_api.cpp CstrikePlayer.cpp CstrikeNatives.cpp CstrikeHacks.cpp CstrikeUtils.cpp \ + ../../../public/memtools/MemoryUtils.cpp \ + ../../../public/memtools/CDetour/detours.cpp \ ../../../public/memtools/CDetour/asm/asm.c ############################################## diff --git a/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj b/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj index 355ccb75..c19e1bda 100644 --- a/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj +++ b/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj @@ -139,9 +139,10 @@ - + + @@ -150,14 +151,13 @@ - - + - + diff --git a/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj.filters b/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj.filters index c73b5ac0..cdf8c9fa 100644 --- a/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj.filters +++ b/dlls/cstrike/cstrike/msvc10/cstrike.vcxproj.filters @@ -41,9 +41,6 @@ Source Files - - Source Files - Memtools @@ -53,23 +50,23 @@ Memtools\CDetour\asm + + Source Files + + + Source Files + Header Files - - Header Files - Module SDK Module SDK\SDK Base - - Header Files - Header Files @@ -85,9 +82,12 @@ Memtools\CDetour\asm + + Header Files + - + Pawn Includes From f130a8ea89b846741267db0e6cef4224447497f6 Mon Sep 17 00:00:00 2001 From: Arkshine Date: Fri, 30 May 2014 00:13:03 +0200 Subject: [PATCH 07/14] Cstrike: Implement CS_OnBuy forward. --- dlls/cstrike/cstrike/CstrikeDatas.h | 89 +++++++++++- dlls/cstrike/cstrike/CstrikeHacks.cpp | 195 +++++++++++++++++++++----- dlls/cstrike/cstrike/CstrikeUtils.h | 32 +++++ dlls/cstrike/cstrike/amxx_api.cpp | 3 + plugins/include/cstrike.inc | 50 +++++++ public/memtools/CDetour/detours.h | 14 +- public/memtools/MemoryUtils.cpp | 52 ++++++- public/memtools/MemoryUtils.h | 8 ++ 8 files changed, 404 insertions(+), 39 deletions(-) diff --git a/dlls/cstrike/cstrike/CstrikeDatas.h b/dlls/cstrike/cstrike/CstrikeDatas.h index b237b34e..b4af6ceb 100644 --- a/dlls/cstrike/cstrike/CstrikeDatas.h +++ b/dlls/cstrike/cstrike/CstrikeDatas.h @@ -1,3 +1,35 @@ +/* AMX Mod X + * Counter-Strike Module + * + * by the AMX Mod X Development Team + * + * This file is part of AMX Mod X. + * + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + */ #ifndef CSTRIKE_DATA_H #define CSTRIKE_DATA_H @@ -123,10 +155,64 @@ #define CS_CLICMD_OFFS_BOTARGS 22 #endif +/** + * CS_OnBuy forward + */ +#if defined(__linux__) + #define CS_SYM_CANBUYTHIS "_Z10CanBuyThisP11CBasePlayeri" + #define CS_SYM_BUYITEM "_Z7BuyItemP11CBasePlayeri" + #define CS_SYM_BUYGUNAMMO "_Z10BuyGunAmmoR11CBasePlayerR15CBasePlayerItemb" +#elif defined(__APPLE__) + #define CS_SYM_CANBUYTHIS "__Z10CanBuyThisP11CBasePlayeri" + #define CS_SYM_BUYITEM "__Z7BuyItemP11CBasePlayeri" + #define CS_SYM_BUYGUNAMMO "__Z10BuyGunAmmoR11CBasePlayerR15CBasePlayerItemb" +#elif defined(WIN32) + #define CS_SIG_CANBUYTHIS "\x53\x8B\x2A\x2A\x2A\x2A\x2A\x56\x8B\x2A\x2A\x2A\x57" + #define CS_SIG_BUYITEM "\x53\x56\x8B\x2A\x2A\x2A\xBB\x2A\x2A\x2A\x2A\x57\x53" + #define CS_SIG_BUYGUNAMMO "\x56\x57\x8B\x2A\x2A\x2A\x6A\x2A\x8B\x2A\xE8\x2A\x2A\x2A\x2A\x84\x2A\x0F" +#endif + +#define CSI_P228 CSW_P228 +#define CSI_SCOUT CSW_SCOUT +#define CSI_HEGRENADE CSW_HEGRENADE +#define CSI_XM1014 CSW_XM1014 +#define CSI_C4 CSW_C4 +#define CSI_MAC10 CSW_MAC10 +#define CSI_AUG CSW_AUG +#define CSI_SMOKEGRENADE CSW_SMOKEGRENADE +#define CSI_ELITE CSW_ELITE +#define CSI_FIVESEVEN CSW_FIVESEVEN +#define CSI_UMP45 CSW_UMP45 +#define CSI_SG550 CSW_SG550 +#define CSI_GALI CSW_GALI +#define CSI_FAMAS CSW_FAMAS +#define CSI_USP CSW_USP +#define CSI_GLOCK18 CSW_GLOCK18 +#define CSI_AWP CSW_AWP +#define CSI_MP5NAVY CSW_MP5NAVY +#define CSI_M249 CSW_M249 +#define CSI_M3 CSW_M3 +#define CSI_M4A1 CSW_M4A1 +#define CSI_TMP CSW_TMP +#define CSI_G3SG1 CSW_G3SG1 +#define CSI_FLASHBANG CSW_FLASHBANG +#define CSI_DEAGLE CSW_DEAGLE +#define CSI_SG552 CSW_SG552 +#define CSI_AK47 CSW_AK47 +#define CSI_KNIFE CSW_KNIFE +#define CSI_P90 CSW_P90 +#define CSI_SHIELDGUN CSW_SHIELDGUN +#define CSI_VEST CSW_VEST // Custom +#define CSI_VESTHELM CSW_VESTHELM // Custom +#define CSI_DEFUSER 33 // Custom +#define CSI_NVGS 34 // Custom +#define CSI_PRIMAMMO 36 // Custom +#define CSI_SECAMMO 37 // Custom + +#define BITS_PISTOLS (1< #include "CDetour/detours.h" @@ -6,24 +39,32 @@ #include #endif -void CtrlDetour_ClientCommand(bool set); +void CtrlDetours(bool set); int g_CSCliCmdFwd = -1; +int g_CSBuyCmdFwd = -1; + int *g_UseBotArgs = NULL; const char **g_BotArgs = NULL; + CDetour *g_ClientCommandDetour = NULL; +CDetour *g_CanBuyThisDetour = NULL; +CDetour *g_BuyItemDetour = NULL; +CDetour *g_BuyGunAmmoDetour = NULL; + void InitializeHacks() { - CtrlDetour_ClientCommand(true); + CtrlDetours(true); } void ShutdownHacks() { - CtrlDetour_ClientCommand(false); + CtrlDetours(false); } -DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) + +DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientCommand(edict_t *pEntity) { if (*g_UseBotArgs) { @@ -39,58 +80,146 @@ DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) DETOUR_STATIC_CALL(C_ClientCommand)(pEdict); } -void CtrlDetour_ClientCommand(bool set) +DETOUR_DECL_STATIC2(CanBuyThis, bool, void*, pvPlayer, int, weaponId) // bool CanBuyThis(CBasePlayer *pPlayer, int weaponId) +{ + if (weaponId != CSI_SHIELDGUN) // This will be handled before with BuyItem. Avoiding duplicated call. + { + int player = PrivateToIndex(pvPlayer); + + if (MF_IsPlayerAlive(player) && MF_ExecuteForward(g_CSBuyCmdFwd, static_cast(player), static_cast(weaponId)) > 0) + { + return false; + } + } + + return DETOUR_STATIC_CALL(CanBuyThis)(pvPlayer, weaponId); +} + +DETOUR_DECL_STATIC2(BuyItem, void, void*, pvPlayer, int, iSlot) // void BuyItem(CBasePlayer *pPlayer, int iSlot) +{ + int player = PrivateToIndex(pvPlayer); + + if (MF_IsPlayerAlive(player)) + { + static const int itemSlotToWeaponId[] = {-1, CSI_VEST, CSI_VESTHELM, CSI_FLASHBANG, CSI_HEGRENADE, CSI_SMOKEGRENADE, CSI_NVGS, CSI_DEFUSER, CSI_SHIELDGUN}; + + if (iSlot >= 1 && iSlot <= 8 && MF_ExecuteForward(g_CSBuyCmdFwd, static_cast(player), static_cast(itemSlotToWeaponId[iSlot])) > 0) + { + return; + } + } + + DETOUR_STATIC_CALL(BuyItem)(pvPlayer, iSlot); +} + +DETOUR_DECL_STATIC3(BuyGunAmmo, bool, void*, pvPlayer, void*, pvWeapon, bool, bBlinkMoney) // bool BuyGunAmmo(CBasePlayer *player, CBasePlayerItem *weapon, bool bBlinkMoney) +{ + int player = PrivateToIndex(pvPlayer); + + if (MF_IsPlayerAlive(player)) + { + edict_t *pWeapon = PrivateToEdict(pvWeapon); + + if (pWeapon) + { + int weaponId = *((int *)pWeapon->pvPrivateData + OFFSET_WEAPONTYPE); + int ammoId = (1<(player), static_cast(ammoId)) > 0) + { + return false; + } + } + } + + return DETOUR_STATIC_CALL(BuyGunAmmo)(pvPlayer, pvWeapon, bBlinkMoney); +} + + +void CtrlDetours(bool set) { #if defined AMD64 #error UNSUPPORTED #endif - void *target = (void *)MDLL_ClientCommand; - - if (!g_UseBotArgs) + if (set) { -#if defined(__linux__) + char libName[256]; + uintptr_t base; + + void *target = (void *)MDLL_ClientCommand; + + if (!g_MemUtils.GetLibraryOfAddress(target, libName, sizeof(libName), &base)) + { + return; + } + +#if defined(WIN32) + + void *canBuyThisAddress = g_MemUtils.DecodeAndFindPattern(target, CS_SIG_CANBUYTHIS); + void *buyItemAddress = g_MemUtils.DecodeAndFindPattern(target, CS_SIG_BUYITEM); + void *buyGunAmmoAddress = g_MemUtils.DecodeAndFindPattern(target, CS_SIG_BUYGUNAMMO); + + g_UseBotArgs = *(int **)((unsigned char *)target + CS_CLICMD_OFFS_USEBOTARGS); + g_BotArgs = (const char **)*(const char **)((unsigned char *)target + CS_CLICMD_OFFS_BOTARGS); + +#elif defined(__linux__) + + void *canBuyThisAddress = g_MemUtils.ResolveSymbol(target, CS_SYM_CANBUYTHIS); + void *buyItemAddress = g_MemUtils.ResolveSymbol(target, CS_SYM_BUYITEM); + void *buyGunAmmoAddress = g_MemUtils.ResolveSymbol(target, CS_SYM_BUYGUNAMMO); g_UseBotArgs = (int *)g_MemUtils.ResolveSymbol(target, "UseBotArgs"); g_BotArgs = (const char **)g_MemUtils.ResolveSymbol(target, "BotArgs"); #elif defined(__APPLE__) - /* Using dlsym on OS X won't work because the symbols are hidden */ - char dll[256]; - uintptr_t base; - g_MemUtils.GetLibraryOfAddress(target, dll, sizeof(dll), &base); - - struct nlist symbols[3]; + struct nlist symbols[6]; memset(symbols, 0, sizeof(symbols)); - symbols[0].n_un.n_name = (char *)"_UseBotArgs"; - symbols[1].n_un.n_name = (char *)"_BotArgs"; - if (nlist(dll, symbols) != 0) - { - return; - } - g_UseBotArgs = (int *)(base + symbols[0].n_value); - g_BotArgs = (const char **)(base + symbols[1].n_value); -#elif defined(WIN32) + symbols[0].n_un.n_name = (char *)CS_SYM_CANBUYTHIS; + symbols[1].n_un.n_name = (char *)CS_SYM_BUYITEM; + symbols[2].n_un.n_name = (char *)CS_SYM_BUYGUNAMMO; + symbols[3].n_un.n_name = (char *)"_UseBotArgs"; + symbols[4].n_un.n_name = (char *)"_BotArgs"; - g_UseBotArgs = *(int **)((unsigned char *)target + CS_CLICMD_OFFS_USEBOTARGS); - g_BotArgs = (const char **)*(const char **)((unsigned char *)target + CS_CLICMD_OFFS_BOTARGS); + if (nlist(libName, symbols) != 0) { return; } + + void *canBuyThisAddress = (void *)(base + symbols[0].n_value); + void *buyItemAddress = (void *)(base + symbols[1].n_value); + void *buyGunAmmoAddress = (void *)(base + symbols[2].n_value); + void *g_UseBotArgs = (void *)(base + symbols[3].n_value); + void *g_BotArgs = (void *)(base + symbols[4].n_value); #endif - } - - if (set) - { - g_ClientCommandDetour = DETOUR_CREATE_STATIC_FIXED(C_ClientCommand, target); - + g_ClientCommandDetour = DETOUR_CREATE_STATIC_FIXED(C_ClientCommand, target); + g_CanBuyThisDetour = DETOUR_CREATE_STATIC_FIXED(CanBuyThis, canBuyThisAddress); + g_BuyItemDetour = DETOUR_CREATE_STATIC_FIXED(BuyItem, buyItemAddress); + g_BuyGunAmmoDetour = DETOUR_CREATE_STATIC_FIXED(BuyGunAmmo, buyGunAmmoAddress); + if (g_ClientCommandDetour != NULL) - { g_ClientCommandDetour->EnableDetour(); + else + { + MF_Log("No Client Commands detours could be initialized - Disabled Client Command forward."); + } + + if (g_CanBuyThisDetour != NULL && g_BuyItemDetour != NULL && g_BuyGunAmmoDetour != NULL) + { + g_CanBuyThisDetour->EnableDetour(); + g_BuyItemDetour->EnableDetour(); + g_BuyGunAmmoDetour->EnableDetour(); + } + else + { + MF_Log("No Buy Commands detours could be initialized - Disabled Buy forward."); } } else { + g_CanBuyThisDetour->Destroy(); + g_BuyItemDetour->Destroy(); + g_BuyGunAmmoDetour->Destroy(); g_ClientCommandDetour->Destroy(); } } diff --git a/dlls/cstrike/cstrike/CstrikeUtils.h b/dlls/cstrike/cstrike/CstrikeUtils.h index 0cdd0f95..6e60842b 100644 --- a/dlls/cstrike/cstrike/CstrikeUtils.h +++ b/dlls/cstrike/cstrike/CstrikeUtils.h @@ -84,4 +84,36 @@ void UTIL_TextMsg_Generic(edict_t* pPlayer, const char* message); #define GETEDICT(n) \ ((n >= 1 && n <= gpGlobals->maxClients) ? MF_GetPlayerEdict(n) : INDEXENT(n)) + +inline edict_t *PrivateToEdict(const void *pdata) +{ + if (!pdata) + { + return NULL; + } + + char *ptr = (char*)pdata; + ptr += 4; + entvars_t *pev = *(entvars_t **)ptr; + + if (!pev) + { + return NULL; + } + + return pev->pContainingEntity; +}; + +inline int PrivateToIndex(const void *pdata) +{ + edict_t *pEntity = PrivateToEdict(pdata); + + if (!pEntity) + { + return -1; + } + + return ENTINDEX(pEntity); +}; + #endif // CSTRIKE_UTILS_H \ No newline at end of file diff --git a/dlls/cstrike/cstrike/amxx_api.cpp b/dlls/cstrike/cstrike/amxx_api.cpp index 730ce81a..e190e4a5 100644 --- a/dlls/cstrike/cstrike/amxx_api.cpp +++ b/dlls/cstrike/cstrike/amxx_api.cpp @@ -33,7 +33,9 @@ #include "amxxmodule.h" extern AMX_NATIVE_INFO cstrikeNatives[]; + extern int g_CSCliCmdFwd; +extern int g_CSBuyCmdFwd; void InitializeHacks(); void ShutdownHacks(); @@ -57,6 +59,7 @@ void OnAmxxAttach() void OnPluginsLoaded() { g_CSCliCmdFwd = MF_RegisterForward("CS_InternalCommand", ET_STOP, FP_CELL, FP_STRING, FP_DONE); + g_CSBuyCmdFwd = MF_RegisterForward("CS_OnBuy", ET_STOP, FP_CELL, FP_CELL, FP_DONE); } void OnAmxxDetach() diff --git a/plugins/include/cstrike.inc b/plugins/include/cstrike.inc index 2c0e85a8..f8139107 100755 --- a/plugins/include/cstrike.inc +++ b/plugins/include/cstrike.inc @@ -343,6 +343,7 @@ native cs_set_c4_explode_time(index, Float:value); native bool:cs_get_c4_defusing(c4index); native cs_set_c4_defusing(c4index, bool:defusing); + /** * Called when CS internally fires a command to a player. It does this for a few * functions, most notably rebuy/autobuy functionality. This is also used to pass @@ -353,3 +354,52 @@ native cs_set_c4_defusing(c4index, bool:defusing); * @return PLUGIN_HANDLED to block, PLUGIN_CONTINUE for normal operation. */ forward CS_InternalCommand(id, const cmd[]); + + +/** + * The following constants are used with CS_OnBuy forward. + */ +#define CSI_P228 CSW_P228 +#define CSI_SCOUT CSW_SCOUT +#define CSI_HEGRENADE CSW_HEGRENADE +#define CSI_XM1014 CSW_XM1014 +#define CSI_C4 CSW_C4 +#define CSI_MAC10 CSW_MAC10 +#define CSI_AUG CSW_AUG +#define CSI_SMOKEGRENADE CSW_SMOKEGRENADE +#define CSI_ELITE CSW_ELITE +#define CSI_FIVESEVEN CSW_FIVESEVEN +#define CSI_UMP45 CSW_UMP45 +#define CSI_SG550 CSW_SG550 +#define CSI_GALI CSW_GALI +#define CSI_FAMAS CSW_FAMAS +#define CSI_USP CSW_USP +#define CSI_GLOCK18 CSW_GLOCK18 +#define CSI_AWP CSW_AWP +#define CSI_MP5NAVY CSW_MP5NAVY +#define CSI_M249 CSW_M249 +#define CSI_M3 CSW_M3 +#define CSI_M4A1 CSW_M4A1 +#define CSI_TMP CSW_TMP +#define CSI_G3SG1 CSW_G3SG1 +#define CSI_FLASHBANG CSW_FLASHBANG +#define CSI_DEAGLE CSW_DEAGLE +#define CSI_SG552 CSW_SG552 +#define CSI_AK47 CSW_AK47 +#define CSI_P90 CSW_P90 +#define CSI_SHIELDGUN CSW_SHIELDGUN +#define CSI_VEST CSW_VEST // Custom +#define CSI_VESTHELM CSW_VESTHELM // Custom +#define CSI_DEFUSER 33 // Custom +#define CSI_NVGS 34 // Custom +#define CSI_PRIMAMMO 36 // Custom +#define CSI_SECAMMO 37 // Custom + +/** + * Called when a player attempts to purchase an item. + * Return PLUGIN_CONTINUE to allow the purchase or return a higher action to deny. + * + * @param id Player index. + * @param item Item index, see CSI_* constants. + */ +forward CS_OnBuy(index, item); diff --git a/public/memtools/CDetour/detours.h b/public/memtools/CDetour/detours.h index 797cb1c8..dea92c42 100644 --- a/public/memtools/CDetour/detours.h +++ b/public/memtools/CDetour/detours.h @@ -56,6 +56,14 @@ ret name(void) ret (*name##_Actual)(p1type) = NULL; \ ret name(p1type p1name) +#define DETOUR_DECL_STATIC2(name, ret, p1type, p1name, p2type, p2name) \ +ret (*name##_Actual)(p1type, p2type) = NULL; \ +ret name(p1type p1name, p2type p2name) + +#define DETOUR_DECL_STATIC3(name, ret, p1type, p1name, p2type, p2name, p3type, p3name) \ +ret (*name##_Actual)(p1type, p2type, p3type) = NULL; \ +ret name(p1type p1name, p2type p2name, p3type p3name) + #define DETOUR_DECL_STATIC4(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name) \ ret (*name##_Actual)(p1type, p2type, p3type, p4type) = NULL; \ ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name) @@ -127,9 +135,9 @@ ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name #define GET_STATIC_CALLBACK(name) (void *)&name #define GET_STATIC_TRAMPOLINE(name) (void **)&name##_Actual -#define DETOUR_CREATE_MEMBER(name, gamedata, target) CDetourManager::CreateDetour(GET_MEMBER_CALLBACK(name), GET_MEMBER_TRAMPOLINE(name), gamedata, target); -#define DETOUR_CREATE_STATIC(name, gamedata, target) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), gamedata, target); -#define DETOUR_CREATE_STATIC_FIXED(name, address) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), address); +#define DETOUR_CREATE_MEMBER(name, gamedata, target) CDetourManager::CreateDetour(GET_MEMBER_CALLBACK(name), GET_MEMBER_TRAMPOLINE(name), gamedata, target); +#define DETOUR_CREATE_STATIC(name, gamedata, target) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), gamedata, target); +#define DETOUR_CREATE_STATIC_FIXED(name, address) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), address); class GenericClass {}; typedef void (GenericClass::*VoidFunc)(); diff --git a/public/memtools/MemoryUtils.cpp b/public/memtools/MemoryUtils.cpp index 843d0f6f..5226c3c3 100644 --- a/public/memtools/MemoryUtils.cpp +++ b/public/memtools/MemoryUtils.cpp @@ -29,6 +29,7 @@ #include "MemoryUtils.h" #include +#include #if defined(__linux__) #include @@ -63,8 +64,6 @@ #endif // MAC_OS_X_VERSION_10_6 #endif // __APPLE__ - - MemoryUtils g_MemUtils; MemoryUtils::MemoryUtils() @@ -103,6 +102,19 @@ MemoryUtils::~MemoryUtils() #endif } +void *MemoryUtils::DecodeAndFindPattern(const void *libPtr, const char *pattern) +{ + unsigned char real_sig[511]; + size_t real_bytes = DecodeHexString(real_sig, sizeof(real_sig), pattern); + + if (real_bytes >= 1) + { + return FindPattern(libPtr, (char*)real_sig, real_bytes); + } + + return NULL; +} + void *MemoryUtils::FindPattern(const void *libPtr, const char *pattern, size_t len) { DynLibInfo lib; @@ -655,3 +667,39 @@ bool MemoryUtils::GetLibraryOfAddress(const void *libPtr, char *buffer, size_t m return true; } +size_t MemoryUtils::DecodeHexString(unsigned char *buffer, size_t maxlength, const char *hexstr) +{ + size_t written = 0; + size_t length = strlen(hexstr); + + for (size_t i = 0; i < length; i++) + { + if (written >= maxlength) + break; + + buffer[written++] = hexstr[i]; + if (hexstr[i] == '\\' && hexstr[i + 1] == 'x') + { + if (i + 3 >= length) + continue; + + /* Get the hex part. */ + char s_byte[3]; + int r_byte; + s_byte[0] = hexstr[i + 2]; + s_byte[1] = hexstr[i + 3]; + s_byte[2] = '\0'; + + /* Read it as an integer */ + sscanf(s_byte, "%x", &r_byte); + + /* Save the value */ + buffer[written - 1] = r_byte; + + /* Adjust index */ + i += 3; + } + } + + return written; +} \ No newline at end of file diff --git a/public/memtools/MemoryUtils.h b/public/memtools/MemoryUtils.h index 1e7a5fdc..b7b49662 100644 --- a/public/memtools/MemoryUtils.h +++ b/public/memtools/MemoryUtils.h @@ -44,6 +44,10 @@ #include #endif +#if defined _MSC_VER && _MSC_VER >= 1400 + #pragma warning (disable:4996) /* Disable deprecation warnings */ +#endif + struct DynLibInfo { void *baseAddress; @@ -66,6 +70,7 @@ class MemoryUtils ~MemoryUtils(); public: + void *DecodeAndFindPattern(const void *libPtr, const char *pattern); void *FindPattern(const void *libPtr, const char *pattern, size_t len); void *ResolveSymbol(void *handle, const char *symbol); @@ -73,6 +78,9 @@ class MemoryUtils bool GetLibraryInfo(const void *libPtr, DynLibInfo &lib); bool GetLibraryOfAddress(const void *libPtr, char *buffer, size_t maxlength, uintptr_t *base); + public: + size_t DecodeHexString(unsigned char *buffer, size_t maxlength, const char *hexstr); + #if defined(__linux__) || defined(__APPLE__) private: ke::Vector m_SymTables; From 9d99863c7e4f33d1486f7784271a93258686a878 Mon Sep 17 00:00:00 2001 From: Arkshine Date: Fri, 30 May 2014 16:56:26 +0200 Subject: [PATCH 08/14] Cstrike: Add CSW_SHIELDGUN constant (valid CS value) --- plugins/include/amxconst.inc | 59 ++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/plugins/include/amxconst.inc b/plugins/include/amxconst.inc index 1f902d34..d9023957 100755 --- a/plugins/include/amxconst.inc +++ b/plugins/include/amxconst.inc @@ -77,38 +77,39 @@ /* Id of weapons in CS */ -#define CSW_P228 1 -#define CSW_SCOUT 3 +#define CSW_P228 1 +#define CSW_SCOUT 3 #define CSW_HEGRENADE 4 -#define CSW_XM1014 5 -#define CSW_C4 6 -#define CSW_MAC10 7 -#define CSW_AUG 8 -#define CSW_SMOKEGRENADE 9 -#define CSW_ELITE 10 +#define CSW_XM1014 5 +#define CSW_C4 6 +#define CSW_MAC10 7 +#define CSW_AUG 8 +#define CSW_SMOKEGRENADE 9 +#define CSW_ELITE 10 #define CSW_FIVESEVEN 11 -#define CSW_UMP45 12 -#define CSW_SG550 13 -#define CSW_GALI 14 -#define CSW_GALIL 14 -#define CSW_FAMAS 15 -#define CSW_USP 16 -#define CSW_GLOCK18 17 -#define CSW_AWP 18 -#define CSW_MP5NAVY 19 -#define CSW_M249 20 -#define CSW_M3 21 -#define CSW_M4A1 22 -#define CSW_TMP 23 -#define CSW_G3SG1 24 +#define CSW_UMP45 12 +#define CSW_SG550 13 +#define CSW_GALI 14 +#define CSW_GALIL 14 +#define CSW_FAMAS 15 +#define CSW_USP 16 +#define CSW_GLOCK18 17 +#define CSW_AWP 18 +#define CSW_MP5NAVY 19 +#define CSW_M249 20 +#define CSW_M3 21 +#define CSW_M4A1 22 +#define CSW_TMP 23 +#define CSW_G3SG1 24 #define CSW_FLASHBANG 25 -#define CSW_DEAGLE 26 -#define CSW_SG552 27 -#define CSW_AK47 28 -#define CSW_KNIFE 29 -#define CSW_P90 30 -#define CSW_VEST 31 -#define CSW_VESTHELM 32 +#define CSW_DEAGLE 26 +#define CSW_SG552 27 +#define CSW_AK47 28 +#define CSW_KNIFE 29 +#define CSW_P90 30 +#define CSW_VEST 31 // Custom +#define CSW_VESTHELM 32 // Custom +#define CSW_SHIELDGUN 99 #define HIW_BERETTA 1 #define HIW_SPAS12 2 From a984c85ffc8827a10203e075a4eedd8a36fa0a8b Mon Sep 17 00:00:00 2001 From: Arkshine Date: Fri, 30 May 2014 22:53:27 +0200 Subject: [PATCH 09/14] Cstrike: Define "UseBotArgs" and "BotArgs" symbols in game data file. --- dlls/cstrike/cstrike/CstrikeDatas.h | 14 +++++++++----- dlls/cstrike/cstrike/CstrikeHacks.cpp | 8 ++++---- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/dlls/cstrike/cstrike/CstrikeDatas.h b/dlls/cstrike/cstrike/CstrikeDatas.h index b4af6ceb..9884b4d0 100644 --- a/dlls/cstrike/cstrike/CstrikeDatas.h +++ b/dlls/cstrike/cstrike/CstrikeDatas.h @@ -146,13 +146,17 @@ #endif #if defined __linux__ -#define CS_DETOURCOPYBYTES_CLIENTCOMMAND 6 + #define CS_DETOURCOPYBYTES_CLIENTCOMMAND 6 + #define CS_SYM_USEBOTARGS "UseBotArgs" + #define CS_SYM_BOTARGS "BotArgs" #elif defined __APPLE__ -#define CS_DETOURCOPYBYTES_CLIENTCOMMAND 5 + #define CS_DETOURCOPYBYTES_CLIENTCOMMAND 5 + #define CS_SYM_USEBOTARGS "_UseBotArgs" + #define CS_SYM_BOTARGS "_BotArgs" #else -#define CS_DETOURCOPYBYTES_CLIENTCOMMAND 6 -#define CS_CLICMD_OFFS_USEBOTARGS 2 -#define CS_CLICMD_OFFS_BOTARGS 22 + #define CS_DETOURCOPYBYTES_CLIENTCOMMAND 6 + #define CS_CLICMD_OFFS_USEBOTARGS 2 + #define CS_CLICMD_OFFS_BOTARGS 22 #endif /** diff --git a/dlls/cstrike/cstrike/CstrikeHacks.cpp b/dlls/cstrike/cstrike/CstrikeHacks.cpp index 4fa01792..e58c6dce 100644 --- a/dlls/cstrike/cstrike/CstrikeHacks.cpp +++ b/dlls/cstrike/cstrike/CstrikeHacks.cpp @@ -169,8 +169,8 @@ void CtrlDetours(bool set) void *buyItemAddress = g_MemUtils.ResolveSymbol(target, CS_SYM_BUYITEM); void *buyGunAmmoAddress = g_MemUtils.ResolveSymbol(target, CS_SYM_BUYGUNAMMO); - g_UseBotArgs = (int *)g_MemUtils.ResolveSymbol(target, "UseBotArgs"); - g_BotArgs = (const char **)g_MemUtils.ResolveSymbol(target, "BotArgs"); + g_UseBotArgs = (int *)g_MemUtils.ResolveSymbol(target, CS_SYM_USEBOTARGS); + g_BotArgs = (const char **)g_MemUtils.ResolveSymbol(target, CS_SYM_BOTARGS); #elif defined(__APPLE__) @@ -180,8 +180,8 @@ void CtrlDetours(bool set) symbols[0].n_un.n_name = (char *)CS_SYM_CANBUYTHIS; symbols[1].n_un.n_name = (char *)CS_SYM_BUYITEM; symbols[2].n_un.n_name = (char *)CS_SYM_BUYGUNAMMO; - symbols[3].n_un.n_name = (char *)"_UseBotArgs"; - symbols[4].n_un.n_name = (char *)"_BotArgs"; + symbols[3].n_un.n_name = (char *)CS_SYM_USEBOTARGS; + symbols[4].n_un.n_name = (char *)CS_SYM_BOTARGS; if (nlist(libName, symbols) != 0) { return; } From f08a4f5a663fd2804e040274953fe33b04abb388 Mon Sep 17 00:00:00 2001 From: Arkshine Date: Sat, 31 May 2014 09:14:00 +0200 Subject: [PATCH 10/14] Cstrike: Fix typo under OSX. --- dlls/cstrike/cstrike/CstrikeHacks.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dlls/cstrike/cstrike/CstrikeHacks.cpp b/dlls/cstrike/cstrike/CstrikeHacks.cpp index e58c6dce..f3721f07 100644 --- a/dlls/cstrike/cstrike/CstrikeHacks.cpp +++ b/dlls/cstrike/cstrike/CstrikeHacks.cpp @@ -188,8 +188,8 @@ void CtrlDetours(bool set) void *canBuyThisAddress = (void *)(base + symbols[0].n_value); void *buyItemAddress = (void *)(base + symbols[1].n_value); void *buyGunAmmoAddress = (void *)(base + symbols[2].n_value); - void *g_UseBotArgs = (void *)(base + symbols[3].n_value); - void *g_BotArgs = (void *)(base + symbols[4].n_value); + g_UseBotArgs = (int *)(base + symbols[3].n_value); + g_BotArgs = (const char **)(base + symbols[4].n_value); #endif g_ClientCommandDetour = DETOUR_CREATE_STATIC_FIXED(C_ClientCommand, target); From c96456503c3a8f004cdbd2e6f0a9c154b380c18c Mon Sep 17 00:00:00 2001 From: Arkshine Date: Sat, 31 May 2014 20:06:26 +0200 Subject: [PATCH 11/14] Cstrike: Fix ResolveSymbol misuse under linux/osx. --- dlls/cstrike/cstrike/CstrikeDatas.h | 4 +-- dlls/cstrike/cstrike/CstrikeHacks.cpp | 45 ++++++++++++--------------- 2 files changed, 22 insertions(+), 27 deletions(-) diff --git a/dlls/cstrike/cstrike/CstrikeDatas.h b/dlls/cstrike/cstrike/CstrikeDatas.h index 9884b4d0..c7813928 100644 --- a/dlls/cstrike/cstrike/CstrikeDatas.h +++ b/dlls/cstrike/cstrike/CstrikeDatas.h @@ -151,8 +151,8 @@ #define CS_SYM_BOTARGS "BotArgs" #elif defined __APPLE__ #define CS_DETOURCOPYBYTES_CLIENTCOMMAND 5 - #define CS_SYM_USEBOTARGS "_UseBotArgs" - #define CS_SYM_BOTARGS "_BotArgs" + #define CS_SYM_USEBOTARGS "UseBotArgs" + #define CS_SYM_BOTARGS "BotArgs" #else #define CS_DETOURCOPYBYTES_CLIENTCOMMAND 6 #define CS_CLICMD_OFFS_USEBOTARGS 2 diff --git a/dlls/cstrike/cstrike/CstrikeHacks.cpp b/dlls/cstrike/cstrike/CstrikeHacks.cpp index f3721f07..70eadc23 100644 --- a/dlls/cstrike/cstrike/CstrikeHacks.cpp +++ b/dlls/cstrike/cstrike/CstrikeHacks.cpp @@ -154,42 +154,37 @@ void CtrlDetours(bool set) return; } + void *canBuyThisAddress = NULL; + void *buyItemAddress = NULL; + void *buyGunAmmoAddress = NULL; + #if defined(WIN32) - void *canBuyThisAddress = g_MemUtils.DecodeAndFindPattern(target, CS_SIG_CANBUYTHIS); - void *buyItemAddress = g_MemUtils.DecodeAndFindPattern(target, CS_SIG_BUYITEM); - void *buyGunAmmoAddress = g_MemUtils.DecodeAndFindPattern(target, CS_SIG_BUYGUNAMMO); + canBuyThisAddress = g_MemUtils.DecodeAndFindPattern(target, CS_SIG_CANBUYTHIS); + buyItemAddress = g_MemUtils.DecodeAndFindPattern(target, CS_SIG_BUYITEM); + buyGunAmmoAddress = g_MemUtils.DecodeAndFindPattern(target, CS_SIG_BUYGUNAMMO); g_UseBotArgs = *(int **)((unsigned char *)target + CS_CLICMD_OFFS_USEBOTARGS); g_BotArgs = (const char **)*(const char **)((unsigned char *)target + CS_CLICMD_OFFS_BOTARGS); -#elif defined(__linux__) +#elif defined(__linux__) || defined(__APPLE__) - void *canBuyThisAddress = g_MemUtils.ResolveSymbol(target, CS_SYM_CANBUYTHIS); - void *buyItemAddress = g_MemUtils.ResolveSymbol(target, CS_SYM_BUYITEM); - void *buyGunAmmoAddress = g_MemUtils.ResolveSymbol(target, CS_SYM_BUYGUNAMMO); + Dl_info info; + void *handle = NULL; - g_UseBotArgs = (int *)g_MemUtils.ResolveSymbol(target, CS_SYM_USEBOTARGS); - g_BotArgs = (const char **)g_MemUtils.ResolveSymbol(target, CS_SYM_BOTARGS); + if (dladdr(target, &info) == 0) || (handle = dlopen(info.dli_fname, RTLD_NOW)) == NULL) + { + return; + } -#elif defined(__APPLE__) + canBuyThisAddress = g_MemUtils.ResolveSymbol(handle, CS_SYM_CANBUYTHIS); + buyItemAddress = g_MemUtils.ResolveSymbol(handle, CS_SYM_BUYITEM); + buyGunAmmoAddress = g_MemUtils.ResolveSymbol(handle, CS_SYM_BUYGUNAMMO); - struct nlist symbols[6]; - memset(symbols, 0, sizeof(symbols)); + g_UseBotArgs = (int *)g_MemUtils.ResolveSymbol(handle, CS_SYM_USEBOTARGS); + g_BotArgs = (const char **)g_MemUtils.ResolveSymbol(handle, CS_SYM_BOTARGS); - symbols[0].n_un.n_name = (char *)CS_SYM_CANBUYTHIS; - symbols[1].n_un.n_name = (char *)CS_SYM_BUYITEM; - symbols[2].n_un.n_name = (char *)CS_SYM_BUYGUNAMMO; - symbols[3].n_un.n_name = (char *)CS_SYM_USEBOTARGS; - symbols[4].n_un.n_name = (char *)CS_SYM_BOTARGS; - - if (nlist(libName, symbols) != 0) { return; } - - void *canBuyThisAddress = (void *)(base + symbols[0].n_value); - void *buyItemAddress = (void *)(base + symbols[1].n_value); - void *buyGunAmmoAddress = (void *)(base + symbols[2].n_value); - g_UseBotArgs = (int *)(base + symbols[3].n_value); - g_BotArgs = (const char **)(base + symbols[4].n_value); + dlclose(handle); #endif g_ClientCommandDetour = DETOUR_CREATE_STATIC_FIXED(C_ClientCommand, target); From f1e206fde65652937bcadddf9b7e51808d5d1ff3 Mon Sep 17 00:00:00 2001 From: Arkshine Date: Sun, 1 Jun 2014 19:00:37 +0200 Subject: [PATCH 12/14] Cstrike: Refactor code to seperate detours for readability/maintainability + Fix OSX symbols. --- dlls/cstrike/cstrike/CstrikeDatas.h | 35 ++++++----- dlls/cstrike/cstrike/CstrikeHacks.cpp | 90 +++++++++++---------------- dlls/cstrike/cstrike/CstrikeUtils.cpp | 60 ++++++++++++++++++ dlls/cstrike/cstrike/CstrikeUtils.h | 1 + 4 files changed, 116 insertions(+), 70 deletions(-) diff --git a/dlls/cstrike/cstrike/CstrikeDatas.h b/dlls/cstrike/cstrike/CstrikeDatas.h index c7813928..168ce307 100644 --- a/dlls/cstrike/cstrike/CstrikeDatas.h +++ b/dlls/cstrike/cstrike/CstrikeDatas.h @@ -145,14 +145,16 @@ #define OFFSET_HOSTAGEID 516 + EXTRAOFFSET // +29 #endif -#if defined __linux__ +#if defined(__linux__) #define CS_DETOURCOPYBYTES_CLIENTCOMMAND 6 - #define CS_SYM_USEBOTARGS "UseBotArgs" - #define CS_SYM_BOTARGS "BotArgs" -#elif defined __APPLE__ + #define CS_IDENT_USEBOTARGS "UseBotArgs" + #define CS_IDENT_BOTARGS "BotArgs" + #define CS_IDENT_HIDDEN_STATE false +#elif defined(__APPLE__) #define CS_DETOURCOPYBYTES_CLIENTCOMMAND 5 - #define CS_SYM_USEBOTARGS "UseBotArgs" - #define CS_SYM_BOTARGS "BotArgs" + #define CS_IDENT_USEBOTARGS "UseBotArgs" + #define CS_IDENT_BOTARGS "BotArgs" + #define CS_IDENT_HIDDEN_STATE true #else #define CS_DETOURCOPYBYTES_CLIENTCOMMAND 6 #define CS_CLICMD_OFFS_USEBOTARGS 2 @@ -163,17 +165,20 @@ * CS_OnBuy forward */ #if defined(__linux__) - #define CS_SYM_CANBUYTHIS "_Z10CanBuyThisP11CBasePlayeri" - #define CS_SYM_BUYITEM "_Z7BuyItemP11CBasePlayeri" - #define CS_SYM_BUYGUNAMMO "_Z10BuyGunAmmoR11CBasePlayerR15CBasePlayerItemb" + #define CS_IDENT_CANBUYTHIS "_Z10CanBuyThisP11CBasePlayeri" + #define CS_IDENT_BUYITEM "_Z7BuyItemP11CBasePlayeri" + #define CS_IDENT_BUYGUNAMMO "_Z10BuyGunAmmoR11CBasePlayerR15CBasePlayerItemb" + #define CS_IDENT_HIDDEN_STATE false #elif defined(__APPLE__) - #define CS_SYM_CANBUYTHIS "__Z10CanBuyThisP11CBasePlayeri" - #define CS_SYM_BUYITEM "__Z7BuyItemP11CBasePlayeri" - #define CS_SYM_BUYGUNAMMO "__Z10BuyGunAmmoR11CBasePlayerR15CBasePlayerItemb" + #define CS_IDENT_CANBUYTHIS "_Z10CanBuyThisP11CBasePlayeri" + #define CS_IDENT_BUYITEM "_Z7BuyItemP11CBasePlayeri" + #define CS_IDENT_BUYGUNAMMO "_Z10BuyGunAmmoR11CBasePlayerR15CBasePlayerItemb" + #define CS_IDENT_HIDDEN_STATE true #elif defined(WIN32) - #define CS_SIG_CANBUYTHIS "\x53\x8B\x2A\x2A\x2A\x2A\x2A\x56\x8B\x2A\x2A\x2A\x57" - #define CS_SIG_BUYITEM "\x53\x56\x8B\x2A\x2A\x2A\xBB\x2A\x2A\x2A\x2A\x57\x53" - #define CS_SIG_BUYGUNAMMO "\x56\x57\x8B\x2A\x2A\x2A\x6A\x2A\x8B\x2A\xE8\x2A\x2A\x2A\x2A\x84\x2A\x0F" + #define CS_IDENT_CANBUYTHIS "\\x53\\x8B\\x2A\\x2A\\x2A\\x2A\\x2A\\x56\\x8B\\x2A\\x2A\\x2A\\x57" + #define CS_IDENT_BUYITEM "\\x53\\x56\\x8B\\x2A\\x2A\\x2A\\xBB\\x2A\\x2A\\x2A\\x2A\\x57\\x53" + #define CS_IDENT_BUYGUNAMMO "\\x56\\x57\\x8B\\x2A\\x2A\\x2A\\x6A\\x2A\\x8B\\x2A\\xE8\\x2A\\x2A\\x2A\\x2A\\x84\\x2A\\x0F" + #define CS_IDENT_HIDDEN_STATE false #endif #define CSI_P228 CSW_P228 diff --git a/dlls/cstrike/cstrike/CstrikeHacks.cpp b/dlls/cstrike/cstrike/CstrikeHacks.cpp index 70eadc23..0794a239 100644 --- a/dlls/cstrike/cstrike/CstrikeHacks.cpp +++ b/dlls/cstrike/cstrike/CstrikeHacks.cpp @@ -32,14 +32,10 @@ */ #include "CstrikeDatas.h" #include "CstrikeUtils.h" -#include #include "CDetour/detours.h" -#if defined(__APPLE__) - #include -#endif - -void CtrlDetours(bool set); +void CtrlDetours_ClientCommand(bool set); +void CtrlDetours_BuyCommands(bool set); int g_CSCliCmdFwd = -1; int g_CSBuyCmdFwd = -1; @@ -55,12 +51,18 @@ CDetour *g_BuyGunAmmoDetour = NULL; void InitializeHacks() { - CtrlDetours(true); +#if defined AMD64 + #error UNSUPPORTED +#endif + + CtrlDetours_ClientCommand(true); + CtrlDetours_BuyCommands(true); } void ShutdownHacks() { - CtrlDetours(false); + CtrlDetours_ClientCommand(false); + CtrlDetours_BuyCommands(false); } @@ -136,68 +138,47 @@ DETOUR_DECL_STATIC3(BuyGunAmmo, bool, void*, pvPlayer, void*, pvWeapon, bool, bB } -void CtrlDetours(bool set) +void CtrlDetours_ClientCommand(bool set) { -#if defined AMD64 - #error UNSUPPORTED -#endif - if (set) { - char libName[256]; - uintptr_t base; - void *target = (void *)MDLL_ClientCommand; - - if (!g_MemUtils.GetLibraryOfAddress(target, libName, sizeof(libName), &base)) - { - return; - } - - void *canBuyThisAddress = NULL; - void *buyItemAddress = NULL; - void *buyGunAmmoAddress = NULL; #if defined(WIN32) - canBuyThisAddress = g_MemUtils.DecodeAndFindPattern(target, CS_SIG_CANBUYTHIS); - buyItemAddress = g_MemUtils.DecodeAndFindPattern(target, CS_SIG_BUYITEM); - buyGunAmmoAddress = g_MemUtils.DecodeAndFindPattern(target, CS_SIG_BUYGUNAMMO); - g_UseBotArgs = *(int **)((unsigned char *)target + CS_CLICMD_OFFS_USEBOTARGS); g_BotArgs = (const char **)*(const char **)((unsigned char *)target + CS_CLICMD_OFFS_BOTARGS); #elif defined(__linux__) || defined(__APPLE__) - Dl_info info; - void *handle = NULL; - - if (dladdr(target, &info) == 0) || (handle = dlopen(info.dli_fname, RTLD_NOW)) == NULL) - { - return; - } - - canBuyThisAddress = g_MemUtils.ResolveSymbol(handle, CS_SYM_CANBUYTHIS); - buyItemAddress = g_MemUtils.ResolveSymbol(handle, CS_SYM_BUYITEM); - buyGunAmmoAddress = g_MemUtils.ResolveSymbol(handle, CS_SYM_BUYGUNAMMO); - - g_UseBotArgs = (int *)g_MemUtils.ResolveSymbol(handle, CS_SYM_USEBOTARGS); - g_BotArgs = (const char **)g_MemUtils.ResolveSymbol(handle, CS_SYM_BOTARGS); - - dlclose(handle); + g_UseBotArgs = (int *)UTIL_FindAddressFromEntry(CS_IDENT_USEBOTARGS, CS_IDENT_HIDDEN_STATE); + g_BotArgs = (const char **)UTIL_FindAddressFromEntry(CS_IDENT_BOTARGS, CS_IDENT_HIDDEN_STATE); #endif - g_ClientCommandDetour = DETOUR_CREATE_STATIC_FIXED(C_ClientCommand, target); - g_CanBuyThisDetour = DETOUR_CREATE_STATIC_FIXED(CanBuyThis, canBuyThisAddress); - g_BuyItemDetour = DETOUR_CREATE_STATIC_FIXED(BuyItem, buyItemAddress); - g_BuyGunAmmoDetour = DETOUR_CREATE_STATIC_FIXED(BuyGunAmmo, buyGunAmmoAddress); - + g_ClientCommandDetour = DETOUR_CREATE_STATIC_FIXED(C_ClientCommand, target); + if (g_ClientCommandDetour != NULL) g_ClientCommandDetour->EnableDetour(); else - { - MF_Log("No Client Commands detours could be initialized - Disabled Client Command forward."); - } + MF_Log("No Client Commands detour could be initialized - Disabled Client Command forward."); + } + else + { + g_ClientCommandDetour->Destroy(); + } +} + +void CtrlDetours_BuyCommands(bool set) +{ + if (set) + { + void *canBuyThisAddress = UTIL_FindAddressFromEntry(CS_IDENT_CANBUYTHIS, CS_IDENT_HIDDEN_STATE); + void *buyItemAddress = UTIL_FindAddressFromEntry(CS_IDENT_BUYITEM, CS_IDENT_HIDDEN_STATE); + void *buyGunAmmoAddress = UTIL_FindAddressFromEntry(CS_IDENT_BUYGUNAMMO, CS_IDENT_HIDDEN_STATE); + + g_CanBuyThisDetour = DETOUR_CREATE_STATIC_FIXED(CanBuyThis, canBuyThisAddress); + g_BuyItemDetour = DETOUR_CREATE_STATIC_FIXED(BuyItem, buyItemAddress); + g_BuyGunAmmoDetour = DETOUR_CREATE_STATIC_FIXED(BuyGunAmmo, buyGunAmmoAddress); if (g_CanBuyThisDetour != NULL && g_BuyItemDetour != NULL && g_BuyGunAmmoDetour != NULL) { @@ -212,9 +193,8 @@ void CtrlDetours(bool set) } else { - g_CanBuyThisDetour->Destroy(); g_BuyItemDetour->Destroy(); g_BuyGunAmmoDetour->Destroy(); g_ClientCommandDetour->Destroy(); } -} +} \ No newline at end of file diff --git a/dlls/cstrike/cstrike/CstrikeUtils.cpp b/dlls/cstrike/cstrike/CstrikeUtils.cpp index 3f8de77f..70218fe4 100644 --- a/dlls/cstrike/cstrike/CstrikeUtils.cpp +++ b/dlls/cstrike/cstrike/CstrikeUtils.cpp @@ -31,6 +31,7 @@ * version. */ #include "amxxmodule.h" +#include "MemoryUtils.h" bool UTIL_IsPlayer(AMX* amx, edict_t* pPlayer) { @@ -59,4 +60,63 @@ void UTIL_TextMsg_Generic(edict_t* pPlayer, const char* message) #define HUD_PRINTRADIO 5 However both 1 and 2 seems to go to console with Steam CS. */ +} + +void *UTIL_FindAddressFromEntry(const char *entry, bool isHidden, const char *library) +{ + void *addressInBase = NULL; + void *finalAddress; + + if (strcmp(library, "mod") == 0) + { + addressInBase = (void *)MDLL_Spawn; + } + else if (strcmp(library, "engine") == 0) + { + addressInBase = (void *)gpGlobals; + } + + finalAddress = NULL; + + if (*entry != '\\') + { +#if defined(WIN32) + + MEMORY_BASIC_INFORMATION mem; + + if (VirtualQuery(addressInBase, &mem, sizeof(mem))) + { + finalAddress = g_MemUtils.ResolveSymbol(mem.AllocationBase, entry); + } + +#elif defined(__linux__) || defined(__APPLE__) + + Dl_info info; + void *handle = NULL; + + if (dladdr(addressInBase, &info) != 0) + { + void *handle = dlopen(info.dli_fname, RTLD_NOW); + if (handle) + { + if (isHidden) + { + finalAddress = g_MemUtils.ResolveSymbol(handle, entry); + } + else + { + finalAddress = dlsym(handle, entry); + } + + dlclose(handle); + } + } +#endif + } + else + { + finalAddress = g_MemUtils.DecodeAndFindPattern(addressInBase, entry); + } + + return finalAddress != NULL ? finalAddress : NULL; } \ No newline at end of file diff --git a/dlls/cstrike/cstrike/CstrikeUtils.h b/dlls/cstrike/cstrike/CstrikeUtils.h index 6e60842b..443454ea 100644 --- a/dlls/cstrike/cstrike/CstrikeUtils.h +++ b/dlls/cstrike/cstrike/CstrikeUtils.h @@ -35,6 +35,7 @@ bool UTIL_IsPlayer(AMX* amx, edict_t* pPlayer); void UTIL_TextMsg_Generic(edict_t* pPlayer, const char* message); +void *UTIL_FindAddressFromEntry(const char *entry, bool isHidden = false, const char *library = "mod"); #define GETINFOKEYBUFFER (*g_engfuncs.pfnGetInfoKeyBuffer) #define SETCLIENTKEYVALUE (*g_engfuncs.pfnSetClientKeyValue) From d2f2748e9ed3eec02a1876adaa9de361ccc34e3c Mon Sep 17 00:00:00 2001 From: Arkshine Date: Sun, 1 Jun 2014 22:24:52 +0200 Subject: [PATCH 13/14] Cstrike: Enable/Disable detours whether CS_OnBuy and CS_InternalCommand are used in plugins + Add more check for safety. --- dlls/cstrike/cstrike/CstrikeHacks.cpp | 47 +++++++++++++++++++-------- dlls/cstrike/cstrike/CstrikeUtils.cpp | 20 ++++++++++++ dlls/cstrike/cstrike/CstrikeUtils.h | 1 + dlls/cstrike/cstrike/amxx_api.cpp | 7 ++++ 4 files changed, 61 insertions(+), 14 deletions(-) diff --git a/dlls/cstrike/cstrike/CstrikeHacks.cpp b/dlls/cstrike/cstrike/CstrikeHacks.cpp index 0794a239..e7703597 100644 --- a/dlls/cstrike/cstrike/CstrikeHacks.cpp +++ b/dlls/cstrike/cstrike/CstrikeHacks.cpp @@ -157,17 +157,25 @@ void CtrlDetours_ClientCommand(bool set) #endif g_ClientCommandDetour = DETOUR_CREATE_STATIC_FIXED(C_ClientCommand, target); - if (g_ClientCommandDetour != NULL) - g_ClientCommandDetour->EnableDetour(); - else + if (g_ClientCommandDetour == NULL) + { MF_Log("No Client Commands detour could be initialized - Disabled Client Command forward."); + } } else { - g_ClientCommandDetour->Destroy(); + if (g_ClientCommandDetour) + g_ClientCommandDetour->Destroy(); } } +void ToggleDetour_ClientCommands(bool enable) +{ + if (g_ClientCommandDetour) + (enable) ? g_ClientCommandDetour->EnableDetour() : g_ClientCommandDetour->DisableDetour(); +} + + void CtrlDetours_BuyCommands(bool set) { if (set) @@ -180,21 +188,32 @@ void CtrlDetours_BuyCommands(bool set) g_BuyItemDetour = DETOUR_CREATE_STATIC_FIXED(BuyItem, buyItemAddress); g_BuyGunAmmoDetour = DETOUR_CREATE_STATIC_FIXED(BuyGunAmmo, buyGunAmmoAddress); - if (g_CanBuyThisDetour != NULL && g_BuyItemDetour != NULL && g_BuyGunAmmoDetour != NULL) - { - g_CanBuyThisDetour->EnableDetour(); - g_BuyItemDetour->EnableDetour(); - g_BuyGunAmmoDetour->EnableDetour(); - } - else + if (g_CanBuyThisDetour == NULL || g_BuyItemDetour == NULL || g_BuyGunAmmoDetour == NULL) { MF_Log("No Buy Commands detours could be initialized - Disabled Buy forward."); } } else { - g_BuyItemDetour->Destroy(); - g_BuyGunAmmoDetour->Destroy(); - g_ClientCommandDetour->Destroy(); + if (g_CanBuyThisDetour) + g_CanBuyThisDetour->Destroy(); + + if (g_BuyItemDetour) + g_BuyItemDetour->Destroy(); + + if (g_BuyGunAmmoDetour) + g_BuyGunAmmoDetour->Destroy(); } +} + +void ToggleDetour_BuyCommands(bool enable) +{ + if (g_CanBuyThisDetour) + (enable) ? g_CanBuyThisDetour->EnableDetour() : g_CanBuyThisDetour->DisableDetour(); + + if (g_BuyItemDetour) + (enable) ? g_BuyItemDetour->EnableDetour() : g_BuyItemDetour->DisableDetour(); + + if (g_BuyGunAmmoDetour) + (enable) ? g_BuyGunAmmoDetour->EnableDetour() : g_BuyGunAmmoDetour->DisableDetour(); } \ No newline at end of file diff --git a/dlls/cstrike/cstrike/CstrikeUtils.cpp b/dlls/cstrike/cstrike/CstrikeUtils.cpp index 70218fe4..2c4fe6a3 100644 --- a/dlls/cstrike/cstrike/CstrikeUtils.cpp +++ b/dlls/cstrike/cstrike/CstrikeUtils.cpp @@ -119,4 +119,24 @@ void *UTIL_FindAddressFromEntry(const char *entry, bool isHidden, const char *li } return finalAddress != NULL ? finalAddress : NULL; +} + +bool UTIL_CheckForPublic(const char *publicname) +{ + AMX* amx; + int iFunctionIndex; + int i = 0; + char blah[64]; + + strncpy(blah, publicname, sizeof(blah)- 1); + + while ((amx = MF_GetScriptAmx(i++)) != NULL) + { + if (MF_AmxFindPublic(amx, blah, &iFunctionIndex) == AMX_ERR_NONE) + { + return true; + } + } + + return false; } \ No newline at end of file diff --git a/dlls/cstrike/cstrike/CstrikeUtils.h b/dlls/cstrike/cstrike/CstrikeUtils.h index 443454ea..ec2c7bc4 100644 --- a/dlls/cstrike/cstrike/CstrikeUtils.h +++ b/dlls/cstrike/cstrike/CstrikeUtils.h @@ -36,6 +36,7 @@ bool UTIL_IsPlayer(AMX* amx, edict_t* pPlayer); void UTIL_TextMsg_Generic(edict_t* pPlayer, const char* message); void *UTIL_FindAddressFromEntry(const char *entry, bool isHidden = false, const char *library = "mod"); +bool UTIL_CheckForPublic(const char *publicname); #define GETINFOKEYBUFFER (*g_engfuncs.pfnGetInfoKeyBuffer) #define SETCLIENTKEYVALUE (*g_engfuncs.pfnSetClientKeyValue) diff --git a/dlls/cstrike/cstrike/amxx_api.cpp b/dlls/cstrike/cstrike/amxx_api.cpp index e190e4a5..67088517 100644 --- a/dlls/cstrike/cstrike/amxx_api.cpp +++ b/dlls/cstrike/cstrike/amxx_api.cpp @@ -31,6 +31,7 @@ * version. */ #include "amxxmodule.h" +#include "CstrikeUtils.h" extern AMX_NATIVE_INFO cstrikeNatives[]; @@ -39,6 +40,9 @@ extern int g_CSBuyCmdFwd; void InitializeHacks(); void ShutdownHacks(); +void ToggleDetour_ClientCommands(bool enable); +void ToggleDetour_BuyCommands(bool enable); + int AmxxCheckGame(const char *game) { @@ -60,6 +64,9 @@ void OnPluginsLoaded() { g_CSCliCmdFwd = MF_RegisterForward("CS_InternalCommand", ET_STOP, FP_CELL, FP_STRING, FP_DONE); g_CSBuyCmdFwd = MF_RegisterForward("CS_OnBuy", ET_STOP, FP_CELL, FP_CELL, FP_DONE); + + ToggleDetour_ClientCommands(UTIL_CheckForPublic("CS_InternalCommand")); + ToggleDetour_BuyCommands(UTIL_CheckForPublic("CS_OnBuy")); } void OnAmxxDetach() From 2595fbe7648447c3c145faf14dfffcbb829aa93e Mon Sep 17 00:00:00 2001 From: Arkshine Date: Tue, 3 Jun 2014 10:05:56 +0200 Subject: [PATCH 14/14] Cstrike: Remove unused defines and fix typo. --- dlls/cstrike/cstrike/CstrikeDatas.h | 3 --- plugins/include/cstrike.inc | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/dlls/cstrike/cstrike/CstrikeDatas.h b/dlls/cstrike/cstrike/CstrikeDatas.h index 168ce307..d64c773e 100644 --- a/dlls/cstrike/cstrike/CstrikeDatas.h +++ b/dlls/cstrike/cstrike/CstrikeDatas.h @@ -146,17 +146,14 @@ #endif #if defined(__linux__) - #define CS_DETOURCOPYBYTES_CLIENTCOMMAND 6 #define CS_IDENT_USEBOTARGS "UseBotArgs" #define CS_IDENT_BOTARGS "BotArgs" #define CS_IDENT_HIDDEN_STATE false #elif defined(__APPLE__) - #define CS_DETOURCOPYBYTES_CLIENTCOMMAND 5 #define CS_IDENT_USEBOTARGS "UseBotArgs" #define CS_IDENT_BOTARGS "BotArgs" #define CS_IDENT_HIDDEN_STATE true #else - #define CS_DETOURCOPYBYTES_CLIENTCOMMAND 6 #define CS_CLICMD_OFFS_USEBOTARGS 2 #define CS_CLICMD_OFFS_BOTARGS 22 #endif diff --git a/plugins/include/cstrike.inc b/plugins/include/cstrike.inc index f8139107..2a8d4739 100755 --- a/plugins/include/cstrike.inc +++ b/plugins/include/cstrike.inc @@ -399,7 +399,7 @@ forward CS_InternalCommand(id, const cmd[]); * Called when a player attempts to purchase an item. * Return PLUGIN_CONTINUE to allow the purchase or return a higher action to deny. * - * @param id Player index. + * @param index Player index. * @param item Item index, see CSI_* constants. */ forward CS_OnBuy(index, item);