Skip to content

Hook virtual functions by offset #617

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 30 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8284e52
feat: `CreateValveFunctionByOffset`
KillStr3aK Oct 9, 2024
679ce6c
feat: overloaded constructor
KillStr3aK Oct 9, 2024
73fe4ff
feat: now inherits from `MemoryFunction*`
KillStr3aK Oct 9, 2024
05fde7c
Merge branch 'main' into virtual-hooks
KillStr3aK Oct 11, 2024
3ddc0ba
Merge branch 'main' into virtual-hooks
KillStr3aK Oct 13, 2024
033d69a
Merge branch 'main' into virtual-hooks
KillStr3aK Oct 17, 2024
0f4b855
Merge branch 'main' into virtual-hooks
KillStr3aK Oct 17, 2024
077d1eb
Merge branch 'main' into virtual-hooks
KillStr3aK Oct 19, 2024
96489f3
Merge branch 'main' into virtual-hooks
KillStr3aK Oct 21, 2024
8d60cf9
Merge branch 'main' into virtual-hooks
KillStr3aK Nov 6, 2024
78639d4
Merge branch 'main' into virtual-hooks
KillStr3aK Nov 13, 2024
e56eb54
Merge branch 'main' into virtual-hooks
KillStr3aK Nov 26, 2024
dc87751
Merge branch 'main' into virtual-hooks
KillStr3aK Dec 3, 2024
d999bf1
Merge branch 'main' into virtual-hooks
KillStr3aK Jan 5, 2025
a385a67
Merge branch 'main' into virtual-hooks
KillStr3aK Jan 16, 2025
3764434
Merge branch 'main' into virtual-hooks
KillStr3aK Jan 25, 2025
21dac44
Merge branch 'main' into virtual-hooks
KillStr3aK Jan 27, 2025
9e09709
Merge branch 'main' into virtual-hooks
KillStr3aK Jan 30, 2025
f1703ec
Merge branch 'roflmuffin:main' into virtual-hooks
KillStr3aK May 10, 2025
d9dcb7e
fix: disambiguate virtual functions by offset
KillStr3aK May 10, 2025
a789b0f
chore: removed unused import
KillStr3aK May 10, 2025
4624aed
feat: CModule::FindVirtualTable
KillStr3aK May 12, 2025
415dace
feat: implemented new natives
KillStr3aK May 12, 2025
106c9cd
feat: vtables can now be accessed without an instance
KillStr3aK May 12, 2025
0006d03
feat: created example plugin
KillStr3aK May 12, 2025
cc16cf3
Merge branch 'main' into virtual-hooks
KillStr3aK May 12, 2025
2c28db9
fix: unhook correct method
KillStr3aK May 13, 2025
81f188b
tweak: removed symbol ctors from VTable<TClass>
KillStr3aK May 13, 2025
ab31593
feat: windows and linux implementation of CModule::FindVirtualTable
KillStr3aK May 15, 2025
048f86c
Merge branch 'virtual-hooks' of https://github.com/KillStr3aK/Counter…
KillStr3aK May 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ namespace CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;

public abstract class BaseMemoryFunction : NativeObject
{
private static Dictionary<string, IntPtr> _createdFunctions = new();
private static Dictionary<string, IntPtr> _createdFunctions = new();

private static Dictionary<IntPtr, Dictionary<int, IntPtr>> _createdOffsetFunctions = new();

private static IntPtr CreateValveFunctionBySignature(string signature, DataType returnType,
DataType[] argumentTypes)
Expand Down Expand Up @@ -45,6 +47,30 @@ private static IntPtr CreateValveFunctionBySignature(string signature, string bi
}

return function;
}

private static IntPtr CreateValveFunctionByOffset(IntPtr objectPtr, int offset, DataType returnType,
DataType[] argumentTypes)
{
if (!_createdOffsetFunctions.TryGetValue(objectPtr, out var createdFunctions))
{
createdFunctions = new Dictionary<int, IntPtr>();
_createdOffsetFunctions[objectPtr] = createdFunctions;
}

if (!createdFunctions.TryGetValue(offset, out var function))
{
try
{
function = NativeAPI.CreateVirtualFunction(objectPtr, offset,
argumentTypes.Length, (int)returnType, argumentTypes.Cast<object>().ToArray());
createdFunctions[offset] = function;
} catch (Exception)
{
}
}

return function;
}

