Skip to content

Instantly share code, notes, and snippets.

@M1kep
Last active January 16, 2024 06:57
Show Gist options
  • Save M1kep/b3f57971e83ea86d86581fbd17f4fe4b to your computer and use it in GitHub Desktop.
Save M1kep/b3f57971e83ea86d86581fbd17f4fe4b to your computer and use it in GitHub Desktop.
CS2 Force CVar Flag
using System.Diagnostics;
using System.Runtime.InteropServices;
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
namespace ConCommandTesting;
public class ConCommandTesting : BasePlugin
{
public override string ModuleName => "ConCommandTesting";
public override string ModuleVersion => "v1.0.0";
private static string serverDLLPath = @"D:\Games\cs2-ds\game\csgo\bin\win64\server.dll";
private static ProcessModule? serverModule;
// Look for "RegisterConCommand: Unknown error registering con command \"%s\"!\n" in server.dll
// This qword is the base used for calling RegisterConCommand in the while loop
// As of 1/15/2024 the linux offset is _probably_ 0x18CA7D8
private const int _CCVarOffset= 0x14B13F8;
public unsafe IntPtr GetCCvar()
{
IntPtr baseAddress = serverModule.BaseAddress;
Server.PrintToConsole($"BaseAddress: 0x{baseAddress:X}");
IntPtr absoluteAddress = IntPtr.Add(baseAddress, _CCVarOffset);
Server.PrintToConsole($"AbsoluteAddress: 0x{absoluteAddress:X}");
// Check if absoluteAddress is non-zero and potentially valid
if (absoluteAddress != IntPtr.Zero)
{
IntPtr* pointer = (IntPtr*)absoluteAddress.ToPointer();
IntPtr linkedListPtr = *pointer;
// Check if the dereferenced pointer is valid
if (linkedListPtr != IntPtr.Zero)
{
return linkedListPtr;
}
else
{
Server.PrintToConsole("Dereferenced CCvar pointer is null.");
}
}
else
{
Server.PrintToConsole("AbsoluteAddress is null.");
}
return IntPtr.Zero;
}
public override void Load(bool hotReload)
{
var currentProcess = Process.GetCurrentProcess();
serverModule = currentProcess.Modules.Cast<ProcessModule>()
.FirstOrDefault(module => module.FileName == serverDLLPath);
if (serverModule == null)
{
Server.PrintToConsole("Server Module is null");
return;
}
IntPtr ccvarPtr = GetCCvar();
IntPtr cvarListPtr = IntPtr.Add(ccvarPtr, 0x40);
IntPtr cvarList = Marshal.ReadIntPtr(cvarListPtr);
Int16 conCommandSize = Marshal.ReadInt16(ccvarPtr + 0xA0);
IntPtr startPtr = cvarList;
for (int i = 0; i < conCommandSize - 1; i++)
{
IntPtr cVarPtr = Marshal.ReadIntPtr(startPtr);
if (cVarPtr == IntPtr.Zero)
{
Server.PrintToConsole("Read CVarPtr is null.");
break;
}
IntPtr nameStringPtr = Marshal.ReadIntPtr(cVarPtr);
string cVarName = Marshal.PtrToStringAnsi(nameStringPtr);
if (cVarName == "sv_infinite_ammo")
{
Int64 cVarFlags = Marshal.ReadInt64(cVarPtr + 0x30);
// 8192 is supposed to be for REPLICATED, but seems something else is going on, or I'm just bad...
// Marshal.WriteInt64(cVarPtr + 0x30, cVarFlags & ~16384 & ~8192);
Marshal.WriteInt64(cVarPtr + 0x30, cVarFlags & ~16384);
// Int64 cVarFlagsPost = Marshal.ReadInt64(cVarPtr + 0x30);
// Server.PrintToConsole($"CVarFlagsPost: {cVarFlagsPost}");
// We changed what we wanted, break out of the loop
break;
}
startPtr = IntPtr.Add(startPtr, 0x10);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment