CDetour safetyhook (#2162)
* Add safetyhook, remove libudis86 Co-authored-by: bottiger1 <55270538+bottiger1@users.noreply.github.com> * Add modified CDetour Co-authored-by: bottiger1 <55270538+bottiger1@users.noreply.github.com> * Add CDetour [Safetyhook] to build script * Re-enable loader/core/corelogic, and fix new C++20 error * Reenable all extensions (except dhooks) * Make cstrike compile against new CDetour * Remove unused variable in sdktools output? * Make sdktools compile against new cdetour * Downgrade to C++17 * remove auto * fix compilation on linux * Re-enable dhooks * Re-authorise old compilers * Fix invalid downgrade of std::optional * readd libudis86 for dhooks only --------- Co-authored-by: Kenzzer <kenzzer@users.noreply.github.com> Co-authored-by: bottiger1 <55270538+bottiger1@users.noreply.github.com>
This commit is contained in:
parent
e3734803f0
commit
e07c120cab
@ -520,6 +520,16 @@ class SMConfig(object):
|
|||||||
|
|
||||||
return binary
|
return binary
|
||||||
|
|
||||||
|
def AddCDetour(self, binary):
|
||||||
|
public_path = os.path.join(builder.sourcePath, 'public')
|
||||||
|
binary.sources += [
|
||||||
|
os.path.join(public_path, 'CDetour', 'detours.cpp'),
|
||||||
|
os.path.join(public_path, 'safetyhook', 'safetyhook.cpp'),
|
||||||
|
os.path.join(public_path, 'safetyhook', 'Zydis.c')
|
||||||
|
]
|
||||||
|
binary.compiler.cxxincludes += [ os.path.join(public_path, 'safetyhook') ]
|
||||||
|
binary.compiler.includes += [ os.path.join(public_path, 'safetyhook') ]
|
||||||
|
|
||||||
def HL2Library(self, context, compiler, name, sdk):
|
def HL2Library(self, context, compiler, name, sdk):
|
||||||
binary = self.Library(context, compiler, name)
|
binary = self.Library(context, compiler, name)
|
||||||
self.ConfigureForExtension(context, binary.compiler)
|
self.ConfigureForExtension(context, binary.compiler)
|
||||||
|
@ -395,11 +395,6 @@ void CExtension::AddDependency(const IfaceInfo *pInfo)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator ==(const IfaceInfo &i1, const IfaceInfo &i2)
|
|
||||||
{
|
|
||||||
return (i1.iface == i2.iface) && (i1.owner == i2.owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CExtension::AddChildDependent(CExtension *pOther, SMInterface *iface)
|
void CExtension::AddChildDependent(CExtension *pOther, SMInterface *iface)
|
||||||
{
|
{
|
||||||
IfaceInfo info;
|
IfaceInfo info;
|
||||||
|
@ -59,7 +59,7 @@ namespace SourceMod
|
|||||||
|
|
||||||
struct IfaceInfo
|
struct IfaceInfo
|
||||||
{
|
{
|
||||||
bool operator ==(const IfaceInfo &info)
|
bool operator ==(const IfaceInfo &info) const
|
||||||
{
|
{
|
||||||
return (info.iface == iface && info.owner == owner);
|
return (info.iface == iface && info.owner == owner);
|
||||||
}
|
}
|
||||||
|
@ -9,15 +9,7 @@ project.sources += [
|
|||||||
'timeleft.cpp',
|
'timeleft.cpp',
|
||||||
'forwards.cpp',
|
'forwards.cpp',
|
||||||
'util_cstrike.cpp',
|
'util_cstrike.cpp',
|
||||||
'../../public/smsdk_ext.cpp',
|
'../../public/smsdk_ext.cpp'
|
||||||
'../../public/CDetour/detours.cpp',
|
|
||||||
'../../public/asm/asm.c',
|
|
||||||
'../../public/libudis86/decode.c',
|
|
||||||
'../../public/libudis86/itab.c',
|
|
||||||
'../../public/libudis86/syn-att.c',
|
|
||||||
'../../public/libudis86/syn-intel.c',
|
|
||||||
'../../public/libudis86/syn.c',
|
|
||||||
'../../public/libudis86/udis86.c',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
for sdk_name in ['css', 'csgo']:
|
for sdk_name in ['css', 'csgo']:
|
||||||
@ -34,6 +26,8 @@ for sdk_name in ['css', 'csgo']:
|
|||||||
|
|
||||||
cxx.defines += ['HAVE_STRING_H']
|
cxx.defines += ['HAVE_STRING_H']
|
||||||
binary = SM.HL2ExtConfig(project, builder, cxx, 'game.cstrike.ext.' + sdk['extension'], sdk)
|
binary = SM.HL2ExtConfig(project, builder, cxx, 'game.cstrike.ext.' + sdk['extension'], sdk)
|
||||||
|
SM.AddCDetour(binary)
|
||||||
|
|
||||||
if sdk_name == 'csgo':
|
if sdk_name == 'csgo':
|
||||||
compiler = binary.compiler
|
compiler = binary.compiler
|
||||||
compiler.cxxincludes += [os.path.join(sdk['path'], 'public', 'steam')]
|
compiler.cxxincludes += [os.path.join(sdk['path'], 'public', 'steam')]
|
||||||
|
@ -19,6 +19,7 @@ for cxx in builder.targets:
|
|||||||
binary.compiler.cxxincludes += [
|
binary.compiler.cxxincludes += [
|
||||||
os.path.join(SM.mms_root, 'core'),
|
os.path.join(SM.mms_root, 'core'),
|
||||||
os.path.join(SM.mms_root, 'core', 'sourcehook'),
|
os.path.join(SM.mms_root, 'core', 'sourcehook'),
|
||||||
|
os.path.join(builder.sourcePath, 'extensions', 'dhooks'),
|
||||||
os.path.join(builder.sourcePath, 'public', 'jit'),
|
os.path.join(builder.sourcePath, 'public', 'jit'),
|
||||||
os.path.join(builder.sourcePath, 'public', 'jit', 'x86'),
|
os.path.join(builder.sourcePath, 'public', 'jit', 'x86'),
|
||||||
os.path.join(builder.sourcePath, 'sourcepawn', 'include'),
|
os.path.join(builder.sourcePath, 'sourcepawn', 'include'),
|
||||||
@ -27,6 +28,10 @@ for cxx in builder.targets:
|
|||||||
os.path.join(builder.sourcePath, 'extensions', 'dhooks', 'DynamicHooks'),
|
os.path.join(builder.sourcePath, 'extensions', 'dhooks', 'DynamicHooks'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
binary.compiler.includes += [
|
||||||
|
os.path.join(builder.sourcePath, 'extensions', 'dhooks')
|
||||||
|
]
|
||||||
|
|
||||||
binary.sources += [
|
binary.sources += [
|
||||||
'extension.cpp',
|
'extension.cpp',
|
||||||
'listeners.cpp',
|
'listeners.cpp',
|
||||||
@ -36,13 +41,13 @@ for cxx in builder.targets:
|
|||||||
'util.cpp',
|
'util.cpp',
|
||||||
'dynhooks_sourcepawn.cpp',
|
'dynhooks_sourcepawn.cpp',
|
||||||
'../../public/smsdk_ext.cpp',
|
'../../public/smsdk_ext.cpp',
|
||||||
'../../public/asm/asm.c',
|
'asm/asm.c',
|
||||||
'../../public/libudis86/decode.c',
|
'libudis86/decode.c',
|
||||||
'../../public/libudis86/itab.c',
|
'libudis86/itab.c',
|
||||||
'../../public/libudis86/syn-att.c',
|
'libudis86/syn-att.c',
|
||||||
'../../public/libudis86/syn-intel.c',
|
'libudis86/syn-intel.c',
|
||||||
'../../public/libudis86/syn.c',
|
'libudis86/syn.c',
|
||||||
'../../public/libudis86/udis86.c',
|
'libudis86/udis86.c',
|
||||||
'../../sourcepawn/vm/x86/assembler-x86.cpp',
|
'../../sourcepawn/vm/x86/assembler-x86.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -24,15 +24,7 @@ project.sources += [
|
|||||||
'hooks.cpp',
|
'hooks.cpp',
|
||||||
'gamerulesnatives.cpp',
|
'gamerulesnatives.cpp',
|
||||||
'vstringtable.cpp',
|
'vstringtable.cpp',
|
||||||
'../../public/smsdk_ext.cpp',
|
'../../public/smsdk_ext.cpp'
|
||||||
'../../public/CDetour/detours.cpp',
|
|
||||||
'../../public/asm/asm.c',
|
|
||||||
'../../public/libudis86/decode.c',
|
|
||||||
'../../public/libudis86/itab.c',
|
|
||||||
'../../public/libudis86/syn-att.c',
|
|
||||||
'../../public/libudis86/syn-intel.c',
|
|
||||||
'../../public/libudis86/syn.c',
|
|
||||||
'../../public/libudis86/udis86.c',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
for sdk_name in SM.sdks:
|
for sdk_name in SM.sdks:
|
||||||
@ -45,18 +37,20 @@ for sdk_name in SM.sdks:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
binary = SM.HL2ExtConfig(project, builder, cxx, 'sdktools.ext.' + sdk['extension'], sdk)
|
binary = SM.HL2ExtConfig(project, builder, cxx, 'sdktools.ext.' + sdk['extension'], sdk)
|
||||||
|
SM.AddCDetour(binary)
|
||||||
|
|
||||||
binary.compiler.cxxincludes += [
|
binary.compiler.cxxincludes += [
|
||||||
os.path.join(builder.sourcePath, 'public', 'jit'),
|
os.path.join(builder.sourcePath, 'public', 'jit'),
|
||||||
os.path.join(builder.sourcePath, 'public', 'jit', 'x86'),
|
os.path.join(builder.sourcePath, 'public', 'jit', 'x86'),
|
||||||
]
|
]
|
||||||
|
|
||||||
if sdk['name'] in ('episode1', 'darkm'):
|
if sdk['name'] in ('episode1', 'darkm'):
|
||||||
binary.compiler.cxxincludes += [os.path.join(builder.options.hl2sdk_root, sdk['path'], 'game_shared')]
|
binary.compiler.cxxincludes += [os.path.join(sdk['path'], 'game_shared')]
|
||||||
binary.compiler.cxxincludes += [os.path.join(builder.options.hl2sdk_root, sdk['path'], 'dlls')]
|
binary.compiler.cxxincludes += [os.path.join(sdk['path'], 'dlls')]
|
||||||
else:
|
else:
|
||||||
binary.compiler.cxxincludes += [
|
binary.compiler.cxxincludes += [
|
||||||
os.path.join(builder.options.hl2sdk_root, sdk['path'], 'game', 'shared'),
|
os.path.join(sdk['path'], 'game', 'shared'),
|
||||||
os.path.join(builder.options.hl2sdk_root, sdk['path'], 'game', 'server'),
|
os.path.join(sdk['path'], 'game', 'server'),
|
||||||
]
|
]
|
||||||
|
|
||||||
#binary.sources += [os.path.join(builder.options.hl2sdk_root, sdk['path'], 'game', 'server', 'variant_t.cpp')]
|
#binary.sources += [os.path.join(builder.options.hl2sdk_root, sdk['path'], 'game', 'server', 'variant_t.cpp')]
|
||||||
|
@ -128,7 +128,6 @@ private:
|
|||||||
|
|
||||||
int HookCount;
|
int HookCount;
|
||||||
|
|
||||||
patch_t info_restore;
|
|
||||||
void *info_address;
|
void *info_address;
|
||||||
void *info_callback;
|
void *info_callback;
|
||||||
};
|
};
|
||||||
|
@ -8,6 +8,7 @@ if 'tf2' in SM.sdks:
|
|||||||
if not cxx.target.arch in sdk['platforms'][cxx.target.platform]:
|
if not cxx.target.arch in sdk['platforms'][cxx.target.platform]:
|
||||||
continue
|
continue
|
||||||
binary = SM.HL2Library(builder, cxx, 'game.tf2.ext.' + sdk['extension'], sdk)
|
binary = SM.HL2Library(builder, cxx, 'game.tf2.ext.' + sdk['extension'], sdk)
|
||||||
|
SM.AddCDetour(binary)
|
||||||
binary.sources += [
|
binary.sources += [
|
||||||
'extension.cpp',
|
'extension.cpp',
|
||||||
'natives.cpp',
|
'natives.cpp',
|
||||||
@ -18,15 +19,7 @@ if 'tf2' in SM.sdks:
|
|||||||
'teleporter.cpp',
|
'teleporter.cpp',
|
||||||
'gameplayrules.cpp',
|
'gameplayrules.cpp',
|
||||||
'conditions.cpp',
|
'conditions.cpp',
|
||||||
'../../public/smsdk_ext.cpp',
|
'../../public/smsdk_ext.cpp'
|
||||||
'../../public/CDetour/detours.cpp',
|
|
||||||
'../../public/asm/asm.c',
|
|
||||||
'../../public/libudis86/decode.c',
|
|
||||||
'../../public/libudis86/itab.c',
|
|
||||||
'../../public/libudis86/syn-att.c',
|
|
||||||
'../../public/libudis86/syn-intel.c',
|
|
||||||
'../../public/libudis86/syn.c',
|
|
||||||
'../../public/libudis86/udis86.c',
|
|
||||||
]
|
]
|
||||||
binary.compiler.defines += ['HAVE_STRING_H']
|
binary.compiler.defines += ['HAVE_STRING_H']
|
||||||
SM.extensions += [builder.Add(binary)]
|
SM.extensions += [builder.Add(binary)]
|
||||||
|
@ -1,92 +1,9 @@
|
|||||||
/**
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* 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 <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id: detours.cpp 248 2008-08-27 00:56:22Z pred $
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "detours.h"
|
#include "detours.h"
|
||||||
#include <asm/asm.h>
|
#include <cstdio>
|
||||||
|
|
||||||
ISourcePawnEngine *CDetourManager::spengine = NULL;
|
ISourcePawnEngine *CDetourManager::spengine = NULL;
|
||||||
IGameConfig *CDetourManager::gameconf = NULL;
|
IGameConfig *CDetourManager::gameconf = NULL;
|
||||||
|
|
||||||
// Push 64-bit value onto the stack using two instructions.
|
|
||||||
//
|
|
||||||
// Pushing 0xF00DF00DF00DF00D:
|
|
||||||
// push 0xF00DF00D
|
|
||||||
// mov [rsp+4], 0xF00DF00D
|
|
||||||
static inline void X64_Push_Imm64(JitWriter *jit, jit_int64_t val)
|
|
||||||
{
|
|
||||||
jit->write_ubyte(IA32_PUSH_IMM32);
|
|
||||||
jit->write_int32(jit_int32_t(val));
|
|
||||||
if ((val >> 32) != 0)
|
|
||||||
IA32_Mov_ESP_Disp8_Imm32(jit, 4, (val >> 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Jump to absolute 64-bit address using multiple instructions.
|
|
||||||
//
|
|
||||||
// Jumping to address 0xF00DF00DF00DF00D:
|
|
||||||
// push 0xF00DF00D
|
|
||||||
// mov [rsp+4], 0xF00DF00D
|
|
||||||
// ret
|
|
||||||
static inline void X64_Jump_Abs(JitWriter *jit, void *dest)
|
|
||||||
{
|
|
||||||
X64_Push_Imm64(jit, jit_int64_t(dest));
|
|
||||||
IA32_Return(jit);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void RelativeJump32(JitWriter *jit, void *target)
|
|
||||||
{
|
|
||||||
jitoffs_t call = IA32_Jump_Imm32(jit, 0);
|
|
||||||
IA32_Write_Jump32_Abs(jit, call, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_WIN64) || defined(__x86_64__)
|
|
||||||
static inline bool IsShortJump(JitWriter *jit, void *target)
|
|
||||||
{
|
|
||||||
int64_t diff = int64_t(target) - (int64_t(jit->outbase) + jit->get_outputpos() + OP_JMP_SIZE);
|
|
||||||
int32_t upperBits = (diff >> 32);
|
|
||||||
return upperBits == 0 || upperBits == -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline void AbsJump(JitWriter *jit, void *target)
|
|
||||||
{
|
|
||||||
#if defined(_WIN64) || defined(__x86_64__)
|
|
||||||
if (IsShortJump(jit, target))
|
|
||||||
RelativeJump32(jit, target);
|
|
||||||
else
|
|
||||||
X64_Jump_Abs(jit, target);
|
|
||||||
#else
|
|
||||||
RelativeJump32(jit, target);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDetourManager::Init(ISourcePawnEngine *spengine, IGameConfig *gameconf)
|
void CDetourManager::Init(ISourcePawnEngine *spengine, IGameConfig *gameconf)
|
||||||
{
|
{
|
||||||
CDetourManager::spengine = spengine;
|
CDetourManager::spengine = spengine;
|
||||||
@ -95,196 +12,101 @@ void CDetourManager::Init(ISourcePawnEngine *spengine, IGameConfig *gameconf)
|
|||||||
|
|
||||||
CDetour *CDetourManager::CreateDetour(void *callbackfunction, void **trampoline, const char *signame)
|
CDetour *CDetourManager::CreateDetour(void *callbackfunction, void **trampoline, const char *signame)
|
||||||
{
|
{
|
||||||
CDetour *detour = new CDetour(callbackfunction, trampoline, signame);
|
void* pAddress;
|
||||||
if (detour)
|
if (!gameconf->GetMemSig(signame, &pAddress))
|
||||||
{
|
{
|
||||||
if (!detour->Init(spengine, gameconf))
|
g_pSM->LogError(myself, "Signature for %s not found in gamedata", signame);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pAddress)
|
||||||
|
{
|
||||||
|
g_pSM->LogError(myself, "Sigscan for %s failed", signame);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CreateDetour(callbackfunction, trampoline, pAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
CDetour *CDetourManager::CreateDetour(void *callbackFunction, void **trampoline, void *pAddress)
|
||||||
|
{
|
||||||
|
CDetour* detour = new CDetour(callbackFunction, trampoline, pAddress);
|
||||||
|
|
||||||
|
auto result = safetyhook::InlineHook::create(pAddress, callbackFunction, safetyhook::InlineHook::Flags::StartDisabled);
|
||||||
|
if(result)
|
||||||
|
{
|
||||||
|
detour->m_hook = std::move(result.value());
|
||||||
|
*trampoline = detour->m_hook.original<void*>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto err = result.error();
|
||||||
|
switch(err.type)
|
||||||
{
|
{
|
||||||
delete detour;
|
case safetyhook::InlineHook::Error::BAD_ALLOCATION:
|
||||||
return NULL;
|
if(err.allocator_error == safetyhook::Allocator::Error::BAD_VIRTUAL_ALLOC)
|
||||||
|
{
|
||||||
|
g_pSM->LogError(myself, "BAD_VIRTUAL_ALLOC hook %p", pAddress);
|
||||||
|
}
|
||||||
|
else if(err.allocator_error == safetyhook::Allocator::Error::NO_MEMORY_IN_RANGE)
|
||||||
|
{
|
||||||
|
g_pSM->LogError(myself, "NO_MEMORY_IN_RANGE hook %p", pAddress);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_pSM->LogError(myself, "BAD_ALLOCATION hook %p errnum %i", pAddress, err.allocator_error);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case safetyhook::InlineHook::Error::FAILED_TO_DECODE_INSTRUCTION:
|
||||||
|
g_pSM->LogError(myself, "FAILED_TO_DECODE_INSTRUCTION hook %p ip %p", pAddress, err.ip);
|
||||||
|
break;
|
||||||
|
case safetyhook::InlineHook::Error::SHORT_JUMP_IN_TRAMPOLINE:
|
||||||
|
g_pSM->LogError(myself, "SHORT_JUMP_IN_TRAMPOLINE hook %p ip %p", pAddress, err.ip);
|
||||||
|
break;
|
||||||
|
case safetyhook::InlineHook::Error::IP_RELATIVE_INSTRUCTION_OUT_OF_RANGE:
|
||||||
|
g_pSM->LogError(myself, "IP_RELATIVE_INSTRUCTION_OUT_OF_RANGE hook %p ip %p", pAddress, err.ip);
|
||||||
|
break;
|
||||||
|
case safetyhook::InlineHook::Error::UNSUPPORTED_INSTRUCTION_IN_TRAMPOLINE:
|
||||||
|
g_pSM->LogError(myself, "UNSUPPORTED_INSTRUCTION_IN_TRAMPOLINE hook %p ip %p", pAddress, err.ip);
|
||||||
|
break;
|
||||||
|
case safetyhook::InlineHook::Error::FAILED_TO_UNPROTECT:
|
||||||
|
g_pSM->LogError(myself, "FAILED_TO_UNPROTECT hook %p ip %p", pAddress, err.ip);
|
||||||
|
break;
|
||||||
|
case safetyhook::InlineHook::Error::NOT_ENOUGH_SPACE:
|
||||||
|
g_pSM->LogError(myself, "NOT_ENOUGH_SPACE hook %p ip %p", pAddress, err.ip);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_pSM->LogError(myself, "Unknown error %i hook %p ip %p", err.type, pAddress, err.ip);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return detour;
|
delete detour;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return detour;
|
||||||
}
|
}
|
||||||
|
|
||||||
CDetour *CDetourManager::CreateDetour(void *callbackfunction, void **trampoline, void *pAddress)
|
CDetour::CDetour(void* callbackFunction, void **trampoline, void *pAddress)
|
||||||
{
|
{
|
||||||
CDetour *detour = new CDetour(callbackfunction, trampoline, pAddress);
|
|
||||||
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;
|
|
||||||
spengine = NULL;
|
|
||||||
gameconf = NULL;
|
|
||||||
this->trampoline = trampoline;
|
|
||||||
}
|
|
||||||
|
|
||||||
CDetour::CDetour(void*callbackfunction, void **trampoline, void *pAddress)
|
|
||||||
{
|
|
||||||
enabled = false;
|
|
||||||
detoured = false;
|
|
||||||
detour_address = pAddress;
|
|
||||||
detour_trampoline = NULL;
|
|
||||||
this->signame = NULL;
|
|
||||||
this->detour_callback = callbackfunction;
|
|
||||||
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()
|
bool CDetour::IsEnabled()
|
||||||
{
|
{
|
||||||
return enabled;
|
return m_hook.enabled();
|
||||||
}
|
|
||||||
|
|
||||||
bool CDetour::CreateDetour()
|
|
||||||
{
|
|
||||||
if (signame)
|
|
||||||
{
|
|
||||||
if (!gameconf->GetMemSig(signame, &detour_address))
|
|
||||||
{
|
|
||||||
g_pSM->LogError(myself, "Signature for %s not found in gamedata", signame);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!detour_address)
|
|
||||||
{
|
|
||||||
g_pSM->LogError(myself, "Sigscan for %s failed", signame);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!detour_address)
|
|
||||||
{
|
|
||||||
g_pSM->LogError(myself, "Invalid function address passed for detour");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_WIN64) || defined(__x86_64__)
|
|
||||||
int shortBytes = copy_bytes((unsigned char *)detour_address, NULL, OP_JMP_SIZE);
|
|
||||||
detour_restore.bytes = copy_bytes((unsigned char *)detour_address, NULL, X64_ABS_SIZE);
|
|
||||||
#else
|
|
||||||
detour_restore.bytes = copy_bytes((unsigned char *)detour_address, NULL, OP_JMP_SIZE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JitWriter wr;
|
|
||||||
JitWriter *jit = ≀
|
|
||||||
jit_uint32_t CodeSize = 0;
|
|
||||||
|
|
||||||
wr.outbase = NULL;
|
|
||||||
wr.outptr = NULL;
|
|
||||||
|
|
||||||
jit_rewind:
|
|
||||||
|
|
||||||
/* Patch old bytes in */
|
|
||||||
if (wr.outbase != NULL)
|
|
||||||
{
|
|
||||||
#if defined(_WIN64) || defined(__x86_64__)
|
|
||||||
wr.outptr += shortBytes;
|
|
||||||
bool isShort = IsShortJump(jit, detour_address);
|
|
||||||
wr.outptr -= shortBytes;
|
|
||||||
if (isShort)
|
|
||||||
detour_restore.bytes = shortBytes;
|
|
||||||
#endif
|
|
||||||
/* Save restore bits */
|
|
||||||
memcpy(detour_restore.patch, detour_address, detour_restore.bytes);
|
|
||||||
|
|
||||||
copy_bytes((unsigned char *)detour_address, (unsigned char*)wr.outptr, detour_restore.bytes);
|
|
||||||
}
|
|
||||||
wr.outptr += detour_restore.bytes;
|
|
||||||
|
|
||||||
/* Return to the original function */
|
|
||||||
AbsJump(jit, (unsigned char *)detour_address + detour_restore.bytes);
|
|
||||||
|
|
||||||
if (wr.outbase == NULL)
|
|
||||||
{
|
|
||||||
CodeSize = wr.get_outputpos();
|
|
||||||
wr.outbase = (jitcode_t)spengine->AllocatePageMemory(CodeSize);
|
|
||||||
spengine->SetReadWrite(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 */
|
|
||||||
spengine->FreePageMemory(detour_trampoline);
|
|
||||||
detour_trampoline = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDetour::EnableDetour()
|
void CDetour::EnableDetour()
|
||||||
{
|
{
|
||||||
if (!detoured)
|
m_hook.enable();
|
||||||
{
|
|
||||||
DoGatePatch((unsigned char *)detour_address, detour_callback);
|
|
||||||
detoured = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDetour::DisableDetour()
|
void CDetour::DisableDetour()
|
||||||
{
|
{
|
||||||
if (detoured)
|
m_hook.disable();
|
||||||
{
|
|
||||||
/* Remove the patch */
|
|
||||||
ApplyPatch(detour_address, 0, &detour_restore, NULL);
|
|
||||||
detoured = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CDetour::Destroy()
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
@ -32,18 +32,8 @@
|
|||||||
#ifndef _INCLUDE_SOURCEMOD_DETOURS_H_
|
#ifndef _INCLUDE_SOURCEMOD_DETOURS_H_
|
||||||
#define _INCLUDE_SOURCEMOD_DETOURS_H_
|
#define _INCLUDE_SOURCEMOD_DETOURS_H_
|
||||||
|
|
||||||
#include "extension.h"
|
#include "../safetyhook/safetyhook.hpp"
|
||||||
#include <jit/jit_helpers.h>
|
#include <smsdk_ext.h>
|
||||||
#include <jit/x86/x86_macros.h>
|
|
||||||
#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_MEMBER_CALL(name) (this->*name##_Actual)
|
||||||
#define DETOUR_STATIC_CALL(name) (name##_Actual)
|
#define DETOUR_STATIC_CALL(name) (name##_Actual)
|
||||||
@ -220,32 +210,9 @@ public:
|
|||||||
friend class CDetourManager;
|
friend class CDetourManager;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CDetour(void *callbackfunction, void **trampoline, const char *signame);
|
|
||||||
CDetour(void*callbackfunction, void **trampoline, void *pAddress);
|
CDetour(void*callbackfunction, void **trampoline, void *pAddress);
|
||||||
|
|
||||||
bool Init(ISourcePawnEngine *spengine, IGameConfig *gameconf);
|
|
||||||
private:
|
private:
|
||||||
|
SafetyHookInline m_hook{};
|
||||||
/* 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;
|
|
||||||
ISourcePawnEngine *spengine;
|
|
||||||
IGameConfig *gameconf;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CDetourManager
|
class CDetourManager
|
||||||
@ -293,10 +260,9 @@ public:
|
|||||||
*
|
*
|
||||||
* Note we changed the netadr_s reference into a void* to avoid needing to define the type
|
* 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, const char *signame);
|
||||||
static CDetour *CreateDetour(void *callbackfunction, void **trampoline, void *pAddress);
|
static CDetour *CreateDetour(void *callbackFunction, void **trampoline, void *pAddress);
|
||||||
|
|
||||||
friend class CBlocker;
|
|
||||||
friend class CDetour;
|
friend class CDetour;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -304,4 +270,4 @@ private:
|
|||||||
static IGameConfig *gameconf;
|
static IGameConfig *gameconf;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _INCLUDE_SOURCEMOD_DETOURS_H_
|
#endif // _INCLUDE_SOURCEMOD_DETOURS_H_
|
54198
public/safetyhook/Zydis.c
Normal file
54198
public/safetyhook/Zydis.c
Normal file
File diff suppressed because one or more lines are too long
11885
public/safetyhook/Zydis.h
Normal file
11885
public/safetyhook/Zydis.h
Normal file
File diff suppressed because it is too large
Load Diff
2444
public/safetyhook/expected.hpp
Normal file
2444
public/safetyhook/expected.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1731
public/safetyhook/safetyhook.cpp
Normal file
1731
public/safetyhook/safetyhook.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1153
public/safetyhook/safetyhook.hpp
Normal file
1153
public/safetyhook/safetyhook.hpp
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user