public BaseMemoryFunction(string signature, DataType returnType, DataType[] parameters) : base(
Expand All @@ -55,6 +81,14 @@ public BaseMemoryFunction(string signature, DataType returnType, DataType[] para
public BaseMemoryFunction(string signature, string binarypath, DataType returnType, DataType[] parameters) : base(
CreateValveFunctionBySignature(signature, binarypath, returnType, parameters))
{
}

/// <summary>
/// <b>WARNING:</b> this is only supposed to be used with <see cref="VirtualFunctionVoid"/> and <see cref="VirtualFunctionWithReturn{TResult}"/>
/// </summary>
internal BaseMemoryFunction(IntPtr objectPtr, int offset, DataType returnType, DataType[] parameters) : base(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and related constructors are internal because they should not be used randomly. People should only use the exposed VirtualFunctionVoid and VirtualFunctionWithReturn versions

CreateValveFunctionByOffset(objectPtr, offset, returnType, parameters))
{
}

public void Hook(Func<DynamicHook, HookResult> handler, HookMode mode)
Expand All @@ -76,4 +110,4 @@ protected void InvokeInternalVoid(params object[] args)
{
NativeAPI.ExecuteVirtualFunction<object>(Handle, args);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
using System;
/*
* This file is part of CounterStrikeSharp.
* CounterStrikeSharp 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 3 of the License, or
* (at your option) any later version.
*
* CounterStrikeSharp 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 CounterStrikeSharp. If not, see <https://www.gnu.org/licenses/>. *
*/

namespace CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;

#pragma warning disable CS8601 // Possible null reference assignment.
#pragma warning disable CS8604 // Possible null reference argument.
#pragma warning disable CS8604 // Possible null reference argument.

public class MemoryFunctionVoid : BaseMemoryFunction
{
public MemoryFunctionVoid(string signature) : base(signature, DataType.DATA_TYPE_VOID, Array.Empty<DataType>())
Expand All @@ -13,14 +27,18 @@ public MemoryFunctionVoid(string signature) : base(signature, DataType.DATA_TYPE

public MemoryFunctionVoid(string signature, string binarypath) : base(signature, binarypath, DataType.DATA_TYPE_VOID, Array.Empty<DataType>())
{
}

internal MemoryFunctionVoid(IntPtr objectPtr, int offset) : base(objectPtr, offset, DataType.DATA_TYPE_VOID, Array.Empty<DataType>())
{
}

public void Invoke()
{
InvokeInternalVoid();
}
}
}

public class MemoryFunctionVoid<T1> : BaseMemoryFunction
{
public MemoryFunctionVoid(string signature) : base(signature, DataType.DATA_TYPE_VOID,
Expand All @@ -33,6 +51,11 @@ public MemoryFunctionVoid(string signature, string binarypath) : base(signature,
{
}

internal MemoryFunctionVoid(IntPtr objectPtr, int offset) : base(objectPtr, offset, DataType.DATA_TYPE_VOID,
new[] { typeof(T1).ToValidDataType() })
{
}

public void Invoke(T1 arg1)
{
InvokeInternalVoid(arg1);
Expand All @@ -51,6 +74,11 @@ public MemoryFunctionVoid(string signature, string binarypath) : base(signature,
{
}

internal MemoryFunctionVoid(IntPtr objectPtr, int offset) : base(objectPtr, offset, DataType.DATA_TYPE_VOID,
new[] { typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType() })
{
}

public void Invoke(T1 arg1, T2 arg2)
{
InvokeInternalVoid(arg1, arg2);
Expand All @@ -69,6 +97,11 @@ public MemoryFunctionVoid(string signature, string binarypath) : base(signature,
{
}

internal MemoryFunctionVoid(IntPtr objectPtr, int offset) : base(objectPtr, offset, DataType.DATA_TYPE_VOID,
new[] { typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(), typeof(T3).ToValidDataType() })
{
}

public void Invoke(T1 arg1, T2 arg2, T3 arg3)
{
InvokeInternalVoid(arg1, arg2, arg3);
Expand All @@ -95,12 +128,21 @@ public MemoryFunctionVoid(string signature, string binarypath) : base(signature,
{
}

internal MemoryFunctionVoid(IntPtr objectPtr, int offset) : base(objectPtr, offset, DataType.DATA_TYPE_VOID,
new[]
{
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(),
typeof(T3).ToValidDataType(), typeof(T4).ToValidDataType()
})
{
}

public void Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4)
{
InvokeInternalVoid(arg1, arg2, arg3, arg4);
}
}
}

public class MemoryFunctionVoid<T1, T2, T3, T4, T5> : BaseMemoryFunction
{
public MemoryFunctionVoid(string signature) : base(signature, DataType.DATA_TYPE_VOID,
Expand All @@ -123,6 +165,16 @@ public MemoryFunctionVoid(string signature, string binarypath) : base(signature,
{
}

internal MemoryFunctionVoid(IntPtr objectPtr, int offset) : base(objectPtr, offset, DataType.DATA_TYPE_VOID,
new[]
{
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(),
typeof(T3).ToValidDataType(), typeof(T4).ToValidDataType(),
typeof(T5).ToValidDataType()
})
{
}

public void Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
{
InvokeInternalVoid(arg1, arg2, arg3, arg4, arg5);
Expand Down Expand Up @@ -151,6 +203,16 @@ public MemoryFunctionVoid(string signature, string binarypath) : base(signature,
{
}

internal MemoryFunctionVoid(IntPtr objectPtr, int offset) : base(objectPtr, offset, DataType.DATA_TYPE_VOID,
new[]
{
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(),
typeof(T3).ToValidDataType(), typeof(T4).ToValidDataType(),
typeof(T5).ToValidDataType(), typeof(T6).ToValidDataType()
})
{
}

public void Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6)
{
InvokeInternalVoid(arg1, arg2, arg3, arg4, arg5, arg6);
Expand Down Expand Up @@ -181,6 +243,17 @@ public MemoryFunctionVoid(string signature, string binarypath) : base(signature,
{
}

internal MemoryFunctionVoid(IntPtr objectPtr, int offset) : base(objectPtr, offset, DataType.DATA_TYPE_VOID,
new[]
{
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(),
typeof(T3).ToValidDataType(), typeof(T4).ToValidDataType(),
typeof(T5).ToValidDataType(), typeof(T6).ToValidDataType(),
typeof(T7).ToValidDataType()
})
{
}

public void Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7)
{
InvokeInternalVoid(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
Expand Down Expand Up @@ -211,12 +284,23 @@ public MemoryFunctionVoid(string signature, string binarypath) : base(signature,
{
}

internal MemoryFunctionVoid(IntPtr objectPtr, int offset) : base(objectPtr, offset, DataType.DATA_TYPE_VOID,
new[]
{
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(),
typeof(T3).ToValidDataType(), typeof(T4).ToValidDataType(),
typeof(T5).ToValidDataType(), typeof(T6).ToValidDataType(),
typeof(T7).ToValidDataType(), typeof(T8).ToValidDataType()
})
{
}

public void Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8)
{
InvokeInternalVoid(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
}
}

public class MemoryFunctionVoid<T1, T2, T3, T4, T5, T6, T7, T8, T9> : BaseMemoryFunction
{
public MemoryFunctionVoid(string signature) : base(signature, DataType.DATA_TYPE_VOID,
Expand All @@ -243,6 +327,18 @@ public MemoryFunctionVoid(string signature, string binarypath) : base(signature,
{
}

internal MemoryFunctionVoid(IntPtr objectPtr, int offset) : base(objectPtr, offset, DataType.DATA_TYPE_VOID,
new[]
{
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(),
typeof(T3).ToValidDataType(), typeof(T4).ToValidDataType(),
typeof(T5).ToValidDataType(), typeof(T6).ToValidDataType(),
typeof(T7).ToValidDataType(), typeof(T8).ToValidDataType(),
typeof(T9).ToValidDataType()
})
{
}

public void Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9)
{
InvokeInternalVoid(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
Expand Down Expand Up @@ -275,11 +371,23 @@ public MemoryFunctionVoid(string signature, string binarypath) : base(signature,
{
}

internal MemoryFunctionVoid(IntPtr objectPtr, int offset) : base(objectPtr, offset, DataType.DATA_TYPE_VOID,
new[]
{
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(),
typeof(T3).ToValidDataType(), typeof(T4).ToValidDataType(),
typeof(T5).ToValidDataType(), typeof(T6).ToValidDataType(),
typeof(T7).ToValidDataType(), typeof(T8).ToValidDataType(),
typeof(T9).ToValidDataType(), typeof(T10).ToValidDataType()
})
{
}

public void Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10)
{
InvokeInternalVoid(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
}
}

#pragma warning restore CS8601 // Possible null reference assignment.
#pragma warning restore CS8604 // Possible null reference argument.
#pragma warning restore CS8604 // Possible null reference argument.
Loading
Loading