Advertisement
OvidiuS

Hook Module

Aug 30th, 2012
392
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.81 KB | None | 0 0
  1. #include <extdll.h>
  2. #include <meta_api.h>
  3. #include <stdarg.h>
  4. #include <cbase.h>
  5.  
  6. #ifdef __linux__
  7.     #include <sys/mman.h>
  8.     #include <malloc.h>
  9. #endif
  10.  
  11. #if _MSC_VER
  12.     #if _MSC_VER >= 1400
  13.         #define stricmp _stricmp
  14.     #endif
  15. #endif
  16.  
  17. #ifdef __linux__
  18.     #define stricmp strcasecmp
  19. #endif
  20.  
  21. #ifdef _WIN32
  22.     #define VirtFuncSpawn       0
  23.     #define VirtFuncTakeDamage  12
  24. #elif __linux__
  25.     #define VirtFuncSpawn       2
  26.     #define VirtFuncTakeDamage  14
  27. #endif
  28.  
  29. #ifdef _WIN32
  30.     #define PrivateToEdict(pPrivate) (*(entvars_t **)((char*)pPrivate + 4))->pContainingEntity
  31. #elif __linux__
  32.     #define PrivateToEdict(pPrivate) (*(entvars_t **)pPrivate)->pContainingEntity
  33. #endif
  34.  
  35. plugin_info_t Plugin_info =
  36. {
  37.     META_INTERFACE_VERSION,            // ifvers
  38.     "WPMG",                  // name
  39.     "Alpha",                        // version
  40.     "2011/11/7",                  // date
  41.     "WPMG Team",                     // author
  42.     "http://www.wpmg.ru",            // url
  43.     "WPMG",                  // logtag, all caps please
  44.     PT_ANYTIME,                     // (when) loadable
  45.     PT_ANYPAUSE                     // (when) unloadable
  46. };
  47.  
  48. meta_globals_t *gpMetaGlobals;
  49. mutil_funcs_t *gpMetaUtilFuncs;
  50. enginefuncs_t g_engfuncs;
  51. globalvars_t  *gpGlobals;
  52.  
  53. bool g_bActivated = false;
  54. bool g_bInitialized = false;
  55.  
  56. void *pOrigFuncSpawn = NULL;
  57. void *pOrigFuncTakeDamage = NULL;
  58.  
  59. void print_srvconsole(char *fmt, ...)
  60. {
  61.         va_list argptr;
  62.         static char string[384];
  63.         va_start(argptr, fmt);
  64.         vsnprintf(string, sizeof(string) - 1, fmt, argptr);
  65.         string[sizeof(string) - 1] = '\0';
  66.         va_end(argptr);
  67.        
  68.         SERVER_PRINT(string);
  69. }
  70.  
  71. #ifdef _WIN32
  72. void __fastcall HookSpawn(void *pthis)
  73. #elif __linux__
  74. void HookSpawn(void *pthis)
  75. #endif
  76. {
  77.     print_srvconsole("::Spawn(void) %d prehook!\n", ENTINDEX(PrivateToEdict(pthis)));
  78.  
  79. #ifdef _WIN32
  80.     reinterpret_cast<int (__fastcall *)(void *, int)>(pOrigFuncSpawn)(pthis, 0);
  81. #elif __linux__
  82.     reinterpret_cast<int (*)(void *)>(pOrigFuncSpawn)(pthis);
  83. #endif
  84.  
  85.     SERVER_PRINT("::Spawn(void) posthook!\n");
  86. }
  87.  
  88. #ifdef _WIN32
  89. int __fastcall HookTakeDamage(void *pthis, int i, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamage)
  90. #elif __linux__
  91. int HookTakeDamage(void *pthis, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamage)
  92. #endif
  93. {
  94.     SERVER_PRINT("::TakeDamage(int) prehook!\n");
  95.  
  96. #ifdef _WIN32
  97.     int iOrigRet = reinterpret_cast<int (__fastcall *)(void *, int, entvars_t *, entvars_t *, float, int)>(pOrigFuncTakeDamage)(pthis, 0, pevInflictor, pevAttacker, flDamage, bitsDamage);
  98. #elif __linux__
  99.     int iOrigRet = reinterpret_cast<int (*)(void *, entvars_t *, entvars_t *, float, int)>(pOrigFuncTakeDamage)(pthis, pevInflictor, pevAttacker, flDamage, bitsDamage);
  100. #endif
  101.  
  102.     SERVER_PRINT("::TakeDamage(int) posthook!\n");
  103.  
  104.     return iOrigRet;
  105. }
  106.  
  107. void MakeHookSpawn()
  108. {
  109.     edict_t *pEdict = CREATE_ENTITY();
  110.  
  111.     CALL_GAME_ENTITY(PLID, "player", &pEdict->v);
  112.    
  113.     if (pEdict->pvPrivateData == NULL)
  114.     {
  115.         REMOVE_ENTITY(pEdict);
  116.        
  117.         return;
  118.     }
  119.  
  120. #ifdef _WIN32
  121.     void **vtable = *((void***)((char*)pEdict->pvPrivateData));
  122. #elif __linux__
  123.     void **vtable = *((void***)(((char*)pEdict->pvPrivateData) + 0x94));
  124. #endif
  125.    
  126.     REMOVE_ENTITY(pEdict);
  127.    
  128.     if(vtable == NULL)
  129.         return;
  130.    
  131.     int **ivtable = (int **)vtable;
  132.    
  133.     pOrigFuncSpawn = (void *)ivtable[VirtFuncSpawn];
  134.    
  135. #ifdef _WIN32
  136.     DWORD OldFlags;
  137.  
  138.     VirtualProtect(&ivtable[VirtFuncSpawn], sizeof(int *), PAGE_READWRITE, &OldFlags);
  139. #elif __linux__
  140.     mprotect(&ivtable[VirtFuncSpawn], sizeof(int*), PROT_READ | PROT_WRITE);
  141. #endif
  142.  
  143.     ivtable[VirtFuncSpawn] = (int *)HookSpawn;
  144. }
  145.  
  146. void MakeHookTakeDamage()
  147. {
  148.     edict_t *pEdict = CREATE_ENTITY();
  149.  
  150.     CALL_GAME_ENTITY(PLID, "player", &pEdict->v);
  151.    
  152.     if (pEdict->pvPrivateData == NULL)
  153.     {
  154.         REMOVE_ENTITY(pEdict);
  155.        
  156.         return;
  157.     }
  158.  
  159. #ifdef _WIN32
  160.     void **vtable = *((void***)((char*)pEdict->pvPrivateData));
  161. #elif __linux__
  162.     void **vtable = *((void***)(((char*)pEdict->pvPrivateData) + 0x94));
  163. #endif
  164.  
  165.     REMOVE_ENTITY(pEdict);
  166.    
  167.     if(vtable == NULL)
  168.         return;
  169.    
  170.     int **ivtable = (int **)vtable;
  171.    
  172.     pOrigFuncTakeDamage = (void *)ivtable[VirtFuncTakeDamage];
  173.    
  174. #ifdef _WIN32
  175.     DWORD OldFlags;
  176.  
  177.     VirtualProtect(&ivtable[VirtFuncTakeDamage], sizeof(int *), PAGE_READWRITE, &OldFlags);
  178. #elif __linux__
  179.     mprotect(&ivtable[VirtFuncTakeDamage], sizeof(int*), PROT_READ | PROT_WRITE);
  180. #endif
  181.  
  182.     ivtable[VirtFuncTakeDamage] = (int *)HookTakeDamage;
  183. }
  184.  
  185. void ServerActivatePost(edict_t *pEdictList, int edictCount, int clientMax)
  186. {
  187.     if (g_bActivated)
  188.         RETURN_META(MRES_IGNORED);
  189.  
  190.     MakeHookSpawn();
  191.     MakeHookTakeDamage();
  192.  
  193.     g_bActivated = true;
  194.  
  195.     RETURN_META(MRES_IGNORED);
  196. }
  197.  
  198. void ServerDeactivatePost()
  199. {
  200.     if (!g_bInitialized)
  201.         RETURN_META(MRES_IGNORED);
  202.  
  203.     g_bInitialized = false;
  204.  
  205.     RETURN_META(MRES_IGNORED);
  206. }
  207.  
  208. void ClientCommandPost(edict_t *pEntity)
  209. {
  210.     const char *szArg;
  211.  
  212.     szArg = CMD_ARGV(0);
  213.  
  214.     if (stricmp(szArg, "say"))
  215.         RETURN_META(MRES_IGNORED);
  216.  
  217.     szArg = CMD_ARGV(1);
  218.  
  219.     if (stricmp(szArg, "/damage"))
  220.         RETURN_META(MRES_IGNORED);
  221.  
  222. #ifdef _WIN32
  223.     reinterpret_cast<int (__fastcall *)(void *, int, entvars_t *, entvars_t *, float, int)>((*((void***)((char*)pEntity->pvPrivateData)))[VirtFuncTakeDamage])(pEntity->pvPrivateData, 0, &(pEntity->v), &(pEntity->v), 50.0, DMG_SLASH);
  224. #elif defined __linux__
  225.     reinterpret_cast<int (*)(void *, entvars_t *, entvars_t *, float, int)>((*((void***)(((char*)pEntity->pvPrivateData) + 0x94)))[VirtFuncTakeDamage])(pEntity->pvPrivateData, &(pEntity->v), &(pEntity->v), 50.0, DMG_SLASH);
  226. #endif
  227.  
  228.     RETURN_META(MRES_IGNORED);
  229. }
  230.  
  231. int SpawnPre(edict_t *pEnt)
  232. {
  233.     if (g_bInitialized)
  234.         RETURN_META_VALUE(MRES_IGNORED, 0);
  235.  
  236.     g_bActivated = false;
  237.     g_bInitialized = true;
  238.  
  239.     RETURN_META_VALUE(MRES_IGNORED, 0);
  240. }
  241.  
  242. C_DLLEXPORT int Meta_Query(char *ifvers, plugin_info_t **pPlugInfo, mutil_funcs_t *pMetaUtilFuncs)
  243. {
  244.     gpMetaUtilFuncs = pMetaUtilFuncs;
  245.  
  246.     *pPlugInfo = &Plugin_info;
  247.  
  248.     return(TRUE);
  249. }
  250.  
  251. static META_FUNCTIONS gMetaFunctionTable;
  252. C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, meta_globals_t *pMGlobals, gamedll_funcs_t *pGamedllFuncs)
  253. {
  254.     gpMetaGlobals = pMGlobals;
  255.  
  256.     gMetaFunctionTable.pfnGetEntityAPI2 = GetEntityAPI2;
  257.     gMetaFunctionTable.pfnGetEntityAPI2_Post = GetEntityAPI2_Post;
  258.  
  259.     memcpy(pFunctionTable, &gMetaFunctionTable, sizeof(META_FUNCTIONS));
  260.    
  261.     return(TRUE);
  262. }
  263.  
  264. #ifdef __linux__
  265. // linux prototype
  266. C_DLLEXPORT void GiveFnptrsToDll(enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals)
  267. {
  268. #else
  269. #ifdef _MSC_VER
  270. // MSVC: Simulate __stdcall calling convention
  271. C_DLLEXPORT __declspec(naked) void GiveFnptrsToDll(enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals)
  272. {
  273.     __asm           // Prolog
  274.     {
  275.         // Save ebp
  276.         push        ebp
  277.         // Set stack frame pointer
  278.         mov         ebp, esp
  279.         // Allocate space for local variables
  280.         // The MSVC compiler gives us the needed size in __LOCAL_SIZE.
  281.         sub         esp, __LOCAL_SIZE
  282.         // Push registers
  283.         push        ebx
  284.         push        esi
  285.         push        edi
  286.     }
  287. #else   // _MSC_VER
  288. #ifdef __GNUC__
  289. // GCC can also work with this
  290. C_DLLEXPORT void __stdcall GiveFnptrsToDll(enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals)
  291. {
  292. #else   // __GNUC__
  293. // compiler not known
  294. #error There is no support (yet) for your compiler. Please use MSVC or GCC compilers or contact the AMX Mod X dev team.
  295. #endif  // __GNUC__
  296. #endif // _MSC_VER
  297. #endif // __linux__
  298.  
  299.     // ** Function core <--
  300.     memcpy(&g_engfuncs, pengfuncsFromEngine, sizeof(enginefuncs_t));
  301.     gpGlobals = pGlobals;
  302.     // --> ** Function core
  303.  
  304. #ifdef _MSC_VER
  305.     // Epilog
  306.     if (sizeof(int*) == 8)
  307.     {   // 64 bit
  308.         __asm
  309.         {
  310.             // Pop registers
  311.             pop edi
  312.             pop esi
  313.             pop ebx
  314.             // Restore stack frame pointer
  315.             mov esp, ebp
  316.             // Restore ebp
  317.             pop ebp
  318.             // 2 * sizeof(int*) = 16 on 64 bit
  319.             ret 16
  320.         }
  321.     }
  322.     else
  323.     {   // 32 bit
  324.         __asm
  325.         {
  326.             // Pop registers
  327.             pop edi
  328.             pop esi
  329.             pop ebx
  330.             // Restore stack frame pointer
  331.             mov esp, ebp
  332.             // Restore ebp
  333.             pop ebp
  334.             // 2 * sizeof(int*) = 8 on 32 bit
  335.             ret 8
  336.         }
  337.     }
  338. #endif // #ifdef _MSC_VER
  339. }
  340.  
  341. DLL_FUNCTIONS gFunctionTable;
  342. C_DLLEXPORT int GetEntityAPI2(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion)
  343. {
  344.     memset(&gFunctionTable, 0, sizeof(DLL_FUNCTIONS));
  345.  
  346.     gFunctionTable.pfnSpawn = SpawnPre;
  347.  
  348.     memcpy(pFunctionTable, &gFunctionTable, sizeof(DLL_FUNCTIONS));
  349.  
  350.     return 1;
  351. }
  352.  
  353. DLL_FUNCTIONS gFunctionTable_Post;
  354. C_DLLEXPORT int GetEntityAPI2_Post(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion)
  355. {
  356.     memset(&gFunctionTable_Post, 0, sizeof(DLL_FUNCTIONS));
  357.  
  358.     gFunctionTable_Post.pfnServerActivate = ServerActivatePost;
  359.     gFunctionTable_Post.pfnServerDeactivate = ServerDeactivatePost;
  360.     gFunctionTable_Post.pfnClientCommand = ClientCommandPost;
  361.  
  362.     memcpy(pFunctionTable, &gFunctionTable_Post, sizeof(DLL_FUNCTIONS));
  363.  
  364.     return 1;
  365. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement